fstream跳过位图中未读取的字符

4

我正在尝试使用fstream读取bmp文件。

然而,它会跳过08和0E(十六进制)之间的值。

例如,对于以下值:

42 4d 8a 16 0b 00 00 00 00 00 36

它只会读取:

42 4d 8a 16 00 00 00 00 00 36

就好像文档中不存在0b一样。

该怎么办?

代码:

ifstream in;
in.open("ben.bmp", ios::binary);
unsigned char a='\0';
ofstream f("s.txt");
while(!in.eof())
{
    in>>a;
    f<<a;
}

编辑:使用 in.read(a,1); 而不是 in>>a; 可以解决读取问题,但我需要写无符号字符,并且 f.write(a,1); 不接受无符号字符。有没有人有一个函数可以用来写无符号字符?


请贴出能够说明问题的代码。 - anon
">>" 运算符会跳过空格。 - Martin York
看起来你正在尝试以“十六进制”值读取文件。在使用流之前不要忘记插入“hex”操作器。 - Khaled Alshaya
7个回答

7
如果您想逐字节读取文件,使用istream缓冲区迭代器是一个不错的选择。
int main()
{
   ifstream in("ben.bmp", ios::binary);  
   ofstream f("s.txt");  

   //
   // Note: this is NOT istream_iterator
   // The major different is that the istreambuf_iterator does not skip white space.
   //
   std::istreambuf_iterator<char>  loop(in);
   std::istreambuf_iterator<char>  end;

   for(; loop != end; ++loop)
   {
       f << (*loop);  
   }

   // You could now also use it with any of the std algorithms
       // Alternative to Copy input to output
            std::copy(loop,end,std::ostream_iterator<char>(f));

       // Alternative if you want to do some processing on each element
       // The HighGain_FrequencyIvertModulator is a functor that will manipulate each char.
            std::transform( loop,
                            end,
                            std::ostream_iterator<char>(f),
                            HighGain_FrequencyIvertModulator()
                          );
}  

6

有几个问题:

while(!in.eof())
{
    in>>a;
    f<<a;
}

直接读取文件不是正确的方法 - 需要检查读取是否成功:

while( in >> a)
{
    f<<a;
}

第二,如果你想以二进制模式读取文件,则需要使用read()和相关函数 - 无论文件以何种模式打开,>>操作符始终执行格式化(非二进制)输入。 编辑:写入将需要转换类型:
unsigned char c = 42;
out.write( (char *) & c, 1 );

6
operator>>operator<<是用于文本输入输出的。对于二进制文件,请使用read()write()

4

这是因为流将字节解释为ASCII字符。08到0e是空格(水平制表符、换行符、垂直制表符、回车符等),被跳过了。就像其他答案所说,您需要使用流的read()方法。


3
#include <fstream>
#include <iostream>
#include <string>

int main(int argc, char *argv[])
{
  const char *bitmap;
  const char *output = "s.txt";

  if (argc < 2)
    bitmap = "ben.bmp";
  else
    bitmap = argv[1];

  std::ifstream  in(bitmap, std::ios::in  | std::ios::binary);
  std::ofstream out(output, std::ios::out | std::ios::binary);
  char a;

  while (in.read(&a, 1) && out.write(&a, 1))
    ;

  if (!in.eof() && in.fail())
    std::cerr << "Error reading from " << bitmap << std::endl;

  if (!out)
    std::cerr << "Error writing to "   << output << std::endl;

  return 0;
}

明白了。我们在read()中没有使用&,这可能导致了问题。再次感谢! - Dunya Degirmenci
虽然这个答案不错,但如果你使用迭代器和算法来进行概述(由马丁提出),阅读和编写可能会更容易。 - GManNickG

1

在处理二进制数据时,使用read()而不是重载的位运算符(<<和>>)

如果需要使用流,可以像这样做:

std::ifstream ifs("bar", std::ios::in | std::ios::binary);
std::ofstream ofs("foo", std::ios::out | std::ios::binary);
ofs << ifs.rdbuf();

0

请确保您将其作为二进制文件打开,如下所示:

ifstream ifs('input.bin', ios::in | ios::binary);

ofstream ofs('output.bin', ios::out | ios::binary);

另外一个好的实践是检查ifs.good()以确保您打开的文件一切正常


1
没有,没有任何作用。 - Dunya Degirmenci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接