我想了解读取二进制文件如何在C ++中工作。 我的代码:
int main() {
ifstream ifd("input.png",ios::binary |ios::ate);
int size = ifd.tellg();
ifd.seekg(0, ios::beg);
vector<char> buffer;
buffer.reserve(size);
ifd.read(buffer.data(), size);
cout << buffer.data();
return 0;
}
我认为如果我输入我的缓冲区,我会得到二进制的结果,但事实并非如此。
My output is: ˙Ř˙á6Exif
如果我读取文本文件,它会以正常形式显示不是二进制文本的文本。显然我的逻辑不正确。 如何将文件读取到缓冲区以使其包含二进制值? 附:我这样做是为了实现Shannon-Fano算法,所以如果有人对阅读二进制文件有任何建议,我将不胜感激。
答案 0 :(得分:3)
您需要调整矢量大小,而不是保留它:
int main()
{
ifstream ifd("input.png", ios::binary | ios::ate);
int size = ifd.tellg();
ifd.seekg(0, ios::beg);
vector<char> buffer;
buffer.resize(size); // << resize not reserve
ifd.read(buffer.data(), size);
cout.write(buffer.data(), buffer.size()); // you cannot just output buffer to cout as the buffer won't have '\0' ond-of-string terminator
}
否则,您的代码会尝试将size
个字符读入空缓冲区。您也可以使用设置矢量大小的矢量构造函数:vector<char> buffer(size);
您可以这样输出缓冲区的字节值:
void dumpbytes(const vector<char>& v)
{
for (int i=0; i<v.size(); ++i)
{
printf("%u ", (unsigned char)v[i]);
if ((i+1) % 16 == 0)
printf("\n");
}
printf("\n");
}
或类似于十六进制输出的常见十六进制编辑器:
void dumphex(const vector<char>& v)
{
const int N = 16;
const char hex[] = "0123456789ABCDEF";
char buf[N*4+5+2];
for (int i = 0; i < v.size(); ++i)
{
int n = i % N;
if (n == 0)
{
if (i)
puts(buf);
memset(buf, 0x20, sizeof(buf));
buf[sizeof(buf) - 2] = '\n';
buf[sizeof(buf) - 1] = '\0';
}
unsigned char c = (unsigned char)v[i];
buf[n*3+0] = hex[c / 16];
buf[n*3+1] = hex[c % 16];
buf[3*N+5+n] = (c>=' ' && c<='~') ? c : '.';
}
puts(buf);
}
缓冲区带有“Hello World!”数据将按如下方式打印:
48 65 6C 6C 6F 20 57 6F 72 6C 64 21 Hello World!
答案 1 :(得分:1)
以二进制模式打开文件意味着您的操作系统不能透明地翻译CR / LF / CRLF格式之间的行结尾。
它对计算机如何打印字符串没有任何影响,七行之后。我不知道&#34;得到的结果是二进制&#34;意思是,但我建议通过以十六对形式表示一次一个地打印其组成字节来渲染vector<char>
的内容:
std::cout << std::hex << std::setfill('0');
for (const auto byte : buffer)
std::setw(2) << byte;
输出结果如下:
0123456789abcdef0123456789abcdef
使用base-16(或&#34; hex&#34;)数值系统,每两个字符代表数据中一个字节的0-255字节值。这是非文本信息的常见表示。
或者,you could output the data in base-2(字面意思是&#34;二进制&#34;)。
由您决定如何呈现信息。文件打开模式与矢量无关。
您还需要修复矢量的大小;当您打算.reserve
时,请拨打.resize
。
答案 2 :(得分:1)
根据Pavel回答,您还可以添加此内容以查看实际二进制数据,即0
和1
s。不要忘记包含bitset标题。
void dumpbin(const vector<char>& v)
{
for (int i = 0; i < v.size(); ++i)
{
cout <<bitset<8>((unsigned char)(v[i])) << " ";
if ((i + 1) % 8 == 0)
printf("\n");
}
}