Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Побитное считывание файла.

10K
29 марта 2005 года
asdsee
9 / / 29.03.2005
Доброго всем времени суток.
Ребята, подскажите пожалуйста, в Билдере 6 С++
можно ли считывать файлы побайтно или побитно?
Например берем файл ххх.ххх и считывая побитно информацию из него побитно, присваиваем его значение массиву например.

Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)
301
29 марта 2005 года
lord Kelvin
897 / / 08.11.2004
Цитата:
Originally posted by asdsee
Доброго всем времени суток.
Ребята, подскажите пожалуйста, в Билдере 6 С++
можно ли считывать файлы побайтно или побитно?
Например берем файл ххх.ххх и считывая побитно информацию из него побитно, присваиваем его значение массиву например.

Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)


Можно считывать по байтам, а их представлять уже, как биты.

243
30 марта 2005 года
pacific_7
1.9K / / 06.09.2004
Цитата:
Originally posted by asdsee

Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)


Это вы зря конечно пытаетесь людей разжаловать - я тоже не профи. Книжки читать надо - вопрос элементарный в принципе.
По сути дела - осмелюсь дополнить ответ lord'a Kelvin'a: считав побайтно, загоняете каждый байт в объединение вида:

Код:
union s
{
    unsigned char byte;
    struct bits
    {
        unsigned int b0:1;
        unsigned int b1:1;
        unsigned int b2:1;
        unsigned int b3:1;
        unsigned int b4:1;
        unsigned int b5:1;
        unsigned int b6:1;
        unsigned int b7:1;
    }bits;
}my_union;

Теперь, что бы загнать байт в my_union делаем так:
my_union.byte=ch;//ваш байт
А что бы получить доступ к каждому биту, так:
my_union.bits.b0=0;//b0 - нужный бит
Примечание: в билдере тип unsigned int полей битового поля вызывает насколько я помню ошибку. Вместо него нужно поставить bool.
487
30 марта 2005 года
ddnh_bc
301 / / 16.09.2003
Цитата:
Originally posted by asdsee
Доброго всем времени суток.
Ребята, подскажите пожалуйста, в Билдере 6 С++
можно ли считывать файлы побайтно или побитно?
Например берем файл ххх.ххх и считывая побитно информацию из него побитно, присваиваем его значение массиву например.

Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)



Подобный вопрос уже обсуждался недавно.
Вот тебе пример того как это можно реализовать:

Код:
BYTE *sptr,*tptr;
TMemoryStream *src=new TMemoryStream();
TMemoryStream *target=new TMemoryStream();
// Загружаем исходный файл
src->LoadFromFile("sourcefile.bin");
// Выделяем память под битовый массив (размер фала * 8 )
target->SetSize(src->Size<<3);
sptr=(BYTE*)src->Memory();
tptr=(BYTE*)target->Memory();
// Переводим байтовый массив в битовое представление
for (int i=0;i<src->Size;i++)
{
   for (int j=0;j<8;j++)
   {
      *(tptr++)=*sptr&1;
      *sptr>>=1;
   }
   sptr++;
}
// Теперь в target лежит битовый образ
delete src;
delete target;
7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by pacific_7
Код:
union s
{
    unsigned char byte;
    struct bits
    {
        unsigned int b0:1;
        unsigned int b1:1;
        unsigned int b2:1;
        unsigned int b3:1;
        unsigned int b4:1;
        unsigned int b5:1;
        unsigned int b6:1;
        unsigned int b7:1;
    }bits;
}my_union;

Если использовать unsigned int, тогда за основу будет браться поле типа int. sizeof(my_union)==4. Скорей всего нужно использовать тип unsigned char.

310
30 марта 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by Mongoose
Если использовать unsigned int, тогда за основу будет браться поле типа int. sizeof(my_union)==4. Скорей всего нужно использовать тип unsigned char.


Не совсем так :) . Объявление битового поля в структуре как указание его длины в unsigned int - общепринятая со времён С практика. При этом реально будет задействовано столько байт, сколько нужно для вмещения всех полей. Например, в случае

Код:
union s
{
    unsigned char byte;
    struct bits
    {
        unsigned int b0:1;
        unsigned int b1:1;
        unsigned int b2:1;
        unsigned int b3:1;
        unsigned int b4:1;
        unsigned int b5:1;
        unsigned int b6:1;
        unsigned int b7:1;
        unsigned int other:28;

    }bits;
};

будет использовано 5 байт.
Что касается sizeof() и действительного размера переменной, то не нужно забывать, что у компилера есть опция - выравнивание данных (data alignment). Сделайте byte, это заставит компилер отказаться от выравнивания по границам слов и паковать поля структуры плотнее друг к другу.
Попробуйте менять в опциях проекта data alignment и всякий раз проверяйте размер исходной переменной my_union - вы увидете, что при выравнивании по границе слов размер будет 2 байта, при выравнивании по границам двойных слов - 4 байта, без выравнивания - ровно один байт.
Та же структура, но с добавленным мною полем bits.other, также будет менять свой размер при разных значениях data alignment.
7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by fellow
Не совсем так :) . Объявление битового поля в структуре как указание его длины в unsigned int - общепринятая со времён С практика. При этом реально будет задействовано столько байт, сколько нужно для вмещения всех полей.

Но выделено будет 4 байта даже для

 
Код:
struct t
{
  unsigned int k : 1;
}t;

Цитата:
Originally posted by fellow
Например, в случае
Код:
union s
{
    unsigned char byte;
    struct bits
    {
        unsigned int b0:1;
        unsigned int b1:1;
        unsigned int b2:1;
        unsigned int b3:1;
        unsigned int b4:1;
        unsigned int b5:1;
        unsigned int b6:1;
        unsigned int b7:1;
        unsigned int other:28;

    }bits;
}my_union;

будет использовано 5 байт.

sizeof(my_union)==8, даже при #pragma pack(1). структура bits занимает 8 байтов, так как за основу берется int. Но если определить

Код:
union s
{
    unsigned char byte;
    struct bits
    {
        unsigned char b0:1;
        unsigned char b1:1;
        unsigned char b2:1;
        unsigned char b3:1;
        unsigned char b4:1;
        unsigned char b5:1;
        unsigned char b6:1;
        unsigned char b7:1;
        unsigned char other1:8;
        unsigned char other2:8;
        unsigned char other3:8;
        unsigned char other4:4;
    }bits;
}my_union;
тогда sizeof(my_struct)==5.
310
30 марта 2005 года
fellow
853 / / 17.03.2003
Что-то ты не так делаешь :) . Объективные измерения, проведённые мной, твои слова не подтверждают.
Прочитай ещё раз про data alignment и поэкспериментируй. С #pragma pack(1) ты всё правильно сделал?
7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by fellow
Что-то ты не так делаешь :) . Объективные измерения, проведённые мной, твои слова не подтверждают.
Прочитай ещё раз про data alignment и поэкспериментируй. С #pragma pack(1) ты всё правильно сделал?

Я все это смотpел в VisualC. Но в Buildere так работает как ты говорил. И структура pacific_7, если установить #pragma pack(1) имеет длину 1, иначе 4. Мда. VisualC и Builder немношко отличаются друг от друга. :)

310
30 марта 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by Mongoose
Я все это смотpел в VisualC. Но в Buildere так работает как ты говорил. И структура pacific_7, если установить #pragma pack(1) имеет длину 1, иначе 4. Мда. VisualC и Builder немношко отличаются друг от друга. :)


"немножко" - звучит так умилительно :):):)

А что скажешь насчёт использования для компилера VC ключа /Zp ?
Кстати, в VC-шной справке битовые поля в структуре также показаны как unsigned (т.е. unsigned int)

7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by fellow
"немножко" - звучит так умилительно :):):)
А что скажешь насчёт использования для компилера VC ключа /Zp ?
Кстати, в VC-шной справке битовые поля в структуре также показаны как unsigned (т.е. unsigned int)

Если идет речь о том, что при /Zp1 описанная тобою структура будет иметь длину 5 байт, то это не так.

На счет справки. Если хорошо посмотреть приведенный в ней структуру, то становится ясно, что при использовании char, __int16, __int32 длина его будет одна и таже 4 байта. И если в справке unsigned int, то из этого следует, что стандарт C++ запрещает использование напр. unsigned char?

310
30 марта 2005 года
fellow
853 / / 17.03.2003
Цитата:
Originally posted by Mongoose
Если идет речь о том, что при /Zp1 описанная тобою структура будет иметь длину 5 байт, то это не так.


Ну, я так и предполагал, в общем... :)

Цитата:
Originally posted by Mongoose
... при использовании char, __int16, __int32 длина его будет одна и таже 4 байта


Да, потому что основу для битового поля составляет полноценный целочисленный тип, на широко распространённых современных писюках - 32 бита.

Цитата:
Originally posted by Mongoose
И если в справке unsigned int, то из этого следует, что стандарт C++ запрещает использование напр. unsigned char?


Отнюдь :) . Вообще, битовые поля в структурах - штука непереносимая, машинозависимая и, как показала практика, компилерозависимая. Билдер позволяет реально упаковать биты, а ВЦ не позволяет :)

7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by fellow

Да, потому что основу для битового поля составляет полноценный целочисленный тип, на широко распространённых современных писюках - 32 бита.

 
Код:
struct Date
{
    unsigned int nWeekDay  : 3;    // 0..7   (3 bits)
    unsigned int nMonthDay : 5;    // 0..31  (6 bits)
    unsigned int nMonth    : 6;    // 0..12  (5 bits)
    unsigned int nYear     : 8;    // 0..100 (8 bits)
};
Число битов та же. Но длина 3.
Цитата:
Билдер позволяет реально упаковать биты, а ВЦ не позволяет :)

Оба системы упаковывают ~одинаково. Разница только в том, что при #pragma pack(1) builder не обращает внимание на тип, взятый за основу. Спорный вопрос хорошо это или плохо.

10K
30 марта 2005 года
asdsee
9 / / 29.03.2005
В общем я сделал примерно так, ибо тип BYTE не хочет определяться у меня.

Код:
{
OpenDialog1->Execute();
 char *sptr,*tptr;
TMemoryStream *src=new TMemoryStream();
TMemoryStream *target=new TMemoryStream();

src->LoadFromFile(OpenDialog1->FileName);

//target->SetSize(src->Size<<3); если эту строчку раскоментировать, то вообще мильен ошибок начинает выводить %(

sptr=(char*)src->Memory();
tptr=(char*)target->Memory();

for (int i=0;i<src->Size;i++)
{
   for (int j=0;j<8;j++)
   {
      *(tptr++)=*sptr&1;
      *sptr>>=1;
   }
   sptr++;
}

delete src;

SaveDialog1->Execute();
target->SaveToFile(SaveDialog1->FileName);


но компилироваться это дело не хочет, говорит мол "Call of nofunction" и "'target' is assigned a value that is never used" че делать не знаю.
7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by asdsee
но компилироваться это дело не хочет, говорит мол "Call of nofunction" и "'target' is assigned a value that is never used" че делать не знаю.

Код:
if(OpenDialog1->Execute())
  {
    char *sptr,*tptr;
    TMemoryStream *src=new TMemoryStream();
    TMemoryStream *target=new TMemoryStream();

    src->LoadFromFile(OpenDialog1->FileName);

    target->SetSize(src->Size<<3);

    sptr=(char*)src->Memory;
    tptr=(char*)target->Memory;

    for (int i=0;i<src->Size;i++)
    {
       for (int j=0;j<8;j++)
       {
          *(tptr++)=*sptr&1;
// Вместо вернего кода лучше бы написать
//        *(tptr++)=(*sptr&1) + 48;
          *sptr>>=1;
       }
       sptr++;
    }

    delete src;

    if(SaveDialog1->Execute())
    {
      target->SaveToFile(SaveDialog1->FileName);
    }
    delete target;
  }
10K
30 марта 2005 года
asdsee
9 / / 29.03.2005
ух, спасибо, компилируется теперь на ура, правда как дело доходит то непосредственно момента открытия файла, вылетает ошибка и процесс останавливается насмерть.

Ведь, если я правильно понял, открыть так можно ЛЮБОЙ файл? мне например надо *.wav или *.mp3
7.2K
30 марта 2005 года
Mongoose
32 / / 23.09.2004
Цитата:
Originally posted by asdsee
ух, спасибо, компилируется теперь на ура, правда как дело доходит то непосредственно момента открытия файла, вылетает ошибка и процесс останавливается насмерть.Ведь, если я правильно понял, открыть так можно ЛЮБОЙ файл? мне например надо *.wav или *.mp3

Может не насмерть. Просто нет памяти и пишется на винт. Открой маленький .mp3. Проверил 5mb файл обрабатывает нормально. Поставь breakpoint на команду if(OpenDialog1->Execute())[F5], а потом в пошаговом режиме [F8]. Так можно определить где зависает, если зависает.

10K
30 марта 2005 года
asdsee
9 / / 29.03.2005
хм.. зависает на любых файлах, будь то даже текстовый файлик весом несколько килобайт...

В пошаговом режиме, выполнение программы останавливается на пункте...

 
Код:
*(tptr++)=*sptr&1;
243
31 марта 2005 года
pacific_7
1.9K / / 06.09.2004
Цитата:
Originally posted by asdsee
хм.. зависает на любых файлах, будь то даже текстовый файлик весом несколько килобайт...


Если дело стоит только в том, что бы просто вывести файл в массив, или на экран (для наглядности), то вот вариант решения, должно компилится в любом С-компилире без проблем (т.к. исползуются только стандартные функции):

Код:
int main(int argc, char *argv[])
{
  FILE *f;
  register int i,num;
  my_union.byte=0;
  f=fopen("filename","r");
  if(f==0)
  {
    cout<<"Error opening file\n";
    return 1;
  }
  num=fread(&my_union.byte,1,1,f);
  do
  {
    cout<<my_union.bits.b7;
    cout<<my_union.bits.b6;
    cout<<my_union.bits.b5;
    cout<<my_union.bits.b4;
    cout<<my_union.bits.b3;
    cout<<my_union.bits.b2;
    cout<<my_union.bits.b1;
    cout<<my_union.bits.b0<<" ";
  }
  while((num=fread(&my_union.byte,1,1,f))>0);
  fclose(f);
  return 0;
}

Используется указаннове выше объединение.
В массив загнать думаю труда не составит.
Выводит любые файлы - у меня сейчас до сих пор выводится файл подкачки винды :D (300 Mb для одного раздела) Считывать можно конечно и не по одному байтику - оптимизируйте и все будет работать на ура.
10K
31 марта 2005 года
asdsee
9 / / 29.03.2005
вообще то я закоментировал строчку


target->SetSize(src->Size<<3);

ибо если ее не коментируешь, то пишет ошибочку

[COLOR=red]'_fastcall TMemoryStream::SetSize(const __int64)' is not accessible
[/COLOR]

может поэтому у меня и не работает?

2pacific_7

хм.. ща попробую. мне не суть важно, мне лишь бы можно было загнать в массив побитно файл
487
31 марта 2005 года
ddnh_bc
301 / / 16.09.2003
Цитата:
Originally posted by asdsee
вообще то я закоментировал строчку


target->SetSize(src->Size<<3);

ибо если ее не коментируешь, то пишет ошибочку

[COLOR=red]'_fastcall TMemoryStream::SetSize(const __int64)' is not accessible
[/COLOR]

может поэтому у меня и не работает?

2pacific_7

хм.. ща попробую. мне не суть важно, мне лишь бы можно было загнать в массив побитно файл



Естественно из-за этого и не работает.

 
Код:
target->SetSize(src->Size<<3);


Это как раз выделение памяти для массива. Если ее не сделать - массив не инициализирован (tptr=NULL) поэтому и возникает ошибка.

[COLOR=red]'_fastcall TMemoryStream::SetSize(const __int64)' is not accessible
[/COLOR]

Напиши так:
 
Код:
target->SetSize((int)(src->Size<<3));


Да, забыл, можно еще так:
 
Код:
target->Size=(src->Size<<3);

10K
31 марта 2005 года
asdsee
9 / / 29.03.2005
спасибо.
Прога работает.
Осталось добиться, что бы открываешь wav файл и тут же его сохраняешь, и полсле этого он бы еще и проигрывался -)
и почему то открываешь, ну грубо говоря, файл весом 1 метр, сохраняешь его, получаешь файл весом в 5 метров ;)))
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог