2014-11-14 56 views
0

我试图读取一个文件与1024行,每行9次相同的字母和返回,如果它发现一行不符合这个条款。C函数读取(文件,缓冲区,字节读取)打破一个字符串

的文件是如下但1024线:

eeeeeeeee 
eeeeeeeee 
eeeeeeeee 

代码:

fd = open(fileName, O_RDONLY); 
lseek(fd,0,SEEK_SET); 


if(flock(fd, LOCK_SH) == -1) 
     perror("error on file lock"); 

if(fd != 0){ 

    read(fd, lineFromFile, (sizeof(char)*10)); 
    arguments->charRead = lineFromFile[0]; 

    for(i=0; i < 1024; i++){   
     var = read(fd, toReadFromFile, (sizeof(char)*10)); 
     if(strncmp(toReadFromFile,lineFromFile,10) != 0 || var < 10){   

      arguments->result = -1; 
      printf("%s \n\n",toReadFromFile); 
      printf("%s \n",lineFromFile); 
      printf("i %d var %d \n",i,var);     
      free(toReadFromFile); 
      free(lineFromFile); 
      return ; 
     }      
    } 
} 

输出:

> eeeee 
eeee 

eeeee 
eeee 
i 954 var 6 

我有5个不同的文件和不同的字母,每个单独的文件在这个特定的行(954)中给出了这个输出,并且该行对于最后用\ n书写了9次的字母是正确的。

任何想法,为什么会发生这种情况?如果我不使用lseek它可以正常工作,但我需要lseek将文件分成若干部分,以便通过不同的线程进行测试。我把lseek中的0索引简化为向你们展示。

谢谢。

+0

如果你正在尝试使用'与fgets(读取由行的文本文件行倒不如让库函数做的工作适合你)'或'fscanf()'。而不是使用'fseek()',每个线程可以在它感兴趣的人之前简单地丢弃任何行。另一条路线可以是将整个10k文件(它不是很大,并且你知道它的大小)读入所有可用的静态存储器线程,让他们都检查相同的副本。 – 2014-11-14 18:18:42

+0

当您从中读取文件时,您的其他线程之一是否正在对您的文件执行lseek?你应该把'lseek'移到你锁定文件的地方。这样,一旦你锁定了,你就只能'查看'。 – JS1 2014-11-14 18:20:20

+0

问题是,由于我已经有了使用线程读取整个文件的其他程序,因此这个新程序需要共享相同的文件才能更快地进行测试,而且我的老师说它必须使用lseek()和read()。我不明白它是如何工作的大部分线路,只是在特定的路线失败。没有意义。 – 2014-11-14 18:27:10

回答

1

它看起来像你正在寻找"eeeee\neeee",而不是"eeeeeeeee\n"。这意味着你的文件应该应该这样开始:

eeeee 
eeeeeeeee 
eeeeeeeee 

,并最终像这样:

eeeeeeeee 
eeee 

如果你的文件结尾是这样的:

eeeeeeeee 
eeeeeeeee 

然后,当你到了最后行,它将失败,因为您只会阅读"eeeee\n"而不是"eeeee\neeee"

鉴于您评论中的新信息,我认为问题在于您不应该寻找到行的中间位置(本例中为342和684)。你应该寻求预期的字符串的偶数倍(如340和680)。另外,第954行不是发生问题的地方。它应该是954 + X行,其中X是你寻找的行。

+0

但它在954行失败,最后一行是1024.如果我使用3个线程与以下lseeks:lseek(fd,0,SEEk_SET)lseek(fd,342,SEEk_SET)lseek(fd,684,SEEk_SET) - 前两个是成功的,最后一个失败的是第954行。 如果它开始于eeeee,它不应该失败的前2个线程?或者只在1024行失败? – 2014-11-14 18:50:27

+1

有趣。你为什么寻求342和684?你不应该寻求可以被10整除的补偿吗?另外,您不应该在文件中查看第954行。您应该查看X + 954行,其中X是您寻找的行。在你的情况下,你找到68行的中间,所以问题发生在68 + 954 = 1022行,或者1023,如果第一行是第一行。 – JS1 2014-11-14 18:55:40

+0

你是对的:DI改变了并保存了从lseek像这样: 'newIndex = lseek(fd,arguments-> startLineIndex * 10,SEEK_SET);''for(i = newIndex/10; i < arguments-> finishLineIndex; i ++)'谢谢 – 2014-11-14 19:12:51

1

无论你的程序有什么其他问题,它肯定有这样的:read()函数不保证读取请求的全部字节数。除非遇到错误或文件末尾,否则它将读取至少一个文件,并且在很多情况下它会读取请求的全部字节数,但即使在文件结尾之前剩余的字节数足够多,也可以读取read()更少的字节比请求。

催促您使用更高级别功能的注释已被充分考虑,但如果您出于某种原因有义务使用read(),则必须注意读取的字节数少于请求数的情况,并通过阅读额外的字节到缓冲区未使用的尾端。可能多次。

在函数形式,可能看起来像这样的:

int read_all(int fd, char buf[], int num_to_read) { 
    int total_read = 0; 
    int n_read = 0; 

    while (total_read < num_to_read) { 
     n_read = read(fd, buf + total_read, num_to_read - total_read); 
     if (n_read > 0) { 
      total_read += n_read; 
     } else { 
      break; 
     } 
    } 

    return (n_read < 0) ? n_read : total_read; 
} 
+0

已经解决了,不过谢谢。我真的需要使用lseek来做这个。 – 2014-11-14 19:17:44

+0

您可能确实需要使用'lseek()',但这并不意味着您不需要执行我所描述的操作。即使你的计划到目前为止没有给你预期的结果,依靠它总是这样做是不安全的。 – 2014-11-14 19:30:47