0

我正在编写一些串行端口代码,需要将文件的内容(二进制)读取到变量中。从http://www.cplusplus.com/doc/tutorial/files/的“二进制文件”示例开始,我尝试打开一个 .jpg 文件:

#include <iostream>
#include <fstream>
using namespace std;

ifstream::pos_type size;
char * memblock;

int main () {
  ifstream file ("example.jpg", ios::in|ios::binary|ios::ate);
  if (file.is_open())
  {
    size = file.tellg();
    memblock = new char [size];
    file.seekg (0, ios::beg);
    file.read (memblock, size);
    file.close();

    cout << memblock << endl;

    delete[] memblock;
   }
 else cout << "Unable to open file";
 return 0;
}

但是,控制台中仅打印前 4 个字符(32 位)。

但特别奇怪的是,将 ostream::write() 与所谓的错误变量“memblock”一起使用可以完美地工作:

ofstream fileOut ("writtenFile.jpg",ios::out|ios::binary);
fileOut.write(memblock,size);
fileOut.close();

即它创建一个新的.jpg 文件。

所以我的问题是为什么 memblock 变量似乎只包含前 4 个字符。

4

2 回答 2

1

您的二进制数据中可能有一个 0。cout是一个文本流,所以memblock看成一个字符串。如果它到达一个空字符,那么它认为字符串已经完成。

有关输出二进制数据的一些帮助引脚,请参阅此内容: 如何使 cout 以二进制模式运行?

于 2012-05-09T06:14:33.650 回答
0

嗯。快速浏览您引用的页面表明作者对 C++ 中的 IO 了解不多。避免它,因为它所说的大部分内容都是错误的。

其余的:.jpg不是文本格式,不能简单地输出到cout. 当然,当您使用<<时,输出会在第一个 '\0'字符处停止,但各种二进制数据可能会导致奇怪的效果:数据可能被解释为重新定位光标的转义序列、锁定键盘(实际上发生在我身上一次)等.这些问题即使你使用也会出现std::cout.write()(不会停在'\0'字符上)。如果您想可视化数据,最好的选择是某种二进制转储。(我使用类似下面的东西来可视化大块数据:

template <typename InputIterator>
void
process(
    InputIterator       begin,
    InputIterator       end,
    std::ostream&       output = std::cout )
{
    IOSave              saveAndRestore( output ) ;
    output.setf( std::ios::hex, std::ios::basefield ) ;
    output.setf( std::ios::uppercase ) ;
    output.fill( '0' ) ;
    static int const    lineLength( 16 ) ;
    while ( begin != end ) {
        int                 inLineCount = 0;
        unsigned char       buffer[ lineLength ] ;
        while ( inLineCount != lineLength && begin != end ) {
            buffer[inLineCount] = *begin;
            ++ begin;
            ++ inLineCount;
        }
        for ( int i = 0 ; i < lineLength ; ++ i ) {
            static char const *const
                                separTbl [] =
            {
                " ", " ", " ", " ",
                "  ", " ", " ", " ",
                "   ", " ", " ", " ",
                "  ", " ", " ", " ",
            } ; 
            output << separTbl[ i ] ;
            if ( i < inLineCount ) {
                output << std::setw( 2 )
                       << static_cast< unsigned int >(buffer[ i ] & 0xFF) ) ;
            } else {
                output << "  " ;
            }
        }
        output << " |" ;
        for ( int i = 0 ; i != inLineCount ; ++ i ) {
            output << (i < lengthRead && isprint( buffer[ i ] )
                       ?   static_cast< char >( buffer[ i ] ) 
                       :   ' ') ;
        }
        output << '|' << std::endl ;
    }
}

(您还需要读入一个std::vector<char>,因此您不必担心释放内存。)

于 2012-05-09T08:17:04.003 回答