读取二进制文件c++



我正在尝试将图像读取到char数组中。这是我的尝试:

ifstream file ("htdocs/image.png", ios::in | ios::binary | ios::ate);
ifstream::pos_type fileSize;
char* fileContents;
if(file.is_open())
{
    fileSize = file.tellg();
    fileContents = new char[fileSize];
    file.seekg(0, ios::beg);
    if(!file.read(fileContents, fileSize))
    {
        cout << "fail to read" << endl;
    }
    file.close();
                
    cout << "size: " << fileSize << endl;
    cout << "sizeof: " << sizeof(fileContents) << endl;
    cout << "length: " << strlen(fileContents) << endl;
    cout << "random: " << fileContents[55] << endl;
    cout << fileContents << endl;
}

这就是输出:

size: 1944
sizeof: 8
length: 8
random: ?
?PNG

有人能向我解释一下吗?位置8处是否有文件末尾字符?此示例取自cplusplus.com

运行Mac OS X并使用XCode进行编译。

  1. 返回文件的大小。image.png的大小是1944 bytes

    cout << "size: " << fileSize << endl;

  2. 返回sizeof(char*),即环境中的8请注意,在任何环境中,任何指针的大小都是相同的

    cout << "sizeof: " << sizeof(fileContents) << endl;

  3. 您正在读取的文件是一个二进制文件,因此它可能包含0作为有效数据。当您使用strlen时,它会返回遇到0之前的长度,如果您的文件是8

    cout << "length: " << strlen(fileContents) << endl;

  4. 返回文件开头的56th location(记住数组索引从0开始)处的字符。

    cout << "random: " << fileContents[55] << endl;

建议:

请记住使用: 解除分配fileContents的动态内存分配

delete[] fileContents;

如果不这样做,您最终将创建内存泄漏

fileSize-文件中的字节数。

sizeof(fileContents)-返回char*指针的大小。

strlen(fileContents)-统计字符数,直到找到值为"0"的字符为止。这显然是在8个字符之后——因为您正在读取二进制数据,所以这不是一个意外的结果。

cout<lt;fileContents-像strlen一样,cout写出字符,直到找到值为"0"的字符。从输出中看,有些字符似乎无法打印。

您的示例还有一些其他问题——例如,它没有释放所使用的内存。这里有一个稍微健壮一点的版本:

vector< char > fileContents;
{
  ifstream file("htdocs/image.png", ios::in | ios::binary | ios::ate);
  if(!file.is_open())
    throw runtime_error("couldn't open htdocs/image.png");
  fileContents.resize(file.tellg());
  file.seekg(0, ios::beg);
  if(!file.read(&fileContents[ 0 ], fileContents.size()))
    throw runtime_error("failed to read from htdocs/image.png");
}
cout << "size: " << fileContents.size() << endl;
cout << "data:" << endl;
for( unsigned i = 0; i != fileContents.size(); ++i )
{
  if( i % 65 == 0 )
    cout << L"n';
  cout << fileContents[ i ];
}

我对另一个问题的回答应该正是你想要的(尤其是关于将其读入vector<char>的第二部分,你应该更喜欢它而不是数组

至于你的输出:

  • sizeof(fileContents)返回char *的大小,在您的系统中为8(我猜是64位)
  • strlen在第一个''处停止,就像输出操作符一样

您期待什么?png文件是二进制的,因此它们可能在某个地方包含''字符(具有数值0的字符)。

如果将png文件内容视为字符串('' terminated array of characters)并将其打印为字符串,则它将在遇到第一个''字符后停止。

所以代码没有错,fileContents正确地包含png文件(大小为1944字节)

size: 1944 // the png is 1944 bytes
sizeof: 8  // sizeof(fileContents) is the sizeof a pointer (fileContents type is char*) which is 8 bytes
length: 8  // the 9th character in the png file is '' (numeric 0)
random: ?  // the 56th character in the png file
?PNG       // the 5th-8th character is not printable, the 9th character is '' so cout stop here

使用无符号字符与二进制数据一起使用是一种很好的做法。由于所支持字体的限制,随机选择的字符可能无法在控制台窗口中正确显示。您也可以通过十六进制打印来验证相同的东西,并在十六进制编辑器中打开相同的文件来验证它。请不要忘记删除使用后分配的内存。

相关内容

  • 没有找到相关文章

最新更新