C/C++编程:复制整个文件或文件的一半
代码思路:在copyFile.cpp中编写两个函数copyWholeFile和copyHalfOfFile,分别实现复制整个文件和文件一半的功能,然后在main.cpp中调用这两个函数。
copyFile.h
#ifndef _COPYFILE_H_
#define _COPYFILE_H_
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void copyWholeFile(const string &srcFilePath, const string &dstFilePath);
void copyHalfOfFile(const string &srcFilePath, const string &dstFilePath);
#endif
copyFile.cpp
#include "copyFile.h"
void copyWholeFile(const string &srcFilePath, const string &dstFilePath)
{
ifstream src(srcFilePath, ios::binary);
if (!src)
{
cerr << "Failed to open source file: " << srcFilePath << '\n';
return;
}
ofstream dst(dstFilePath, ios::binary);
if (!dst)
{
cerr << "Failed to open destination file: " << dstFilePath << '\n';
return;
}
dst << src.rdbuf();
src.close();
dst.close();
cout << "File copied successfully.\n";
}
void copyHalfOfFile(const string &srcFilePath, const string &dstFilePath)
{
ifstream src(srcFilePath, ios::binary);
if (!src)
{
cerr << "Failed to open source file: " << srcFilePath << '\n';
return;
}
// 获取源文件大小
src.seekg(0, ios::end); // 将输入流src的位置指针移动到文件的末尾,偏移量为0
long fileSize = src.tellg(); // 将位置指针移动到文件末尾后,使用tellg()函数获取当前的位置
src.seekg(0, ios::beg); // 将输入流的位置指针重新定位到文件的开始位置,且偏移量未0,ios::beg指定参考点为文件开头
if (fileSize <= 0)
{
cerr << "Invalid file size.\n";
return;
}
// 计算要复制的字节数(向下取整到最接近的一半)
long halfSize = fileSize / 2;
ofstream dst(dstFilePath, ios::binary);
if (!dst)
{
cerr << "Failed to open target file: " << dstFilePath << '\n';
return;
}
/*
**min<long>() 是一个函数调用,用于返回两个给定数值中较小的一个。避免缓冲区溢出错误OR如果需要处理的数据量(halfSize)
小于缓冲区大小,只读取实际需要的数据量,提高效率并避免不必要的内存使用。
**从输入流src中读取bytesToRead个字节的数据到buffer中。
**从缓冲区buffer中取出前bytesToRead个字节的数据,并将这些数据写入到输出流dst中.static_cast用于安全地将bytesToRead的类型从long转换为
streamsize,以确保类型兼容性
**如果 halfSize>buffer 会再次进入循环,直到所有需要的数据都被处理完毕。
*/
char buffer[4096] = {0};
while (halfSize > 0)
{
long bytesToRead = min<long>(sizeof(buffer), halfSize);
src.read(buffer, bytesToRead);
dst.write(buffer, static_cast<streamsize>(bytesToRead));
halfSize -= bytesToRead;
}
src.close();
dst.close();
cout << "Half of the file copied successfully.\n";
}
main.c
#include "copyFile.h"
int main() {
cout<<"选择mode(half or whole)后输入源路径和目标路径"<<endl;
cout<<"输入示例:half /path to the source file /path to the target file"<<endl;
string mode;
string srcFilePath;
string dstFilePath;
cin>>mode>>srcFilePath>>dstFilePath;
if (mode == "whole") {
copyWholeFile(srcFilePath, dstFilePath);
} else if (mode == "half") {
copyHalfOfFile(srcFilePath, dstFilePath);
} else {
cerr << "Invalid mode. Use either 'whole' or 'half'.\n";
return 1;
}
return 0;
}
编译规则见Makefile
Makefile
CC = g++
LDFLAGS = -lpthread -lm
TARGET = ./bin/main #目标可执行文件的路径和名称,位于./bin/main
INCLUDE_PATH = -I ./inc #从./inc目录下查找头文件
SOURCE_FILES = $(wildcard ./src/*.cpp) #使用wildcard函数自动找出./src/目录下所有的.cpp源文件
OBJECTS = $(patsubst ./src/%.cpp, ./obj/%.o, $(SOURCE_FILES)) #通过patsubst函数将每个源文件路径转换为对应的obj文件路径,存放在./obj/目录
$(TARGET): $(OBJECTS)
$(CC) $^ -o $@ $(INCLUDE_PATH) $(LDFLAGS)
# 生成.o文件的规则,放到./obj目录下
./obj/%.o: ./src/%.cpp
$(CC) -c $< -o $@ $(INCLUDE_PATH)
clean:
$(RM) $(TARGET) $(OBJECTS)
.PHONY: clean
代码量比较小,其实可以不用分成三个文件来写,但还是希望大家在编程学习的过程中养成模块化的思想。