读取文件并保存完全相同的文件c ++
Reading a file and saving the same exact file c++
我实际上正在编写一个 c++ 程序,它可以读取任何类型的文件并将其保存为 bmp 文件,但首先我需要读取文件,这就是问题所在
char fileName[] = "test.jpg";
FILE * inFileForGettingSize;//This is for getting the file size
fopen_s(&inFileForGettingSize, fileName, "r");
fseek(inFileForGettingSize, 0L, SEEK_END);
int fileSize = ftell(inFileForGettingSize);
fclose(inFileForGettingSize);
ifstream inFile;//This is for reading the file
inFile.open(fileName);
if (inFile.fail()) {
cerr << "Error Opening File" << endl;
}
char * data = new char[fileSize];
inFile.read(data, fileSize);
ofstream outFile;//Writing the file back again
outFile.open("out.jpg");
outFile.write(data, fileSize);
outFile.close();
cin.get();
但是当我读取文件时,假设它是一个纯文本文件,它总是在末尾输出一些奇怪的字符,例如:
assdassaasd
sdaasddsa
sdadsa
传递给:
assdassaasd
sdaasddsa
sdadsaÍÍÍ
因此,当我使用 jpg、exe 等执行此操作时,它会损坏它。
我不是要复制文件,我知道还有其他方法,我只是想每个字节读取一个完整的文件字节。谢谢
编辑:
我发现那些“Í”等于文件的结束行数,但这对我帮助不大
这是由newline handling造成的。
您以文本模式打开文件(因为您对 fopen
使用 "r"
而不是 "rb"
,并且因为您没有将 ios::binary
传递给 fstream
open
调用),在 Windows 上,文本模式将 "\r\n"
对在读取时转换为 "\n"
,在写入时转换回 "\r\n"
。结果是内存中的大小将小于磁盘上的大小,因此当您尝试使用磁盘上的大小进行写入时,您会越过数组的末尾并写入任何随机的东西在记忆中。
处理二进制数据时需要以二进制模式打开文件:
fopen_s(&inFileForGettingSize, fileName, "rb");
inFile.open(fileName, ios::binary);
outFile.open("out.jpg", ios::binary);
为了将来参考,您的复制例程可以改进。将 FILE*
I/O 与 iostream
I/O 混合感觉很尴尬,打开和关闭文件两次是额外的工作,而且(最重要的是)如果你的例程是 运行 在一个足够大的文件上,它会耗尽内存试图将整个文件加载到 RAM 中。一次复制一个块会更好:
const int BUFFER_SIZE = 65536;
char buffer[BUFFER_SIZE];
while (source.good()) {
source.read(buffer, BUFFER_SIZE);
dest.write(buffer, source.gcount());
}
它是一个二进制文件,所以你需要以二进制的方式读写文件;否则它被视为文本,并假定有需要翻译的换行符。
在调用 fopen() 时,您需要添加 "b" 指示符:
fopen_s(&inFileForGettingSize, fileName, "rb");
并且在您的 fstream::open 调用中,您需要添加 std::fstream::binary:
inFile.open(fileName, std::fstream::binary);
// ...
outFile.open("out.jpg", std::fstream::binary);
我实际上正在编写一个 c++ 程序,它可以读取任何类型的文件并将其保存为 bmp 文件,但首先我需要读取文件,这就是问题所在
char fileName[] = "test.jpg";
FILE * inFileForGettingSize;//This is for getting the file size
fopen_s(&inFileForGettingSize, fileName, "r");
fseek(inFileForGettingSize, 0L, SEEK_END);
int fileSize = ftell(inFileForGettingSize);
fclose(inFileForGettingSize);
ifstream inFile;//This is for reading the file
inFile.open(fileName);
if (inFile.fail()) {
cerr << "Error Opening File" << endl;
}
char * data = new char[fileSize];
inFile.read(data, fileSize);
ofstream outFile;//Writing the file back again
outFile.open("out.jpg");
outFile.write(data, fileSize);
outFile.close();
cin.get();
但是当我读取文件时,假设它是一个纯文本文件,它总是在末尾输出一些奇怪的字符,例如:
assdassaasd
sdaasddsa
sdadsa
传递给:
assdassaasd
sdaasddsa
sdadsaÍÍÍ
因此,当我使用 jpg、exe 等执行此操作时,它会损坏它。 我不是要复制文件,我知道还有其他方法,我只是想每个字节读取一个完整的文件字节。谢谢
编辑:
我发现那些“Í”等于文件的结束行数,但这对我帮助不大
这是由newline handling造成的。
您以文本模式打开文件(因为您对 fopen
使用 "r"
而不是 "rb"
,并且因为您没有将 ios::binary
传递给 fstream
open
调用),在 Windows 上,文本模式将 "\r\n"
对在读取时转换为 "\n"
,在写入时转换回 "\r\n"
。结果是内存中的大小将小于磁盘上的大小,因此当您尝试使用磁盘上的大小进行写入时,您会越过数组的末尾并写入任何随机的东西在记忆中。
处理二进制数据时需要以二进制模式打开文件:
fopen_s(&inFileForGettingSize, fileName, "rb");
inFile.open(fileName, ios::binary);
outFile.open("out.jpg", ios::binary);
为了将来参考,您的复制例程可以改进。将 FILE*
I/O 与 iostream
I/O 混合感觉很尴尬,打开和关闭文件两次是额外的工作,而且(最重要的是)如果你的例程是 运行 在一个足够大的文件上,它会耗尽内存试图将整个文件加载到 RAM 中。一次复制一个块会更好:
const int BUFFER_SIZE = 65536;
char buffer[BUFFER_SIZE];
while (source.good()) {
source.read(buffer, BUFFER_SIZE);
dest.write(buffer, source.gcount());
}
它是一个二进制文件,所以你需要以二进制的方式读写文件;否则它被视为文本,并假定有需要翻译的换行符。
在调用 fopen() 时,您需要添加 "b" 指示符:
fopen_s(&inFileForGettingSize, fileName, "rb");
并且在您的 fstream::open 调用中,您需要添加 std::fstream::binary:
inFile.open(fileName, std::fstream::binary);
// ...
outFile.open("out.jpg", std::fstream::binary);