读取二进制文件c ++

时间:2011-05-28 15:33:53

标签: c++ file binary

我正在尝试将图像读入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进行编译。

5 个答案:

答案 0 :(得分:10)

  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;

  5. 建议:

    请记得使用以下内容取消分配fileContents的动态内存分配:

    delete[] fileContents;
    

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

答案 1 :(得分:3)

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

至于你的输出:

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

答案 2 :(得分:3)

fileSize - 文件中的字节数。

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

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

cout&lt;&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 ];
}

答案 3 :(得分:2)

你期待什么? 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

答案 4 :(得分:0)

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