在之前的讲座中,我展示了一个程序,它生成伪随机整数流,并将它们写入标准输出。
下面是稍微修改过的程序版本,它将整型流写入文本文件。用户提供文本文件的名称作为命令行参数,以及随机数序列的种子和要写入的数字数。
#include <stdio.h> int main (int argc, const char * argv[]) {int x, N, N;if(argc != 4) {printf(“无效参数列表。\n”);printf("Usage: drnd <seed> <N> <filename>\ N ");返回1;} sscanf (argv[1],“% d”,x);sscanf (argv[2],“% d n);FILE* f = fopen(argv[3],"w");N = 0;while(n < n) {x = (17389*x+12553)%11657;n + +;流(f,“% d \ n”,x % 10000);}文件关闭(f);返回0;}
今天示例程序的第二个版本做了同样的事情,但这次程序将整数流写入二进制文件。通过以二进制形式写出数据,我们跳过了在将整数保存到文件之前必须将其转换为文本的步骤。这个程序的速度大约是文本版本的两倍。
#include <stdio.h> int main (int argc, const char * argv[]) {int x, N, N, y;if(argc != 4) {printf(“无效参数列表。\n”);printf("Usage: drnd <seed> <N> <filename>\ N ");返回1;} sscanf (argv[1],“% d”,x);sscanf (argv[2],“% d n);//将数字以二进制形式保存FILE* f = fopen(argv[3],"wb");N = 0;while(n < n) {x = (17389*x+12553)%11657;n + +;Y = x%10000;写入文件(y, sizeof (int), 1, f);}文件关闭(f);返回0;}
使用fopen/fwrite/fclose组合的替代方法是使用等效的系统调用open/write/close。该程序的第三个版本使用系统调用而不是标准库将数据以二进制形式写入文件。
#include <stdio.h> #include <fcntl.h> #include <unistd.h> int main (int argc, const char * argv[]) {int x, N, N, y;if(argc != 4) {printf(“无效参数列表。\n”);printf("Usage: drnd <seed> <N> <filename>\ N ");返回1;} sscanf (argv[1],“% d”,x);sscanf (argv[2],“% d n);//保存二进制形式的数字int fd = open(argv[3],O_WRONLY|O_CREAT);N = 0;while(n < n) {x = (17389*x+12553)%11657;n + +;Y = x%10000;写(fd, y, sizeof (int));}关闭(fd);返回0;}
这个版本非常慢。性能差的原因是我们对write()进行了N次单独的调用,以将N个整数流写入文件。与fwrite()不同,write()系统调用使用无缓冲的写操作。当调用fwrite()时,首先要求写入的数据会累积到内存中的缓冲区中。当缓冲区满了或关闭文件时,缓冲区的内容会立即全部转储到文件中。当调用write()时,所请求的数据会立即写入文件。在每次写入少量数据的情况下,对write()进行大量调用是非常低效的。
使用write()的更有效的方法是将赢博体育数据放在缓冲区中,然后立即将整个缓冲区写入文件。示例程序的第四个也是最后一个版本就是这样做的。
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main (int argc, const char * argv[]) {int x, N, N;if(argc != 4) {printf(“无效参数列表。\n”);printf("Usage: drnd <seed> <N> <filename>\ N ");返回1;} sscanf (argv[1],“% d”,x);sscanf (argv[2],“% d n);int* A = (int*) malloc(N*sizeof(int))//生成n = 0的数字;while(n < n) {x = (17389*x+12553)%11657;A[n] = x%10000;n + +;} //一次将赢博体育数字转储到文件int fd = open(argv[3],O_WRONLY|O_CREAT);写(fd, N * sizeof (int));关闭(fd);自由(A);返回0;}
我们的教材很好地涵盖了系统调用和文件的标准库函数。您将在第二章中找到对系统调用的讨论。我建议阅读第二章,直到但不包括同步I/O部分。您将在第三章中找到对标准库文件函数的深入讨论。