我实际上正在编写一个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();
但是当我读取文件时,让我们说它是一个plainttext文件,它总是在最后输出一些奇怪的字符,例如:
assdassaasd
sdaasddsa
sdadsa
传递给:
assdassaasd
sdaasddsa
sdadsaÍÍÍ
因此,当我使用jpg,exe等执行此操作时,它会破坏它。 我不是要复制文件,我知道还有其他方法,我只想尝试每个字节读取一个完整的文件字节。感谢。
编辑:
我发现那些'Í'等于文件的结束行数,但这对我没什么帮助
答案 0 :(得分:3)
这是由newline handling引起的。
您以文本模式打开文件(因为"r"
使用"rb"
代替fopen
,因为您没有将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());
}
答案 1 :(得分:1)
这是一个二进制文件,所以你需要读取和写入二进制文件;否则它被视为文本,并假设有需要翻译的换行符。
在你对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);