使用C语言实现文件的拷贝——底层内存分析

使用C语言实现文件的拷贝

本文主要涉及sprintf()函数的讲解以及系统IO与标准IO的区别和一个实例使用C语言实现文件的拷贝,在最后还深度刨析了文件拷贝的底层原理。

文章目录

  • 使用C语言实现文件的拷贝
    • 一、 sprintf()函数
      • 1.1 sprintf ()函数的参数解析
      • 1.2 sprintf()函数将整数和浮点数格式化为字符串
    • 二、 系统 I/O(Input/Output)和标准 I/O
    • 三、 C语言实现文件的拷贝
      • 3.1 实现效果要求
      • 3.2 实现代码
      • 3.3 实现效果
      • 3.4 实现文件拷贝的底层内存刨析

一、 sprintf()函数

1.1 sprintf ()函数的参数解析

sprintf() 是 C 语言中的一个标准库函数,用于将格式化的数据写入字符串中。它的功能与 printf() 相似,但是 printf() 会将格式化的数据写入标准输出(通常是屏幕),而 sprintf() 则将数据写入一个字符串。

sprintf() 的原型如下:

#include <stdio.h>

int sprintf(char *str, const char *format, ...);

其中:

  • str:是一个字符数组或字符指针,用于存储格式化的输出字符串。在调用 sprintf() 之前,str 应该已经分配了足够的空间来存储生成的字符串,以防止缓冲区溢出。

  • format:是一个字符串,它包含了一个或多个格式说明符,用于指定如何格式化输出的数据。

sprintf() 函数与 printf() 函数在格式说明符和用法上是相同的,但是它不输出到标准输出,而是将结果写入 str 指定的字符串中。

1.2 sprintf()函数将整数和浮点数格式化为字符串

以下是一个 sprintf() 的简单示例:

#include <stdio.h>

int main() {
    char buffer[100];
    int num = 12345;
    float fnum = 67.89;

    // 使用 sprintf 将整数和浮点数格式化为字符串
    sprintf(buffer, "Integer: %d, Float: %.2f", num, fnum);

    // 打印生成的字符串
    printf("Formatted string: %s\n", buffer);

    return 0;
}

在上述示例中,sprintf() 将整数 num 和浮点数 fnum 格式化为一个字符串,并存储在 buffer 中。然后,我们使用 printf() 打印生成的字符串。

需要注意的是,为了安全起见,当使用 sprintf() 时,应确保目标字符串(即第一个参数 str)有足够的空间来存储格式化后的字符串,以防止缓冲区溢出。

在这里插入图片描述

二、 系统 I/O(Input/Output)和标准 I/O

系统 I/O(Input/Output)和标准 I/O 都是在计算机编程中用于数据输入和输出的概念,但它们之间存在一些区别。以下是对这两者的简要说明:

  1. 系统 I/O(Low-Level I/O)

    • 系统 I/O 指的是直接使用操作系统提供的系统调用(system calls)进行输入/输出操作。
    • 这种 I/O 是直接的、底层的,通常涉及到操作系统的内核级别。
    • 例如,在UNIX/Linux系统中,系统调用如 readwrite 用于从文件描述符(file descriptors)进行读写。
    • 系统 I/O 更接近底层硬件操作,通常提供了更细粒度的控制,但使用它可能需要处理更多的细节和复杂性。
  2. 标准 I/O(Standard I/O or Buffered I/O)

    • 标准 I/O 是在系统 I/O 之上构建的高级 I/O 概念。
    • 它使用了缓冲区(buffer)来优化数据的读写,减少了直接调用系统调用的频率,从而提高了性能。
    • 在C语言中,标准 I/O 是通过库函数实现的,如 stdio.h 提供的 fopen, fclose, fread, fwrite, fprintf, fscanf 等函数。
    • 标准 I/O 提供了对流(stream)的概念,如文件流、标准输入流(stdin)、标准输出流(stdout)等。
    • 标准 I/O 通常更易于使用和管理,因为它隐藏了底层的细节和复杂性。

总结

  • 系统 I/O 是直接的、底层的 I/O 操作,通常使用系统调用来进行读写,提供了更细粒度的控制。
  • 标准 I/O 是基于系统 I/O 构建的高级 I/O 抽象,使用缓冲区来优化数据的读写,提供了更简洁、易于使用的接口。

在实际编程中,通常建议使用标准 I/O,除非有特定的需求或优化目标需要使用系统 I/O。标准 I/O 提供了足够的性能,并且更易于管理和维护。

三、 C语言实现文件的拷贝

3.1 实现效果要求

使用C语言实现cp函数一样的效果,进行文件的拷贝。

执行要求:
执行:./a.out ./1.txt …/2.txt
执行代码./a.out 后将当前文件下的./1.txt 拷贝到 …/2.txt

3.2 实现代码

#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <source_file> <destination_file>\n", argv[0]);
        return 1;
    }

    const char *file1 = argv[1];
    const char *file2 = argv[2];

    // 打开源文件
    int fd_source = open(file1, O_RDONLY);
    if (fd_source == -1) {
        perror("Error opening source file");
        return 1;
    }

    // 获取源文件的权限
    struct stat stat_source;
    if (fstat(fd_source, &stat_source) == -1) {
        perror("Error getting source file status");
        close(fd_source);
        return 1;
    }

    // 创建或打开目标文件
    int fd_dest = open(file2, O_WRONLY | O_CREAT | O_TRUNC, stat_source.st_mode);
    if (fd_dest == -1) {
        perror("Error opening destination file");
        close(fd_source);
        return 1;
    }

    // 读取源文件并写入目标文件
    char buffer[1024];
    ssize_t bytes_read;
    while ((bytes_read = read(fd_source, buffer, sizeof(buffer))) > 0) {
        if (write(fd_dest, buffer, bytes_read) != bytes_read) {
            perror("Error writing to destination file");
            close(fd_source);
            close(fd_dest);
            return 1;
        }
    }

    // 关闭文件描述符
    close(fd_source);
    close(fd_dest);

    printf("File copied successfully.\n");

    return 0;
}


read(fd_source, buffer, sizeof(buffer)):从 fd_source 文件描述符中读取数据,将读取的数据存储在 buffer 中,最多读取 buffer 的大小(即 1024 字节)。

如果 read 调用成功并读取了数据,bytes_read 将存储实际读取的字节数

当 read 返回0(表示已到达文件末尾)或者返回一个错误(read 返回 -1)时,循环将结束

3.3 实现效果

执行命令:
在这里插入图片描述

执行效果:
在这里插入图片描述

3.4 实现文件拷贝的底层内存刨析

当你从底层内存角度考虑文件复制操作时,实际上涉及到数据在计算机系统中的存储和处理方式。以下是从底层内存的角度详细解释文件拷贝的过程和原因:

  1. 数据的存储

    • 文件数据存储在硬盘或其他存储设备上的磁盘块中。
    • 当你打开一个文件进行读取时,操作系统将这些磁盘块的内容读入内存的页缓存中。这样做是为了加速后续的读取操作,因为内存的读写速度远高于磁盘。
  2. 系统调用与缓冲

    • 使用openread系统调用时,操作系统会处理数据的缓冲和调度,确保数据被有效地从磁盘读入内存。
    • 同样,使用write系统调用时,操作系统会确保数据从内存写回到磁盘。
  3. 数据的传输

    • 在执行文件复制时,数据首先从源文件的内存缓存中被读取到应用程序的地址空间(通常是通过read系统调用实现的)。
    • 然后,这些数据从应用程序的地址空间被写入到目标文件的内存缓存中(通过write系统调用)。
    • 最终,操作系统会确保目标文件的内存缓存中的数据被写回到磁盘上的相应位置。
  4. 性能考虑

    • 文件拷贝操作在内存和磁盘之间进行,这通常比直接在磁盘之间进行文件拷贝更快。因为内存操作的速度远快于磁盘操作。
    • 此外,操作系统和硬件通常有各种优化,如预读、预写、缓冲等,进一步提高了数据传输的效率。
  5. 数据的完整性和一致性

    • 在数据传输过程中,操作系统会确保数据的完整性和一致性。这意味着,除非操作系统确定数据已经被完全写入目标文件,否则不会认为写操作已经完成。

总之,从底层内存的角度看,文件复制涉及数据在内存和磁盘之间的传输,操作系统在其中扮演了关键的角色,确保数据的正确、高效地传输。这也解释了为什么直接在磁盘之间执行文件拷贝通常比先将数据加载到内存中再写回更加高效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/259941.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设计测试用例(万能思路 + 六种设计用例方法)(详细 + 图解 + 实例)

一、设计测试用例的万能思路 针对某个物品/功能进行测试。 万能思路&#xff1a;功能测设 界面测试 性能测试 兼容性测试 易用性测试 安全测试。 总结&#xff1a; 功能测试&#xff1a; 水杯&#xff1a;装水、喝水... 注册场景&#xff1a;注册 登录 想象日常使用…

2017年第六届数学建模国际赛小美赛A题飓风与全球变暖解题全过程文档及程序

2017年第六届数学建模国际赛小美赛 A题 飓风与全球变暖 原题再现&#xff1a; 飓风&#xff08;也包括在西北太平洋被称为“台风”的风暴以及在印度洋和西南太平洋被称为“严重热带气旋”&#xff09;具有极大的破坏性&#xff0c;往往造成数百人甚至数千人死亡。   许多气…

【Spring Security】打造安全无忧的Web应用--入门篇

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Spring Security的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Spring Security是什么 1.概…

FFmepeg——视频处理工具安装以及简单命令学习。

FFmpeg 是一个免费、开源且高度可定制的多媒体处理工具&#xff0c;它是一个强大的跨平台框架&#xff0c;用于处理音频、视频、多媒体流和图像。FFmpeg 的主要功能包括解码、编码、转码、流处理、多路复用、分离、合并、过滤等&#xff0c;支持多种音视频格式&#xff0c;包括…

研发管理-代码管理篇

前言&#xff1a; 工作了这些年&#xff0c;工作了三家公司&#xff0c;也用过主流的代码管理平台&#xff0c;比如SVN&#xff0c;git系列&#xff08;gitlib,gitee&#xff09;,各有优点&#xff0c;我个人比较喜欢SVN&#xff0c;多人协作的代码管理难免会有代码冲突&#…

【QT表格-6】QTableWidget的currentCellChanged实现中途撤销

背景&#xff1a; 【QT表格-1】QStandardItem的堆内存释放需要单独delete&#xff0c;还是随QStandardItemModel的remove或clear自动销毁&#xff1f;-CSDN博客 【QT表格-2】QTableWidget单元格结束编辑操作endEditting_qtablewidget 单元格编辑事件-CSDN博客 【QT表格-3】Q…

LLama Factory 安装部署实操记录(二)

1. 项目地址 GitHub - hiyouga/LLaMA-Factory: Easy-to-use LLM fine-tuning framework (LLaMA, BLOOM, Mistral, Baichuan, Qwen, ChatGLM)Easy-to-use LLM fine-tuning framework (LLaMA, BLOOM, Mistral, Baichuan, Qwen, ChatGLM) - GitHub - hiyouga/LLaMA-Factory: Easy…

hive命令启动出现classnotfound

环境&#xff1a;ambari集群三个节点node104、node105和node106&#xff0c;其中node105上有hiveserver2&#xff0c;并且三个节点均有HIVE CLIENT 注意&#xff1a;“./”指hive安装目录 其中装有hiveserver2的node105节点&#xff0c;由于某种需要向lib目录下上传了某些jar包…

无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测

无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测 无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测介绍题目一. 背景&#xff08;解决的问题&#xff09;二. 系统模型2.1 信道模型2.1.1 信道系数2.1.2 进行标准化 2.2 信道估计 和 数据传输2.2.1 信道估计…

环境搭建及源码运行_java环境搭建_idea版本下载及安装

1、介绍 Idea是一款被广泛使用的Java集成开发环境&#xff0c;它提供了丰富的功能和工具来帮助开发人员更高效地编写和调试代码。作为一款开源软件&#xff0c;Idea不仅提供了基本的代码编辑、自动完成和调试功能&#xff0c;还支持大量的插件和扩展&#xff0c;可为开发人员提…

将Abp默认事件总线改造为分布式事件总线

文章目录 原理创建分布式事件总线实现自动订阅和事件转发 使用启动Redis服务配置传递Abp默认事件传递自定义事件 项目地址 原理 本地事件总线是通过Ioc容器来实现的。 IEventBus接口定义了事件总线的基本功能&#xff0c;如注册事件、取消注册事件、触发事件等。 Abp.Events…

MySQL之表的约束

目录 前言 not null约束 default约束 同时设置not null约束和default约束 comment约束 zerofill约束 primary key约束&#xff08;又称主键约束&#xff09; 复合主键约束 auto_increment约束&#xff08;又称自增长约束&#xff09; unique约束&#xff08;又称唯一…

Redis分布式缓存-Redis持久化

RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xff0c;也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后&#xff0c;从磁盘读取快照文件&#xff0c;恢复数据。快照文件称为RDB文…

cpp_04_类_对象_this指针_常对象_常(成员)函数

1 类 1.1 类的定义 类的作用是抽象事物&#xff08;抽取事物特征&#xff09;的规则。 类的外化表现是用户自定义的复合数据类型&#xff08;包括成员变量、成员函数&#xff09;&#xff1a; 成员变量用于表达事物的属性&#xff0c;成员函数用于表达事物的行为。 类的表现…

力扣79. 单词搜索(java DFS解法)

Problem: 79. 单词搜索 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 该问题可以归纳为一类遍历二维矩阵的题目&#xff0c;此类中的一部分题目可以利用DFS来解决&#xff0c;具体到本题目&#xff08;该题目可以的写法大体不变可参看前面几个题目&#xff1a;&…

校园圈子交友系统,APP小程序H5,三端源码交付,支持二开!实名认证,大V认证,地图找伴,二手平台!

校园圈子交友系统&#xff0c;是属于自主定义开发的系统&#xff0c;内容有很多&#xff0c;先截取一些给大家看看&#xff0c;让大家更多的了解本系统&#xff0c;然后再做评价&#xff01; 校园后端下载地址&#xff1a;校园圈子系统小程序&#xff0c;校园拼车&#xff0c;校…

Netty Review - StringEncoder字符串编码器和StringDecoder 解码器的使用与源码解读

文章目录 概念概述StringEncoderStringDecoder Code源码分析StringEncoderStringDecoder 小结 概念 概述 Netty是一个高性能的网络应用程序框架&#xff0c;它提供了丰富的功能&#xff0c;包括编解码器&#xff0c;这些编解码器用于在网络中发送和接收数据时进行数据的编码和…

mac电脑安装虚拟机教程

1、准备一台虚拟机&#xff0c;安装CentOS7 常用的虚拟化软件有两种&#xff1a; VirtualBoxVMware 这里我们使用VirtualBox来安装虚拟机&#xff0c;下载地址&#xff1a;Downloads – Oracle VM VirtualBox 001 点击安装 002 报错&#xff1a;he installer has detected an…

uni-app 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…

在Windows系统平台下部署运行服务端Idea工程的jar服务

前言 目前云原生docker等技术&#xff0c;加上部署流水线大大的简化了各种流程&#xff0c;我们后端开发的人员只需要提交代码后&#xff0c;构建、部署、测试、发布等环节都无需人员接入&#xff0c;完全的自动化交付了。那么你肯定不禁想问&#xff0c;如题的需求不是点击一…