20211301 学习笔记2

20211301《Unix/Linux系统编程》学习笔记1

教材笔记总结

学习目标

  • 本章是复习C语言中的文件操作内容,结构化从文本文件操作,二进制文件操作两个大内容考虑,以前可能只关注文本文件的操作,我们以后更多的是操作二进制文件。

  • 文本文件中考虑字符读写,行读写,任意位置读写等

  • 文件操作都有什么?

  • 二进制文件和文本文件如何转换?

  • 数据结构如何读写?

9.1 I/O库函数

  • 了解:系统调用是文件操作的基础,他们只支持数据块的读、写

9.2 I/O库函数与系统调用

  • I/O库函数:fopen、fread、fwrite、flseek、fclose

  • 系统调用:open、read、write、lseek、close (I/O库函数的根都在对应的系统调用函数中)

  • 区别:

    • 系统调用中文件描述符fd是一个整数、io中fp是一个文件流指针

    • 系统调用用open打开文件读取,并返回一个整数文件描述符fd,若失败返回-1,io库函数fopen返回一个file结构体指针,若失败,返回NULL

    • 系统调用使用while循环读取/写入文件,在每个迭代中,发出read系统调用,将最多4kb的字符读入buff[],将各字符写到文件描述符中,较为低效。

  • 显示文件内容

  • 复制文件

    • fopen使用字符串表示模式,返回一个指向file结构体的指针,fopen发出open系统调用打开文件,获取文件描述符fd,分配FILE结构体、内部缓冲区

    • 若fopen调用失败程序终止,在失败时返回一个NULL指针,例如 文件不能在指定模式下打开

    • while循环复制文件内容,读取BLKSIZE字节,fread和fwrite一般形式是

    • 上面程序尝试一次性读写BLKSIZE字节,size*nitems=BLKSIZE,但是size>1可能会在最后一个fread上出现问题,因为剩余字节可能小于size,为了处理尾部,在while循环后弥漫添加以下代码:

    • fseek与lseek工作原理相同,将R|W指针定位到总字节位置。

    • 用fclose关闭文件

9.3 IO库函数的算法

  • fread算法:第一次调用read算法,FILE结构体的缓冲区是空的,用保存的文件描述符fd发出一个系统调用,用数据块填充内部的fbuf,然后初始化fbuf的指针、计数器和状态变量。数据复制到缓冲区,满足内部缓冲区的fread调用,若内部缓冲区没有足够数据,则在发出一个read的系统调用来填充

  • fwirite:与fread相反,数据传输方向相反

  • fclose:若文件以写的方式被打开,会先关闭文件流的局部缓冲区,然后发出close(fd)系统调用来关闭FILE结构体中的文件描述符,最后释放结构体,并将指针重置为null

9.4 IO库或系统调用的使用

  • fread依赖read将数据从内核被复制到内部缓冲区,然后从内部缓冲区将数据复制到程序缓冲区,传输了两次数据,而read只传输一次

9.5 IO库模式

  • fopen中的模式参数可以指定为:r w a(追加),加+若文件不存在则创造文件

  • 字符模式:fgets返回的是整数,返回文件结束符(通常-1),与字符区分开

  • 行模式:从fp中读取最多为1行的字符

  • 格式化IO:

  • 其他函数

  • 限制混合:同时读写,规范要求对每个fread和fwrite之间至少有一个fseek或ftell

其他

  • 文本文件:如果一个文件说是文本文件,使用任何一种文本编辑器打开可以展现出人类可读信息字符,因为编码都符合某种编码方式,如ASCII、UTF8、GB2312等等(在文件头可以读出来是什么编码方式,然后文本编辑器再按照规则去读取翻译成对应的字符,展示给我们的就是可读的了)

  • 二进制文件:如果一个文件说是二进制文件,肯定没有编码方式,使用某些文本编辑器可以打开,展现出来的就是可能一些乱码的字符;也有些可以读取二进制文件的,展示出来就是原始的0101这种二进制了。比如说使用UtralEdit可以显示原始的二进制文件,显示的就是原始16进制。右侧自动选了一种编码方式进行翻译成文本,比如他自动选择的就是GBK,显示出来就是乱码。

  • 转换:使用vim修改

vim -b 文件名
:%!xxd ——转化成16进制
——————————————————————
:%!xxd -r——转回去
:wq

代码实现

  1. 文本文件中考虑字符读写,行读写,任意位置读写
  • 读取字符
#include <stdio.h>

int main() {
    FILE *file;
    char c;

    // 打开文件
    file = fopen("example.txt", "r");
    if (file == NULL) {
        printf("无法打开文件。\n");
        return 1;
    }

    // 读取并打印文件中的字符
    while ((c = fgetc(file)) != EOF) {
        printf("%c", c);
    }

    // 关闭文件
    fclose(file);

    return 0;
}

  1. 会以读写模式打开名为example.txt的文本文件,读取并打印文件中的字符,使用fprintf函数在文件末尾添加了一段新的文本。在使用fopen函数时使用的模式字符串为"r+",表示以读写模式打开文件。
#include <stdio.h>

int main() {
    FILE *file;
    char c;

    // 打开文件以读写模式
    file = fopen("example.txt", "a+");
    if (file == NULL) {
        printf("无法打开文件。\n");
        return 1;
    }

    // 在文件末尾添加一些文本
    fprintf(file, "abc");

    // 关闭文件
    fclose(file);

    return 0;
}

  1. 在任意位置读取文件
#include <stdio.h>

int main() {
    FILE* file = fopen("example.txt", "r"); // 文件名(根据自己的需求修改)
    if(file != NULL) {
        long int position = 5; // 要读取的位置(根据自己的需求修改)
        
        fseek(file, position, SEEK_SET); // 设置文件指针的位置

        int c;
        while((c = fgetc(file)) != EOF) {
            putchar(c); // 打印字符
        }

        fclose(file);
    } else {
        printf("无法打开文件\n");
    }

    return 0;
}
  1. 二进制与文本文件间的转换
#include <stdio.h>

void binaryToText(const char* binaryFileName, const char* textFileName) {
   FILE* binaryFile = fopen(binaryFileName, "rb");
   FILE* textFile = fopen(textFileName, "w");

   if (binaryFile != NULL && textFile != NULL) {
       int value;
       while (fread(&value, sizeof(int), 1, binaryFile) == 1) {
           fprintf(textFile, "%d ", value);
       }

       fclose(binaryFile);
       fclose(textFile);
       printf("转换成功: 二进制文件 -> 文本文件\n");
   } else {
       printf("无法打开文件\n");
   }
}

void textToBinary(const char* textFileName, const char* binaryFileName) {
   FILE* textFile = fopen(textFileName, "r");
   FILE* binaryFile = fopen(binaryFileName, "wb");

   if (textFile != NULL && binaryFile != NULL) {
       int value;
       while (fscanf(textFile, "%d", &value) == 1) {
           fwrite(&value, sizeof(int), 1, binaryFile);
       }

       fclose(textFile);
       fclose(binaryFile);
       printf("转换成功: 文本文件 -> 二进制文件\n");
   } else {
       printf("无法打开文件\n");
   }
}

int main() {
   const char* binaryFileName = "binaryfile.bin";
   const char* textFileName = "example.txt";

   // 二进制文件转换为文本文件
   binaryToText(binaryFileName, textFileName);

   // 文本文件转换为二进制文件
   textToBinary(textFileName, binaryFileName);

   return 0;
}

苏格拉底提问









问题与解决方案

  • 问题1 :在对文本文件进行写操作时,txt文件没有添加的内容

  • 解决方案:在程序运行时关闭文件,等程序运行完再打开文件就可以看到添加的内容了

心得体会

如果电脑上的任何操作都可以使用程序去完成,那么鼠标的重要性就极大地降低了,代码可以解决我们现在使用的大多数问题,只是我们还不太熟悉如何使用,我们更习惯用鼠标,但是作为一个程序员,应该更加懂得用程序解决一切问题,这样不仅提升了效率,还锻炼了编程能力。

posted @ 2023-09-17 21:17  20211301郑润芃  阅读(4)  评论(0编辑  收藏  举报