使用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.\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

转载于:https://www.cnblogs.com/yawenunion/p/8934864.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值