我的编程空间,编程开发者的网络收藏夹
学习永远不晚

学习如何用 C 语言来进行文件输入输出操作

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

学习如何用 C 语言来进行文件输入输出操作

理解 I/O 有助于提升你的效率。

如果你打算学习 C 语言的输入、输出,可以从 stdio.h 包含文件开始。正如你从其名字中猜到的,该文件定义了所有的标准(“std”)的输入和输出(“io”)函数。

大多数人学习的第一个 stdio.h 的函数是打印格式化输出的 printf 函数。或者是用来打印一个字符串的 puts 函数。这些函数非常有用,可以将信息打印给用户,但是如果你想做更多的事情,则需要了解其他函数。

你可以通过编写一个常见 Linux 命令的副本来了解其中一些功能和方法。cp 命令主要用于复制文件。如果你查看 cp 的帮助手册,可以看到 cp 命令支持非常多的参数和选项。但最简单的功能,就是复制文件:

  1. cp infile outfile

你只需使用一些读写文件的基本函数,就可以用 C 语言来自己实现 cp 命令。

一次读写一个字符

你可以使用 fgetc 和 fputc 函数轻松地进行输入输出。这些函数一次只读写一个字符。该用法被定义在 stdio.h,并且这也很浅显易懂:fgetc 是从文件中读取一个字符,fputc 是将一个字符保存到文件中。

  1. int fgetc(FILE *stream);
  2. int fputc(int c, FILE *stream);

编写 cp 命令需要访问文件。在 C 语言中,你使用 fopen 函数打开一个文件,该函数需要两个参数:文件名和打开文件的模式。模式通常是从文件读取(r)或向文件写入(w)。打开文件的方式也有其他选项,但是对于本教程而言,仅关注于读写操作。

因此,将一个文件复制到另一个文件就变成了打开源文件和目标文件,接着,不断从第一个文件读取字符,然后将该字符写入第二个文件。fgetc 函数返回从输入文件中读取的单个字符,或者当文件完成后返回文件结束标记(EOF)。一旦读取到 EOF,你就完成了复制操作,就可以关闭两个文件。该代码如下所示:

  1. do {
  2. ch = fgetc(infile);
  3. if (ch != EOF) {
  4. fputc(ch, outfile);
  5. }
  6. } while (ch != EOF);

你可以使用此循环编写自己的 cp 程序,以使用 fgetc 和 fputc 函数一次读写一个字符。cp.c 源代码如下所示:

  1. #include <stdio.h>
  2.  
  3. int
  4. main(int argc, char **argv)
  5. {
  6. FILE *infile;
  7. FILE *outfile;
  8. int ch;
  9.  
  10.  
  11.  
  12. if (argc != 3) {
  13. fprintf(stderr, "Incorrect usage\n");
  14. fprintf(stderr, "Usage: cp infile outfile\n");
  15. return 1;
  16. }
  17.  
  18.  
  19. infile = fopen(argv[1], "r");
  20. if (infile == NULL) {
  21. fprintf(stderr, "Cannot open file for reading: %s\n", argv[1]);
  22. return 2;
  23. }
  24.  
  25.  
  26. outfile = fopen(argv[2], "w");
  27. if (outfile == NULL) {
  28. fprintf(stderr, "Cannot open file for writing: %s\n", argv[2]);
  29. fclose(infile);
  30. return 3;
  31. }
  32.  
  33.  
  34.  
  35. do {
  36. ch = fgetc(infile);
  37. if (ch != EOF) {
  38. fputc(ch, outfile);
  39. }
  40. } while (ch != EOF);
  41.  
  42.  
  43. fclose(infile);
  44. fclose(outfile);
  45.  
  46. return 0;
  47. }

你可以使用 gcc 来将 cp.c 文件编译成一个可执行文件:

  1. $ gcc -Wall -o cp cp.c

-o cp 选项告诉编译器将编译后的程序保存到 cp 文件中。-Wall 选项告诉编译器提示所有可能的警告,如果你没有看到任何警告,则表示一切正常。

读写数据块

通过每次读写一个字符来实现自己的 cp 命令可以完成这项工作,但这并不是很快。在复制“日常”文件(例如文档和文本文件)时,你可能不会注意到,但是在复制大型文件或通过网络复制文件时,你才会注意到差异。每次处理一个字符需要大量的开销。

实现此 cp 命令的一种更好的方法是,读取一块的输入数据到内存中(称为缓存),然后将该数据集合写入到第二个文件。这样做的速度要快得多,因为程序可以一次读取更多的数据,这就就减少了从文件中“读取”的次数。

你可以使用 fread 函数将文件读入一个变量中。这个函数有几个参数:将数据读入的数组或内存缓冲区的指针(ptr),要读取的最小对象的大小(size),要读取对象的个数(nmemb),以及要读取的文件(stream):

  1. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

不同的选项为更高级的文件输入和输出(例如,读取和写入具有特定数据结构的文件)提供了很大的灵活性。但是,在从一个文件读取数据并将数据写入另一个文件的简单情况下,可以使用一个由字符数组组成的缓冲区。

你可以使用 fwrite 函数将缓冲区中的数据写入到另一个文件。这使用了与 fread 函数有相似的一组选项:要从中读取数据的数组或内存缓冲区的指针,要读取的最小对象的大小,要读取对象的个数以及要写入的文件。

  1. size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

如果程序将文件读入缓冲区,然后将该缓冲区写入另一个文件,则数组(ptr)可以是固定大小的数组。例如,你可以使用长度为 200 个字符的字符数组作为缓冲区。

在该假设下,你需要更改 cp 程序中的循环,以将数据从文件读取到缓冲区中,然后将该缓冲区写入另一个文件中:

  1. while (!feof(infile)) {
  2. buffer_length = fread(buffer, sizeof(char), 200, infile);
  3. fwrite(buffer, sizeof(char), buffer_length, outfile);
  4. }

这是更新后的 cp 程序的完整源代码,该程序现在使用缓冲区读取和写入数据:

  1. #include <stdio.h>
  2.  
  3. int
  4. main(int argc, char **argv)
  5. {
  6. FILE *infile;
  7. FILE *outfile;
  8. char buffer[200];
  9. size_t buffer_length;
  10.  
  11.  
  12.  
  13. if (argc != 3) {
  14. fprintf(stderr, "Incorrect usage\n");
  15. fprintf(stderr, "Usage: cp infile outfile\n");
  16. return 1;
  17. }
  18.  
  19.  
  20. infile = fopen(argv[1], "r");
  21. if (infile == NULL) {
  22. fprintf(stderr, "Cannot open file for reading: %s\n", argv[1]);
  23. return 2;
  24. }
  25.  
  26.  
  27. outfile = fopen(argv[2], "w");
  28. if (outfile == NULL) {
  29. fprintf(stderr, "Cannot open file for writing: %s\n", argv[2]);
  30. fclose(infile);
  31. return 3;
  32. }
  33.  
  34.  
  35.  
  36. while (!feof(infile)) {
  37. buffer_length = fread(buffer, sizeof(char), 200, infile);
  38. fwrite(buffer, sizeof(char), buffer_length, outfile);
  39. }
  40.  
  41.  
  42. fclose(infile);
  43. fclose(outfile);
  44.  
  45. return 0;
  46. }

由于你想将此程序与其他程序进行比较,因此请将此源代码另存为 cp2.c。你可以使用 gcc 编译程序:

  1. $ gcc -Wall -o cp2 cp2.c

和之前一样,-o cp2 选项告诉编译器将编译后的程序保存到 cp2 程序文件中。-Wall 选项告诉编译器打开所有警告。如果你没有看到任何警告,则表示一切正常。

是的,这真的更快了

使用缓冲区读取和写入数据是实现此版本 cp 程序更好的方法。由于它可以一次将文件的多个数据读取到内存中,因此该程序不需要频繁读取数据。在小文件中,你可能没有注意到使用这两种方案的区别,但是如果你需要复制大文件,或者在较慢的介质(例如通过网络连接)上复制数据时,会发现明显的差距。

我使用 Linux time 命令进行了比较。此命令可以运行另一个程序,然后告诉你该程序花费了多长时间。对于我的测试,我希望了解所花费时间的差距,因此我复制了系统上的 628 MB CD-ROM 镜像文件。

我首先使用标准的 Linux 的 cp 命令复制了映像文件,以查看所需多长时间。一开始通过运行 Linux 的 cp 命令,同时我还避免使用 Linux 内置的文件缓存系统,使其不会给程序带来误导性能提升的可能性。使用 Linux cp 进行的测试,总计花费不到一秒钟的时间:

  1. $ time cp FD13LIVE.iso tmpfile
  2.  
  3. real 0m0.040s
  4. user 0m0.001s
  5. sys 0m0.003s

运行我自己实现的 cp 命令版本,复制同一文件要花费更长的时间。每次读写一个字符则花了将近五秒钟来复制文件:

  1. $ time ./cp FD13LIVE.iso tmpfile
  2.  
  3. real 0m4.823s
  4. user 0m4.100s
  5. sys 0m0.571s

从输入读取数据到缓冲区,然后将该缓冲区写入输出文件则要快得多。使用此方法复制文件花不到一秒钟:

  1. $ time ./cp2 FD13LIVE.iso tmpfile
  2.  
  3. real 0m0.944s
  4. user 0m0.224s
  5. sys 0m0.608s

我演示的 cp 程序使用了 200 个字符大小的缓冲区。我确信如果一次将更多文件数据读入内存,该程序将运行得更快。但是,通过这种比较,即使只有 200 个字符的缓冲区,你也已经看到了性能上的巨大差异。 

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

学习如何用 C 语言来进行文件输入输出操作

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

学习如何用 C 语言来进行文件输入输出操作

如果你打算学习 C 语言的输入、输出,可以从 stdio.h 包含文件开始。正如你从其名字中猜到的,该文件定义了所有的标准(“std”)的输入和输出(“io”)函数。

如何用 C 语言来进行文件输入输出操作

本篇内容主要讲解“如何用 C 语言来进行文件输入输出操作”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何用 C 语言来进行文件输入输出操作”吧!如果你打算学习 C 语言的输入、输出,可以从 s
2023-06-15

如何在C语言中使用scanf函数进行用户输入

C语言是一种常用的编程语言,它提供了scanf函数来进行输入操作。scanf函数可以用来从用户输入的数据中读取值,然后将这些值存储到变量中。本文将详细介绍如何使用scanf函数,并提供一些具体的代码示例。首先,我们需要了解scanf函数的
如何在C语言中使用scanf函数进行用户输入
2024-02-25

如何在 golang 程序中运行二进制文件并通过发送一些输入并等待输出来保持与其交互?

你在学习Golang相关的知识吗?本文《如何在 golang 程序中运行二进制文件并通过发送一些输入并等待输出来保持与其交互?》,主要介绍的内容就涉及到,如果你想提升自己的开发能力,就不要错过这篇文章,大家要知道编程理论基础和实战操作都是不
如何在 golang 程序中运行二进制文件并通过发送一些输入并等待输出来保持与其交互?
2024-04-05

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录