What is the most efficient way to print a file in C in stdout?

I am stuck on this. I am currently using:

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

However, this method seems a bit inefficient. Is there a better way? I tried using fgets:

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

One thing that I think is wrong with respect to this second method is that for the second argument to fgets you will need a really large amount.

Thanks for all the suggestions. I found a way (someone from the IRC told me this) using open (), read () and 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; } } 
+4
source share
5 answers

The second code is broken. You need to allocate a buffer, for example:

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

Of course, this will not solve your problem.

Read the fixed-size fragments from the input and write out everything that is read:

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

You can also check ferror(a) if it is stopped for some other reason than to achieve EOF.

Notes

  • I originally used a 4096 byte buffer because this is a pretty common page size for memory allocation and block size for the file system. However, the sweet spot on my Linux system is similar to the 64 kB mark, which surprised me. Perhaps the processor cache is a factor here, but I just guess.
  • For a cold cache, this is practically irrelevant, since I / O paging dominates; even one byte at a time works at about the same speed.
+9
source

The most effective method will largely depend on the operating system. For example, on Linux, you can use sendfile :

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

This makes a copy directly to the kernel, minimizing unnecessary copies of memory in memory. Other platforms may have similar approaches, such as write() ing to stdout from the mmap ed buffer.

+5
source

I believe the FILE returned by fopen is buffered (always?), So the first example is not as inefficient as you think.

The second one may improve a bit ... if you correct the errors: do not forget to select the buffer and remember that puts add a new line !.

Another option is to use binary reads (fread).

+1
source

It all depends on what you want to do with the data.

this will crash:

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

since s is not a buffer, but a pointer somewhere.

One way is to read the entire file into the buffer and work with it using fread ()

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

What you do is good enough in 99% of applications. Of course, in most C libraries, stdio works poorly and you will be better off with the Phong Vo sfio library . If you have measurements showing that this is a bottleneck, the next next step is to allocate a buffer and use fread / fwrite . You do not want fgets because you do not need newlines.


Run it first, then do it right. You probably don't need to do this fast.

0
source

Source: https://habr.com/ru/post/1313983/


All Articles