【问题标题】:Read a binary file (jpg) to a string using c++使用c ++将二进制文件(jpg)读取为字符串
【发布时间】:2013-07-11 03:56:20
【问题描述】:

我需要将 jpg 文件读取为字符串。我想将此文件上传到我们的服务器,我只是发现 API 需要一个字符串作为此图片的数据。我遵循了我之前问过Upload pics to a server using c++ 的问题中的建议。

int main() {
    ifstream fin("cloud.jpg");
    ofstream fout("test.jpg");//for testing purpose, to see if the string is a right copy
    ostringstream ostrm;

    unsigned char tmp;
    int count = 0;
    while ( fin >> tmp ) {
        ++count;//for testing purpose
        ostrm << tmp;
    }
    string data( ostrm.str() );
    cout << count << endl;//ouput 60! Definitely not the right size
    fout << string;//only 60 bytes
    return 0;
}

为什么它在 60 处停止? 60岁是一个奇怪的字符,我应该怎么做才能将jpg读取到字符串?

更新

差不多了,但是在使用建议的方法后,当我将字符串重写到输出文件时,它会失真。发现我还应该通过ofstream::binary 指定ofstream 处于二进制模式。完成!

顺便问一下ifstream::binaryios::binary有什么区别,ofstream::binary有什么缩写吗?

【问题讨论】:

  • ifstream::binaryios::binary 没有区别,甚至ofstream::binary 也没有区别。 binary 定义在 ios_base 类中,它是所有 iostream 类的根。 iosbasic_ios&lt;char&gt; 的 typedef,它是层次结构中介于 ios_baseistream/ostream 之间的类。我倾向于使用它,因为它很容易输入。您可以将ios::binary 用于ifstreamofstream。您甚至可以将ifstream::binary 用于ofstream,反之亦然。

标签: c++ file-upload file-io


【解决方案1】:

以二进制模式打开文件,否则会出现可笑的行为,并且会以不恰当的方式处理某些非文本字符,至少在 Windows 上是这样。

ifstream fin("cloud.jpg", ios::binary);

此外,您可以一次读取整个文件,而不是 while 循环:

ostrm << fin.rdbuf();

【讨论】:

    【解决方案2】:

    您不应该将文件读取为字符串,因为 jpg 包含 0 值是合法的。但是在字符串中,值 0 具有特殊含义(它是字符串指示符的结尾,即 \0) .您应该改为将文件读入向量。您可以像这样轻松地做到这一点:

    #include <algorithm>
    #include <iostream>
    #include <fstream>
    #include <vector>
    
    int main(int argc, char* argv[])
    {
        std::ifstream ifs("C:\\Users\\Borgleader\\Documents\\Rapptz.h");
    
        if(!ifs)
        {
            return -1;
        }
    
        std::vector<char> data = std::vector<char>(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
    
        //If you really need it in a string you can initialize it the same way as the vector
        std::string data2 = std::string(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>());
    
        std::for_each(data.begin(), data.end(), [](char c) { std::cout << c; });
    
        std::cin.get();
        return 0;
    }
    

    【讨论】:

    • 虽然 C 风格的字符串不能包含 \0,但 std::string 可以(虽然你基本上是对的 -- std::string 确实不是二进制数据的正确选择)。
    • @JerryCoffin 但是 api 需要一个字符串:const string &amp;data: the raw data of the photo to be uploaded
    • @zoujyjs 我编辑了代码示例以包含如何初始化字符串。它的工作方式与矢量相同。
    • @zoujyjs:你可能别无选择,如果是这样,这就是生活。未来仍然需要记住一些事情(至少在我看来)。
    【解决方案3】:

    尝试以二进制模式打开文件:

    ifstream fin("cloud.jpg", std::ios::binary);
    

    猜测,您可能试图在 Windows 上读取文件,而第 61st 字符可能是 0x26——一个 control-Z,(在 Windows 上)将被视为标记文件结束。

    就如何最好地进行阅读而言,您最终会在简单性和速度之间做出选择,如 a previous answer 所示。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-25
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 2013-09-26
      • 2010-09-12
      相关资源
      最近更新 更多