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.\n", 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!\n"); 77 homedir = "."; 78 } 79 80 /*创建缓存区,用于存放文件的全限定名*/ 81 char *fullyQualifedFileNameBuffer = (char *)malloc(strlen(homedir) + strlen(dirName) + strlen(fileName) + 3); 82 *fullyQualifedFileNameBuffer = '\0'; // 初始化为空字符串 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 = '\0'; 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.\n"; 107 printf("##FilePath: %s\n", 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:\n"); 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.\n"); 20 exit(EXIT_FAILURE); 21 } 22 23 /*执行二进制写操作,把outBuf中的数据写入目标文件中*/ 24 if (fwrite(outBuf, sizeof(int), 20, fp) != 20) { 25 printf("Failed when doing binary-writing.\n"); 26 exit(EXIT_FAILURE); 27 } else { 28 printf("Succeeded in doing binary-writing.\n"); 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.\n"); 37 exit(EXIT_FAILURE); 38 } else { 39 printf("Succeeded in doing binary-reading.\n"); 40 } 41 42 /*结束I/O操作后,关闭文件*/ 43 fclose(fp); 44 45 /*显示outBuf中的数据*/ 46 printf("Data of outBuf:\n"); 47 for (i = 0; i < 20; ++i) { 48 printf("%d ", outBuf[i]); 49 } 50 printf("\n"); 51 52 /*显示inBuf中的数据*/ 53 printf("Data of inBuf:\n"); 54 for (i = 0; i < 20; ++i) { 55 printf("%d ", inBuf[i]); 56 } 57 printf("\n"); 58 59 return 0; 60 }
跑一下
on Windows
on CentOS