【发布时间】:2021-06-15 07:26:31
【问题描述】:
我正在尝试获取有关如何写入文件的示例(shell 脚本)程序:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char buff[1024];
size_t len, idx;
ssize_t wcnt;
for (;;){
if (fgets(buff,sizeof(buff),stdin) == NULL)
return 0;
idx = 0;
len = strlen(buff);
do {
wcnt = write(1,buff + idx, len - idx);
if (wcnt == -1){ /* error */
perror("write");
return 1;
}
idx += wcnt;
} while (idx < len);
}
}
所以我的问题是这样的:假设我想写一个 20000 字节的文件,所以每次我只能写(最多)1024(缓冲区大小)。
假设在我的第一次尝试中一切都很完美, fgets() 读取 1024 字节,而在我第一次尝试时,我写入 1024 字节。
然后,由于我们写入了“len”字节,我们退出了 do-while 循环。
现在怎么办?缓冲区已满,因为我们之前的读取。 在我看来,出于某种原因,暗示 fgets() 现在将从上次在文件中到达的点继续读取。(此处为 buf[1024])。
为什么 fgets() 知道它在文件中停止读取的位置?
我检查了手册页:
fgets() 从流中最多读入一个小于 size 的字符,并将它们存储到 s 指向的缓冲区中。在 EOF 或换行符后停止读取。如果读取了换行符,则将其存储在缓冲区中。终止空字节 (aq\0aq) 存储在缓冲区中的最后一个字符之后。
fgets() 成功时返回 s,错误时返回 NULL,或者在没有读取任何字符的情况下发生文件结尾。*
因此,我知道它返回一个指向 buf 的第一个元素的指针,它始终是 buf[0], 这就是为什么我很困惑。
【问题讨论】:
-
为什么 fgets() 知道它在文件中停止读取的位置。该信息存储在文件流结构中(在这种情况下为
stdin)。但听起来你可能对它与buff的关系感到困惑——它不像fgets每次被调用时都会写入buf的开头,它总是返回buf或@987654327 @. -
是的,您将
fgets交给您的缓冲区与您交给fgets的FILE 对象中的流混淆了。 -
"FILE * ostream 指向文件的第一个字符。" --> 否。
ostream指向一个结构,其中包含以某种方式组织的各种数据。它的内容不适合用户阅读。 -
正如其他人指出的那样,您将 C 运行时文件系统缓冲区与您自己的输入缓冲区混淆了。细节由实现定义,但对于终端设备(即标准输入),通常有一个异步进程在操作系统级别收集输入,然后当您的代码调用
fgets时,它会耗尽操作系统缓冲区,直至 EOL,通过 API 调用并将其写入您提供的缓冲区。 -
@brucebanner 是的,你是对的。