用C++读写任何文件



我有一个程序,需要在其中操作不同类型的文件。我希望以下程序的输入和输出文件是相同的。

#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
typedef unsigned char u8;
using namespace std;
char* readFileBytes(string name)
{
ifstream fl(name);
fl.seekg( 0, ios::end );
size_t len = fl.tellg();
char *ret = new char[len];
fl.seekg(0, ios::beg); 
fl.read(ret, len);
fl.close();
return ret;
}

int main(int argc, char *argv[]){
string name = "file.pdf";
u8* file = (u8*) readFileBytes(name);
// cout<<str<<endl;
int len = 0; 
while(file[len] != '')
len++;
cout<<"FILESIZE : "<<len<<endl;

string filename = "file2.pdf";
ofstream outfile(filename,ios::out | ios::binary);
outfile.write((char*) file,len);        
outfile.close();
exit(0);
}

使用diff检查输出文件和输入文件之间的差异

diff file.pdf file2.pdf

我应该怎么做才能使file2.pdffile.pdf相同?

我曾尝试使用xxd将二进制文件更改为十六进制,但缺点是总大小加倍。所以我只想用二进制运算。

size_t len = fl.tellg();
char *ret = new char[len];

通过这种方式,显示的代码决定了文件中的字符数。这很好。它唯一的问题是,在读取了这么多字符后,这些非常重要的信息会被完全遗忘和丢弃。这个函数只返回这个ret指针,其中的实际字符数现在是一个无法解决的谜。

但随后,main()试图解开这个谜团如下:

int len = 0; 
while(file[len] != '')
len++;

这试图通过查找缓冲区中的第一个0字节来反向工程字符数。

这与任何事情都毫无关系。文件中的第一个字符可能是0字节,因此这将计算出文件是空的,而不是10 GB大小。

或者该文件可以仅包含字符串";Hello world";,这个for循环将愉快地通过,然后在这个缓冲区之后的一些随机存储器中开始扎根,导致未定义的行为。

这就是所示代码中致命的逻辑缺陷:文件的实际大小被丢弃,而是以一种有缺陷的方式进行反向工程。

您需要重新编写代码,这样文件中的字符数,即原始len,也会返回给main(),并且它会使用它,而不是试图猜测它最初是什么。

附言:delete——在使用完ret缓冲区后,使用它也是一个好主意。一个更好的想法是避免使用new,而是使用vector,这将很乐意在任何时候向您提供size(),而且您不必担心删除分配的内存。

为了正确处理二进制数据,必须存储大小,并且不能从sentinel null字节计算,因为null字节可以是二进制文件中的合法字节。因此,除了缓冲区之外,您还应该返回读取长度,或者更好地将每个缓冲区复制到新文件,直到您用完输入文件:

int main(int argc, char *argv[]){
constexpr size_t sz = 10240;           // size of buffer
char buffer[sz];
string name = "file.pdf";
string filename = "file2.pdf";
ifstream fl(name);
ofstream outfile(filename,ios::out | ios::binary);
int len = 0, buflen; 
for (;;) {
buflen = fl.read(buf, len);
if (buflen == 0) break;      // reached EOF
len += buflen;
if (buflen != outfile.write(buf, buflen)) {
// display an error message
return 1;
}
}
fl.close();
outfile.close()
cout<<"FILESIZE : "<<len<<endl;
exit(0);
}

相关内容

最新更新