使用C语言标准I/O库进行文件读写的实践

1) Line-I/O via fgets and fputs

小试牛刀

源文件 main.c

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define BUFFER_SIZE 1024
  6 char *lineBuffer = NULL;
  7 
  8 void buildLineBuffer() {
  9     if (lineBuffer == NULL) {
 10         lineBuffer = (char *)malloc(BUFFER_SIZE);
 11     }
 12 }
 13 
 14 void dropLineBuffer() {
 15     if (lineBuffer != NULL) {
 16         free(lineBuffer);
 17     }
 18 }
 19 
 20 void checkRightAfterFopen(FILE *fp) {
 21     if (fp == NULL) {
 22         fputs("Failed to open file.
", stderr);
 23         exit(1);
 24     }
 25 }
 26 
 27 int writeContents2File(const char *contents, const char *fileName) {
 28     FILE *fp = fopen(fileName, "w");
 29     checkRightAfterFopen(fp);
 30     fputs(contents, fp);
 31     fclose(fp);
 32 
 33     return 0;
 34 }
 35 
 36 char *readLineFromFile(const char *fileName) {
 37     FILE *fp = fopen(fileName, "r");
 38     checkRightAfterFopen(fp);
 39     buildLineBuffer();
 40     fgets(lineBuffer, BUFFER_SIZE, fp);
 41     fclose(fp);
 42     return lineBuffer;
 43 }
 44 
 45 void showAllContentsInFile(const char *fileName) {
 46     FILE *fp = fopen(fileName, "r");
 47     checkRightAfterFopen(fp);
 48     buildLineBuffer();
 49     while (fgets(lineBuffer, BUFFER_SIZE, fp) != NULL) {
 50         printf(lineBuffer);
 51     }
 52     fclose(fp);
 53 }
 54 
 55 int appendContentsFromConsole2File(const char *fileName) {
 56     FILE *fp = fopen(fileName, "a");
 57     checkRightAfterFopen(fp);
 58     buildLineBuffer();
 59     while (fgets(lineBuffer, BUFFER_SIZE, stdin) != NULL && fputs(lineBuffer, fp) != EOF);
 60     fclose(fp);
 61 
 62     return 0;
 63 }
 64 
 65 /*
 66 **由目录名和文件名取得文件的全限定名
 67 **---------------------------------
 68 **建议设定用户环境变量"C_DEV_HOME"的值为该目录的父目录全限定名
 69 **若当前系统环境中尚未设置该环境变量,
 70 **则给出提醒并默认采用当前目录作为该目录的父目录全限定名
 71 */
 72 char *getFullyQualifedFileName(const char *dirName, const char *fileName) {
 73     /*访问用户环境变量以取得根目录的全限定名*/
 74     char *homedir = getenv("C_DEV_HOME");
 75     if (homedir == NULL) {
 76         printf("Info: User/System Environment Varable "C_DEV_HOME" has NOT been set yet!
");
 77         homedir = ".";
 78     }
 79 
 80     /*创建缓存区,用于存放文件的全限定名*/
 81     char *fullyQualifedFileNameBuffer = (char *)malloc(strlen(homedir) + strlen(dirName) + strlen(fileName) + 3);
 82     *fullyQualifedFileNameBuffer = ''; // 初始化为空字符串
 83 
 84     /*设定路径分隔符*/
 85     char *pathSeparator = "/";
 86 #ifdef _WIN32
 87     pathSeparator = "\";
 88 #endif
 89 
 90     /*调用系统函数来创建目标目录*/
 91     char
 92         *cmd_prefix = "mkdir ",
 93         *fullyQualifedDirName = strcat(strcat(strcat(fullyQualifedFileNameBuffer, homedir), pathSeparator), dirName),
 94         *mkdir_CommandBuffer = (char *)malloc(strlen(fullyQualifedDirName) + strlen(cmd_prefix) + 1);
 95     *mkdir_CommandBuffer = '';
 96     system(strcat(strcat(mkdir_CommandBuffer, cmd_prefix), fullyQualifedDirName));
 97     free(mkdir_CommandBuffer);
 98 
 99     /*返回 由目标目录的全限定名和文件名组合成文件的全限定名*/
100     return strcat(strcat(fullyQualifedDirName, pathSeparator), fileName);
101 }
102 
103 int main(void) {
104     char
105         *filePath = getFullyQualifedFileName("FileIO", "demo"),
106         *contents = "Hello, World! Here is C I/O demo.
";
107     printf("##FilePath: %s
", filePath);
108 
109     /*建立缓存容器*/
110     buildLineBuffer();
111 
112     /*Write*/
113     writeContents2File(contents, filePath);
114 
115     /*Read*/
116     printf(readLineFromFile(filePath));
117 
118     /*Append*/
119     printf("You can Append More Contents Here:
");
120     appendContentsFromConsole2File(filePath);
121 
122     /*显示文件的全部内容*/
123     showAllContentsInFile(filePath);
124 
125     /*销毁缓存容器*/
126     dropLineBuffer();
127 
128     return 0;
129 }

想要在Visual Studio中正常使用C语言的标准I/O库函数,而不使用Visual Studio自己的xxx_s安全函数,需要在 项目 > 属性 > C/C++ > 预处理器 > 预处理器定义
添加 _CRT_SECURE_NO_WARNINGS

跑一波

On Windows 10

打开磁盘上的文件瞅瞅

 

On CentOS 7

2) Formatted-I/O via fscanf and fprintf

以下内容待续

3) Binary-I/O via fread and fwrite

二进制I/O可以直接对内存中的数据对象(变量、数组、结构体,等等)进行写出或读入。
下面以数组对象的二进制I/O为例:
源文件 main.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 int main(void) {
 5     /*定义输出数据缓冲区、输入数据缓冲区、循环步进变量*/
 6     int outBuf[20], inBuf[20], i;
 7 
 8     /*对outBuf填入特定的值*/
 9     for (i = 0; i < 20; ++i) {
10         outBuf[i] = (i + 1)*(i + 2);
11     }
12 
13     /*创建二进制输出的目标目录*/
14     system("mkdir .\BinaryIO-Temp"); // 在Linux系统上编译前请把该行改为:system("mkdir -p ./BinaryIO-Temp");
15 16 /*以二进制写的方式打开要输出到的目标文件*/ 17 FILE *fp = fopen(".\BinaryIO-Temp\a", "wb+"); // 在Linux系统上编译前,请把这里的路径分隔符"\"都替换为"/" 18 if (fp == NULL) { 19 printf("Failed when trying to open file. "); 20 exit(EXIT_FAILURE); 21 } 22 23 /*执行二进制写操作,把outBuf中的数据写入目标文件中*/ 24 if (fwrite(outBuf, sizeof(int), 20, fp) != 20) { 25 printf("Failed when doing binary-writing. "); 26 exit(EXIT_FAILURE); 27 } else { 28 printf("Succeeded in doing binary-writing. "); 29 } 30 31 /*将文件读写位置标记重置到文件开头*/ 32 rewind(fp); 33 34 /*执行二进制读操作,把目标文件中的数据写入inBuf中*/ 35 if (fread(inBuf, sizeof(int), 20, fp) != 20) { 36 printf("Failed when doing binary-reading. "); 37 exit(EXIT_FAILURE); 38 } else { 39 printf("Succeeded in doing binary-reading. "); 40 } 41 42 /*结束I/O操作后,关闭文件*/ 43 fclose(fp); 44 45 /*显示outBuf中的数据*/ 46 printf("Data of outBuf: "); 47 for (i = 0; i < 20; ++i) { 48 printf("%d ", outBuf[i]); 49 } 50 printf(" "); 51 52 /*显示inBuf中的数据*/ 53 printf("Data of inBuf: "); 54 for (i = 0; i < 20; ++i) { 55 printf("%d ", inBuf[i]); 56 } 57 printf(" "); 58 59 return 0; 60 }

 跑一下

on Windows

on CentOS

原文地址:https://www.cnblogs.com/yawenunion/p/8934864.html