繁体   English   中英

读取二进制文件 c++

[英]Read binary file 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;
}

这是 output:

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

谁能给我解释一下? position 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的动态 memory 分配:

delete[] fileContents;

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

我对另一个问题的回答应该正是您正在寻找的(尤其是关于将其读入vector<char>的第二部分,您应该更喜欢数组。

至于你的 output:

  • sizeof(fileContents)返回char *的大小,在您的系统上为 8(我猜是 64 位)
  • strlen在第一个'\0'处停止,就像 output 运算符一样。

fileSize - 文件中的字节数。

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

strlen(fileContents) - 计算字符数,直到找到值为“0”的字符。 这显然是在 8 个字符之后 - 因为您正在读取 BINARY 数据,所以这不是一个意外的结果。

cout << fileContents - 与 strlen 类似,cout 会写出字符,直到找到值为 '0' 的字符。 从 output 看来,有些字符无法打印。

您的示例还有一些其他问题 - 例如,它不会释放使用的 memory。 这是一个更强大的版本:

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

你能指望什么? png 文件是二进制文件,因此它们可能在某处包含'\0'字符(数值为 0 的字符)。

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

所以代码没有问题, 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 '\0' (numeric 0)
random: ?  // the 56th character in the png file
?PNG       // the 5th-8th character is not printable, the 9th character is '\0' so cout stop here

使用 unsigned char 处理二进制数据是一个很好的做法。 由于受支持的 fonts 的限制,随机选择的字符可能无法在控制台 window 中正确显示。 您也可以通过以十六进制打印来验证相同的内容,并在十六进制编辑器中打开相同的文件来验证它。 请不要忘记删除使用后分配的 memory。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM