在C中打印文件到stdout最有效的方法是什么?

时间:2010-06-27 00:34:12

标签: c file

我坚持这个。目前我正在使用:

FILE *a = fopen("sample.txt", "r");
int n;
while ((n = fgetc(a)) != EOF) {
  putchar(n);
}

然而,这种方法似乎效率低下。有没有更好的方法?我尝试使用fgets:

char *s;
fgets(s, 600, a);
puts(s);

对于第二种方法,我发现有一件事是错误的,即fgets的第二个参数需要一个非常大的数字。

感谢所有建议。我找到了一种方法(IRC上有人告诉我这个)使用open(),read()和write()。

char *filename = "sample.txt";
char buf[8192];
int r = -1;
int in = open(filename, O_RDONLY), out = 0;
if (in == -1)
  return -1;
while (1) {
  r = read(in, buf, sizeof(buf));
  if (r == -1 || r == 0) { break; }
  r = write(out, buf, r);
  if (r == -1 || r == 0) { break; }
}

5 个答案:

答案 0 :(得分:9)

第二个代码被破坏了。您需要分配一个缓冲区,例如:

char s[4096];
fgets(s, sizeof(s), a);

当然,这并不能解决您的问题。

从输入中读取修复大小的块并写出读取的内容:

int n;
char s[65536];
while ((n = fread(s, 1, sizeof(s), a))) {
    fwrite(s, 1, n, stdout);
}

您可能还想检查ferror(a),以防因其他原因而停止,而不是达到EOF。

备注

  1. 我最初使用的是4096字节缓冲区,因为它是一个相当常见的页面大小,用于文件系统的内存分配和块大小。然而,我的Linux系统上的最佳点似乎是64 kB标记,这让我感到惊讶。也许CPU缓存是一个因素,但我只是在猜测。
  2. 对于冷缓存,它几乎没有区别,因为I / O分页将占主导地位;甚至一次一个字节以大约相同的速度运行。

答案 1 :(得分:5)

最有效的方法将在很大程度上取决于操作系统。例如,在Linux中,您可以使用sendfile

struct stat buf;
int fd = open(filename, O_RDONLY);
fstat(fd, &buf);
sendfile(0, fd, NULL, buf.st_size);

这直接在内核中进行复制,从而最大限度地减少了不必要的内存到内存副本。其他平台可能有类似的方法,例如write()来自mmap ed缓冲区的stdout。

答案 2 :(得分:1)

我相信FILE返回的fopen是经常(总是?)缓冲的,所以你首先举例说的并不像你想象的那么低效。

第二个可能表现得更好......如果你纠正错误:记得分配缓冲区,并记住puts添加换行符!。

其他选项是使用二进制读取(fread)。

答案 3 :(得分:0)

这一切都取决于你想对数据做些什么。

但这会崩溃:

char *s;
fgets(s, 600, a);
puts(s);

因为s不是缓冲区,只是某个指针。

一种方法是将整个文件读入缓冲区并使用它 通过使用fread()

filebuffer = malloc(filelength);
fread( buffer, 1, filelength, fp );

答案 4 :(得分:0)

99%的应用程序中你正在做的事情足够好。当然,在大多数C库中,stdio表现不佳,而您最好使用Phong Vo's sfio library如果您有测量结果显示这是一个瓶颈,下一步自然就是分配缓冲区并使用fread / fwrite。您想要fgets,因为您不关心换行符。


首先使它运行,然后使其正确。你可能没必要加快速度。