Russian Qt Forum

Qt => Общие вопросы => Тема начата: burunduk от Октябрь 25, 2005, 17:41



Название: Как можно читать данные из потока кусками по четыре бита ?
Отправлено: burunduk от Октябрь 25, 2005, 17:41
Формат файла так размечен и не могу придумать красивого решения. Есть идеи ?


Название: Как можно читать данные из потока кусками по четыре бита ?
Отправлено: QCasper от Октябрь 25, 2005, 23:24
А если считывать побайтно, а потом разбивать пополам, не катит?


Название: Как можно читать данные из потока кусками по четыре бита ?
Отправлено: Larrikin от Октябрь 26, 2005, 06:56
Код:

struct (
     unsigned field1 : 4;
     ) field;

Может так? Это структура блиной в 4 бита. Я сам не работал с битами, но у Кернигана Ричи написано именно так.


Название: Re: Как можно читать данные из потока кусками по четыре бита
Отправлено: Dair от Октябрь 26, 2005, 08:04
Цитата: "burunduk"
Формат файла так размечен и не могу придумать красивого решения. Есть идеи ?


я б сделал типа так:

Код:

class HalfByte {
  public:
    HalfByte();
    HalfByte( unsigned char v );
    HalfByte( const HalfByte& hb );
   
    const HalfByte& operator=(const HalfByte& hb );

    operator unsigned char() const { return data & 0x0F; }

  protected:
    unsigned char data;
};

class HalfByteStream: public QDataStream {
  public:
    ...
    HalfByteStream& operator>>(HalfByte& hb );
    HalfByteStream& operator<<(HalfByte hb );
};



ы?

да, из фалйа всё ж считывать побайтно, само собой.


Название: Re: Как можно читать данные из потока кусками по четыре бита
Отправлено: burunduk от Октябрь 26, 2005, 12:20
Идея мне понравилась, но только зачем нужен класс HalfByte ?  Половинку в четыре бита можно хранить и в стандартном типе - unsigned char.


Название: Re: Как можно читать данные из потока кусками по четыре бита
Отправлено: Dair от Октябрь 26, 2005, 12:24
Цитата: "burunduk"
Половинку в четыре бита можно хранить и в стандартном типе - unsigned char.


ну, это уже академически :-)

если перегружать оператор <<( unsigned char ) то возникнут проблемы при mixed reading.

А тут - отдельный тип и фсё.


Название: Re: Как можно читать данные из потока кусками по четыре бита
Отправлено: burunduk от Октябрь 26, 2005, 12:28
уже возникли :-)

Цитировать

если перегружать оператор <<( unsigned char ) то возникнут проблемы при mixed reading.


Название: Как можно читать данные из потока кусками по четыре бита ?
Отправлено: oktogen от Ноябрь 29, 2005, 10:57
QBitArray(QT4).


Название: Как можно читать данные из потока кусками по четыре бита ?
Отправлено: Dendy от Ноябрь 29, 2005, 23:06
Исправь, если неправильно понял.

Данные хранятся укомплектованно: 4 бита + 4 бита + 4 бита + ... .Ты хочешь считывать именно биты, а не байты (у которых полезная часть - младшая половина).

QBitArray тебе здесь не поможет, он нужен только для хранения данных, а не для потока. А QBuffer в свою очередь создаётся только на QByteArray.

Мои рассуждения:

Вариант раз:

Смотрим на интерфейс QIODevice и видим там непримечательную функцию ungetChar( char ), которая засунет символ обратно в поток. Идея такова: читаем байт, берём старшую половину, засовуем байт обратно. В следующий раз читаем байт, берём младшую половину и не засовуем обратно. Проблемы:
1. где хранить чётность нечётность уже прочитанных данных?
2. если поток небуферизированный, то ета функция может не работать.

Вариант два:

Наследуемся от QFile. Получаем IO Device для работы с 4-мя битами:

Код:
class My4BitDevice : public QFile
{
public:
  My4BitDevice() :
    odd( false )
  {
  }

  qint64 readData( char * data, qint64 maxSize )
  {
    int count = maxSize;
    while ( count )
    {
      if ( !odd )
      {
        int bytes = QFile::readData( &tmp, 1 );
        if ( bytes < 0 )
          return bytes;
        if ( bytes != 1 )
          return maxSize - count;
      }
      *data = !odd ? (tmp & 0x0f) : (tmp & 0xf0) >> 4;
      odd = !odd;
      data++;
      count--;
    }
    return maxSize - count;
  }

  bool odd;
  char tmp;
};


Ну чёта типа такого. Итак, теперь при считывании N байт мы на самом деле считаем N блоков по 4 бита. Результат будет такой: в каждом считанном байте младшая часть и будет наши 4 бита.
Пример использования:

Код:
  My4BitDevice dev( "myfile" ); // придумаете конструктор
  QByteArray bits = dev.read( 10 );


Выше мы считываем 10 блоков по 4 бита. Результат будет в младшей части каждого байта массива bits. Хотя я бы советовал юзать qint64 read( char * data, qint64 maxSize ), так можно получить еррор, если биты в файле кончились.

 :D


Название: Как можно читать данные из потока кусками по четыре бита ?
Отправлено: burunduk от Ноябрь 30, 2005, 10:29
Всё правильно понял.
Да, действительно это наверное лучше, чем я уже реализовал и давно забыл :-)