2016-01-18 31 views
1

我正在执行的尾部功能,我只是应该使用read(),write()lseek() I/O,到目前为止,我有这样的:打印最后10行文件或标准输入读写和lseek

int printFileLines(int fileDesc) 
{ 
    char c; 
    int lineCount = 0, charCount = 0; 
    int pos = 0, rState; 
    while(pos != -1 && lineCount < 10) 
    { 
     if((rState = read(fileDesc, &c, 1)) < 0) 
     { 
      perror("read:"); 
     } 
     else if(rState == 0) break; 
     else 
     { 
      if(pos == -1) 
      { 
       pos = lseek(fileDesc, 0, SEEK_END); 
      } 
      pos--; 
      pos=lseek(fileDesc, pos, SEEK_SET); 
      if (c == '\n') 
      { 
       lineCount++; 
      } 
      charCount++; 
     } 
    } 

    if (lineCount >= 10) 
     lseek(fileDesc, 2, SEEK_CUR); 
    else 
     lseek(fileDesc, 0, SEEK_SET); 

    char *lines = malloc(charCount - 1 * sizeof(char)); 

    read(fileDesc, lines, charCount); 
    lines[charCount - 1] = 10; 
    write(STDOUT_FILENO, lines, charCount); 

    return 0; 
} 

到目前为止,它适用于有超过10行的文件,但刹车时,我经过不到10行的文件,它只是打印该文件的最后一行,我可以”让它与stdin一起工作。 如果有人可以给我一个想法如何解决这个问题,那简直太好了:d

回答

2

第一个问题:

如果你读到这里换行...

if(read(fileDesc, &c, 1) < 0) 
{ 
    perror("read:"); 
} 

...然后直接设置位置到前述该换行符字符...

pos--; 
pos=lseek(fileDesc, pos, SEEK_SET); 

然后linecount>= 10(while循环终止),则读取的第一个字符是最后一个换行符之前的最后一个字符。换行符本身也不是最后10行的一部分,所以只是空两个字符从当前流位置上:

if (linecount >= 10) 
    lseek(fileDesc, 2, SEEK_CUR); 

对于第二个问题:

让我们假设,该流偏置值已经到达了流的开始:

pos--; 
pos=lseek(fileDesc, pos, SEEK_SET); // pos is now 0 

的,而条件仍是TRUE:

while(pos != -1 && lineCount < 10) 

现在读取一个字符。在此之后,文件偏移是(第二个字符):

if(read(fileDesc, &c, 1) < 0) 
{ 
    perror("read:"); 
} 

这里,POS下降到-1和lseek的将失败

pos--; 
pos=lseek(fileDesc, pos, SEEK_SET); 

由于lseek的失败时,在文件中的位置现在是第二个字符,因此缺少第一个字符。通过重置文件的while循环之后偏移如果pos == -1文件的开始修复此:

if (linecount >= 10) 
    lseek(fileDesc, 2, SEEK_CUR); 
else 
    lseek(fileDesc, 0, SEEK_SET); 

性能:

这需要很多的系统调用。一个简单的增强将使用缓冲f *功能:

FILE *f = fdopen(fileDesc, "r"); 
fseek(...); 
fgetc(...); 

等此外,这不需要系统特定的功能。

更好的是按块读取文件反向块并在这些块上进行操作,但这需要更多的编码工作。

对于Unix,您也可以使用mmap()整个文件并在内存中向后搜索换行符。

+0

谢谢!!!!!!!!我一直在挣扎几个小时!关于表演的记录,我甚至不会使用这些功能,但这个该死的任务人... – Reaper9806

相关问题