C-函数读取(文件、缓冲区、要读取的字节)中断字符串
我试图读取一个1024行的文件,每行包含9倍的相同字母,如果它发现一行与这个术语不匹配,就会返回 文件如下,但有1024行:C-函数读取(文件、缓冲区、要读取的字节)中断字符串,c,pthreads,lseek,C,Pthreads,Lseek,我试图读取一个1024行的文件,每行包含9倍的相同字母,如果它发现一行与这个术语不匹配,就会返回 文件如下,但有1024行: eeeeeeeee eeeeeeeee eeeeeeeee > eeeee eeee eeeee eeee i 954 var 6 代码: fd = open(fileName, O_RDONLY); lseek(fd,0,SEEK_SET); if(flock(fd, LOCK_SH) == -1) perror("error on
eeeeeeeee
eeeeeeeee
eeeeeeeee
> eeeee
eeee
eeeee
eeee
i 954 var 6
代码:
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 ;
}
}
}
我有5个具有不同字母的不同文件,每个文件都在该特定行(954)中给出此输出,该行正确,字母写了9次,最后有一个\n
你知道为什么会这样吗?如果我不使用lseek,它可以正常工作,但是我需要lseek将文件分成几个部分,由不同的线程进行测试。我将0索引放在lseek中,以便于简化,从而向大家展示
谢谢。看起来您要找的是
“eeeee\neeee”
而不是“eeeeeee\n”
。这意味着您的文件应该如下所示开始:
eeeee
eeeeeeeee
eeeeeeeee
eeeeeeeee
eeee
eeeeeeeee
eeeeeeeee
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;
}
最后是这样的:
eeeee
eeeeeeeee
eeeeeeeee
eeeeeeeee
eeee
eeeeeeeee
eeeeeeeee
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;
}
如果文件的结尾如下所示:
eeeee
eeeeeeeee
eeeeeeeee
eeeeeeeee
eeee
eeeeeeeee
eeeeeeeee
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;
}
然后当您到达最后一行时,它将失败,因为您将只读取“eeeee\n”
,而不是“eeeee\neeee”
考虑到您评论中的新信息,我认为问题在于您不应该寻求中间路线(在本例中为342和684)。您应该寻求期望字符串的偶数倍(如340和680)。此外,第954行不是问题发生的地方。它应该是954+X行,其中X是您要查找的行。无论您的程序可能有什么其他问题,它肯定有以下问题:
read()
函数不能保证读取请求的全部字节数。除非遇到错误或文件结尾,否则它将至少读取一个,并且在许多情况下,它确实读取请求的完整字节数,但即使在文件结尾之前还有足够的字节,read()
读取的字节数也可能少于请求的字节数
敦促您改用更高级别函数的注释是经过深思熟虑的,但是如果出于某种原因您必须使用read()
,那么您必须注意读取的字节数少于请求的字节数的情况,并通过向未使用的缓冲区尾部读取额外的字节来处理这些情况。可能多次
在函数形式中,可能如下所示:
eeeee
eeeeeeeee
eeeeeeeee
eeeeeeeee
eeee
eeeeeeeee
eeeeeeeee
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;
}
int read_all(int fd,char buf[],int num_to_read){
int total_read=0;
int n_read=0;
while(总读取数<总读取数){
n_read=读取(fd,buf+总读取,num_to_read-总读取);
如果(n_读取>0){
总读取次数+=n次读取;
}否则{
打破
}
}
返回值(n\u读取<0)?n\u读取:总读取;
}
如果您试图逐行读取文本文件,最好让库函数通过使用fgets()
或fscanf()
为您完成这项工作。每个线程不必使用fseek()。另一种方法是将整个10k文件(不是很大,你知道它的大小)读入所有线程可用的静态内存中,让它们都检查同一个副本。可能是因为你从文件中读取时,你的另一个线程正在对你的文件执行lseek
?您应该将lseek
向下移动到锁定文件的位置下方。这样一来,一旦你有了锁,你就只能lseek
。问题是,因为我已经有其他程序使用读取整个文件的线程,这个新程序需要共享同一个文件才能更快地测试它,我的老师说必须使用lseek()和read()。我不明白它怎么能适用于大多数生产线,却在特定的生产线失败。没有意义。您是否在所有线程中共享相同的fd
?或者你是在每个线程调用open
一次吗?我将lseek移动到锁后,它也会这样做。我在每个线程上使用一个open
,但在第954行失败,最后一行是1024。如果我对以下lseek使用3个线程:lseek(fd,0,SEEk_SET)lseek(fd,342,SEEk_SET)lseek(fd,684,SEEk_SET)-前两个线程成功,最后一个线程在第954行失败。如果它是从EEEE开始的,那么前两个线程不应该失败吗?还是只在第1024行失败?很有趣。你为什么要找342和684?你不应该寻求可以被10整除的偏移量吗?另外,您不应该查看文件中的第954行。你应该看X+954行,其中X是你要找的线。在您的例子中,您搜索到了第68行的中间,因此问题发生在第68+954=1022行,或者如果第一行是第1行,则出现在第1023行。您是对的:我更改了for并保存了lseek的返回,如下所示:newIndex=lseek(fd,arguments->startineIndex*10,SEEK\u SET)代码>for(i=newIndex/10;ifinishLineIndex;i++)
Thanksalready solved,但还是要谢谢你。我真的需要使用lseek来完成这一步。您可能确实需要使用lseek()
,但这并不意味着您也不需要执行我描述的操作。即使到目前为止,你的程序碰巧给了你预期的结果,但总是依赖它来实现这一点是不安全的。