Fstream пропуская символы без чтения в растровом - PullRequest
3 голосов
/ 09 января 2010

Я пытаюсь прочитать файл bmp, используя fstream. Однако он пропускает значения между 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); не принимает неподписанные символы. У кого-нибудь есть функция для написания символов без знака?

Ответы [ 7 ]

7 голосов
/ 09 января 2010

Если вы хотите читать файл по одному байту за раз, это хорошее применение для итератора буфера 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 голосов
/ 09 января 2010

operator>> и operator<< предназначены для ввода и вывода текста.

Для двоичных файлов используйте read() и write().

6 голосов
/ 09 января 2010

Несколько выпусков:

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

неправильный способ чтения файла - вам нужно проверить, работает ли чтение:

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

Во-вторых, если вы хотите прочитать файл в двоичном режиме, вам нужно использовать функции read () и связанные с ними функции - оператор >> всегда будет выполнять форматированный (недвоичный) ввод независимо от того, в каком режиме находится файл открыт в.

Редактировать: для записи понадобится приведение:

unsigned char c = 42;
out.write( (char *) & c, 1 );
4 голосов
/ 09 января 2010

Это потому, что поток интерпретирует байты как символы ascii. От 08 до 0e - пробелы (горизонтальная табуляция, новая строка, вертикальная табуляция, возврат каретки и т. Д.), Которые пропускаются. Как и в других ответах, вам нужно использовать метод потока read ().

2 голосов
/ 09 января 2010
#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;
}
1 голос
/ 09 января 2010

При работе с двоичными данными используйте 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 голосов
/ 09 января 2010

Убедитесь, что вы открываете его как двоичный файл, например:

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

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

также рекомендуется проверить ifs.good(), чтобы убедиться, что все в порядке с файлом, который вы открыли

...