我正在调用这些函数:
unsigned blah[5];
lseek(0, 100, SEEK_CUR);
read(0, blah, sizeof(blah));
和
FILE *fr;
fr = fopen(arg[1], "r");
unsigned blah[5];
fseek(fr, 100, SEEK_CUR);
fread(blah, 1, sizeof(blah), fr);
我运行第一个代码运行此命令:
cat TEXTFILE | ./a.out
我运行第二个代码运行此命令:
./a.out TEXTFILE
然而,我得到了不同的结果。虽然第一个搜索正确,所以它读取正确的文本,第二个不是。我想使用第二种格式,那么我做错了什么?
答案 0 :(得分:5)
通过添加open(filename,O_RDONLY);
调用第一个示例,两者都适合我。我怀疑你的问题是因为呼叫lseek(0, 100, SEEK_CUR);
,它要求对标准输入进行搜索。你不能总是寻求标准 - 如果你有:
cat file | ./my_program
然后标准输入是一个fifo,你不能寻求。如果我在我的系统上执行此操作,请通过返回-1
并使用“非法搜索”错误来查找失败。这可能是您遇到的问题,您可能没有注意到,因为您没有在示例中检查搜索调用的返回值。
请注意,如果您有:
./my_program < file
然后标准输入是一个文件,您可以寻求。在我的系统上,搜索返回100
,输出正确。
这是一个可用于说明返回值的程序:
int main(void){
int fd = 0;
char blah[5];
printf("Seek moved to this position: %d\n",lseek(fd, 100, SEEK_CUR));
perror("Seek said");
printf("Then read read %d bytes\n",read(fd, blah, sizeof(blah)));
printf("The bytes read were '%c%c%c%c%c'\n",blah[0],blah[1],blah[2],blah[3],blah[4]);
}
以下是两次执行:
$ ./a.out < text
Seek moved to this position: 100
Seek said: Success
Then read read 5 bytes
The bytes read were '+++.-'
(那些是该文件中位置100的正确字节)
$ cat text | ./a.out
Seek moved to this position: -1
Seek said: Illegal seek
Then read read 5 bytes
The bytes read were '# def'
(那些字节是文件的前5个字节)
我还注意到标准输入版本是你说的正常工作版本。如果您在使用FILE *
版本时遇到问题,我怀疑fopen()
调用失败,因此请务必检查fopen()
的返回值。当然,你总是可以这样做:
FILE *fr = stdin;
因此,您正在阅读标准版。但是,由于您无法始终在标准版中进行搜索,因此如果您打算寻找,我建议您始终打开文件。
请注意,您无法在所有可以打开文件的设备上搜索(尽管在大多数系统上都没有问题),因此您应该始终检查seek()
的结果确定它成功了。
答案 1 :(得分:2)
我不是100%肯定差异,但它似乎与管道vs stdio /文件有关。为了说明这一点,我做了两个不同的测试程序:
exam.c
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{
char blah[5] = {0,};
/* we're using stdin instead of pipeline :( */
lseek(0, 100, SEEK_CUR);
read(0, blah, sizeof(blah));
printf("%c%c%c%c%c\n", blah[0], blah[1], blah[2], blah[3], blah[4]);
return 0;
}
test.c的
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
void testA(const char *s)
{
int f = -1;
char blah[5] = {0,};
f = open(s, O_RDONLY);
if (-1 < f)
{
lseek(f, 100, SEEK_CUR);
read(f, blah, sizeof(blah));
}
printf("%c%c%c%c%c\n", blah[0], blah[1], blah[2], blah[3], blah[4]);
}
void testB(const char *s)
{
FILE *fp = NULL;
char blah[5] = {0,};
fp = fopen(s, "r");
if (fp)
{
fseek(fp, 100, SEEK_CUR);
fread(blah, 1, sizeof(blah), fp);
}
printf("%c%c%c%c%c\n", blah[0], blah[1], blah[2], blah[3], blah[4]);
}
int main(int argc, char **argv)
{
testA(argv[1]);
testB(argv[1]);
return 0;
}
然后我创建了一些测试数据。
data.txt中
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
当我执行cat ./data.txt | ./exam
时,输出为
01234
当我执行./test ./data.txt
时,我得到了
bcdef
bcdef
仅供参考,即使我们将SEEK_CUR
替换为SEEK_SET
,结果仍保持不变。
但是,./exam <./data.txt
会产生
bcdef
这是合法的。
我知道如果不知道为什么'0'会显示数据文件的内容,这是不可接受的答案,但我希望它能以某种方式帮助。
答案 2 :(得分:2)
SEEK_CUR从当前位置开始。这就是为什么当你在文件的开头时,你的第一次搜索工作。要始终从头开始寻求,您需要使用SEEK_SET而不是SEEK_CUR。
0 SEEK_SET The beginning of the file
1 SEEK_CUR The current position
2 SEEK_END The end of the file