【问题标题】:Reading and Writing any file in C++用 C++ 读写任何文件
【发布时间】:2021-09-16 07:08:38
【问题描述】:

我有一个程序需要对不同类型的文件进行操作。 我希望下面程序的输入和输出文件是一样的。

#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] != '\0')
        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 将二进制转换为十六进制,但缺点是整体大小翻了一番。因此,我只想以二进制方式操作。

【问题讨论】:

  • 不确定您是否应该检查 '\0' 您的二进制文件不是字符串,因此此处不适用空终止符。我建议将字节读入 std::vector 并从你的函数中返回它并使用向量的大小写出数据
  • 这也避免了内存泄漏:)
  • 您也可以使用std::string 来存储整个文件。 example

标签: c++ pdf file-io diff


【解决方案1】:
size_t len = fl.tellg();
char *ret = new char[len];

以这种方式显示的代码确定文件中的字符数。这可以。唯一的问题是,在读取了这么多的字符之后,这个非常重要的信息就被完全忘记并丢弃了。这个函数只返回这个ret指针,它的实际字符数现在是一个无法解开的谜。

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

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

这会尝试通过查找缓冲区中的第一个 0 字节来对字符数进行逆向工程。

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

或者文件可以只包含一个字符串“Hello world”,这个for 循环会很高兴地过去,然后在这个缓冲区之后开始在一些随机内存中查找,导致未定义的行为。

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

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

附: delete-ing ret 缓冲区,在你完成它之后,也是一个好主意。一个更好的主意是避免使用new,而是使用vector,它会很乐意在您请求时随时为您提供size(),您不必担心删除分配的内存。

【讨论】:

    【解决方案2】:

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

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-23
      • 2015-05-24
      • 2012-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多