zoukankan      html  css  js  c++  java
  • 使用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

  • 相关阅读:
    雷锋依然在人间 工厂方法模式
    为别人做嫁衣 代理模式
    穿什么有这么重要? 装饰模式
    437. Path Sum III
    434. Number of Segments in a String
    447. Add Strings
    414. Third Maximum Number
    412. Fizz Buzz
    404. Sum of Left Leaves
    405. Convert a Number to Hexadecimal
  • 原文地址:https://www.cnblogs.com/yawenunion/p/8934864.html
Copyright © 2011-2022 走看看