读取二进制文件 C++

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6162601/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:35:14  来源:igfitidea点击:

Read binary file c++

c++filebinary

提问by Emil

I'm trying to read an image into a char array. Here is my try:

我正在尝试将图像读入字符数组。这是我的尝试:

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

And this is the output:

这是输出:

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

Can anyone explain this to me? Is there an end-of-file char at position 8? This example was taken from cplusplus.com

任何人都可以向我解释这一点吗?位置 8 处是否有文件结尾字符?这个例子取自cplusplus.com

Running Mac OS X and compiling with XCode.

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

回答by Alok Save

  1. Returns the size of the file. size of your image.pngis 1944 bytes.

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

  2. Returns the sizeof(char*), which is 8on your environment. Note that size of any pointer is always the same on any environment.

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

  3. The file you are reading is a binary file so it might contain 0as a valid data. When you use strlen, it returns the length until a 0is encountered, which in the case of your file is 8.

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

  4. Returns the character at the 56th location(remember array indexing starts from 0) from start of file.

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

  1. 返回文件的大小。你的尺寸image.png1944 bytes.

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

  2. 返回sizeof(char*),8位于您的环境中。请注意,任何指针的大小在任何环境中始终相同。

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

  3. 您正在读取的文件是一个二进制文件,因此它可能包含0有效数据。当您使用 时strlen,它会返回长度,直到0遇到 a,就您的文件而言,它是8.

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

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

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

A suggestion:

一条建议:

Do remember to deallocate the dynamic memory allocation for fileContentsusing:

请记住释放动态内存分配以fileContents使用:

delete[] fileContents;

if you don't, you will end up creating a memory leak.

如果你不这样做,你最终会造成内存泄漏

回答by Geoffrey Elliott

fileSize - the number of bytes in the file.

fileSize - 文件中的字节数。

sizeof( fileContents ) - returns the size of a char* pointer.

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

strlen( fileContents) - counts the number of characters until a character with a value of '0' is found. That is apparently after just 8 characters - since you are reading BINARY data this is not an unexpected result.

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

cout << fileContents - like strlen, cout writes out characters until one with a value of '0' is found. From the output it looks like some of the characters aren't printable.

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

Your example has some other issues - it doesn't free the memory used, for example. Here's a slightly more robust version:

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

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

回答by Bj?rn Pollex

This answerof mine to another question should be exactly what you are looking for (especially the second part about reading it into a vector<char>, which you should prefer to an array.

这个答案我的另外一个问题应该是你在寻找什么(尤其是第二部分关于阅读它变成一个vector<char>,你应该更喜欢到一个数组。

As for your output:

至于你的输出:

  • sizeof(fileContents)return the size of a char *, which is 8 on your system (64 bit I guess)
  • strlenstops at the first '\0', just as the output operator does.
  • sizeof(fileContents)返回 a 的大小,char *在您的系统上为 8(我猜是 64 位)
  • strlen停在 first '\0',就像输出运算符一样。

回答by dragon135

What do you expect? png files are binary so they may contain '\0'character (character having numeric value 0) somewhere.

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

If you treat the png file contents as string ('\0' terminated array of characters) and print it as string then it will stop after encountering the first '\0'character.

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

So there is nothing wrong with the code, fileContentsis correctly contains the png file (with size 1944 bytes)

所以代码没有问题,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

回答by sarat

It's a good practice to use unsigned char to use with binary data. The character randomly selected might not be displayed properly in the console window due to the limitations in the fonts supported. Also you can verify the same thing by printing it in hexadecimal and open the same file in a hex editor to verify it. Please don't forget to delete the memory allocated after use.

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