Побитное считывание файла.
Ребята, подскажите пожалуйста, в Билдере 6 С++
можно ли считывать файлы побайтно или побитно?
Например берем файл ххх.ххх и считывая побитно информацию из него побитно, присваиваем его значение массиву например.
Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)
Доброго всем времени суток.
Ребята, подскажите пожалуйста, в Билдере 6 С++
можно ли считывать файлы побайтно или побитно?
Например берем файл ххх.ххх и считывая побитно информацию из него побитно, присваиваем его значение массиву например.
Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)
Можно считывать по байтам, а их представлять уже, как биты.
Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)
Это вы зря конечно пытаетесь людей разжаловать - я тоже не профи. Книжки читать надо - вопрос элементарный в принципе.
По сути дела - осмелюсь дополнить ответ lord'a Kelvin'a: считав побайтно, загоняете каждый байт в объединение вида:
{
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.
Доброго всем времени суток.
Ребята, подскажите пожалуйста, в Билдере 6 С++
можно ли считывать файлы побайтно или побитно?
Например берем файл ххх.ххх и считывая побитно информацию из него побитно, присваиваем его значение массиву например.
Я новичек в програмировании, так что если вопрос глупый, не сердитесь пожалуйста, помогите, мне это для курсовой работы надо -)
Подобный вопрос уже обсуждался недавно.
Вот тебе пример того как это можно реализовать:
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;
{
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.
Если использовать unsigned int, тогда за основу будет браться поле типа int. sizeof(my_union)==4. Скорей всего нужно использовать тип unsigned char.
Не совсем так :) . Объявление битового поля в структуре как указание его длины в unsigned int - общепринятая со времён С практика. При этом реально будет задействовано столько байт, сколько нужно для вмещения всех полей. Например, в случае
{
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.
Не совсем так :) . Объявление битового поля в структуре как указание его длины в unsigned int - общепринятая со времён С практика. При этом реально будет задействовано столько байт, сколько нужно для вмещения всех полей.
Но выделено будет 4 байта даже для
{
unsigned int k : 1;
}t;
Например, в случае
{
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. Но если определить
{
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;
Прочитай ещё раз про data alignment и поэкспериментируй. С #pragma pack(1) ты всё правильно сделал?
Что-то ты не так делаешь :) . Объективные измерения, проведённые мной, твои слова не подтверждают.
Прочитай ещё раз про data alignment и поэкспериментируй. С #pragma pack(1) ты всё правильно сделал?
Я все это смотpел в VisualC. Но в Buildere так работает как ты говорил. И структура pacific_7, если установить #pragma pack(1) имеет длину 1, иначе 4. Мда. VisualC и Builder немношко отличаются друг от друга. :)
Я все это смотpел в VisualC. Но в Buildere так работает как ты говорил. И структура pacific_7, если установить #pragma pack(1) имеет длину 1, иначе 4. Мда. VisualC и Builder немношко отличаются друг от друга. :)
"немножко" - звучит так умилительно :):):)
А что скажешь насчёт использования для компилера VC ключа /Zp ?
Кстати, в VC-шной справке битовые поля в структуре также показаны как unsigned (т.е. unsigned int)
"немножко" - звучит так умилительно :):):)
А что скажешь насчёт использования для компилера VC ключа /Zp ?
Кстати, в VC-шной справке битовые поля в структуре также показаны как unsigned (т.е. unsigned int)
Если идет речь о том, что при /Zp1 описанная тобою структура будет иметь длину 5 байт, то это не так.
На счет справки. Если хорошо посмотреть приведенный в ней структуру, то становится ясно, что при использовании char, __int16, __int32 длина его будет одна и таже 4 байта. И если в справке unsigned int, то из этого следует, что стандарт C++ запрещает использование напр. unsigned char?
Если идет речь о том, что при /Zp1 описанная тобою структура будет иметь длину 5 байт, то это не так.
Ну, я так и предполагал, в общем... :)
... при использовании char, __int16, __int32 длина его будет одна и таже 4 байта
Да, потому что основу для битового поля составляет полноценный целочисленный тип, на широко распространённых современных писюках - 32 бита.
И если в справке unsigned int, то из этого следует, что стандарт C++ запрещает использование напр. unsigned char?
Отнюдь :) . Вообще, битовые поля в структурах - штука непереносимая, машинозависимая и, как показала практика, компилерозависимая. Билдер позволяет реально упаковать биты, а ВЦ не позволяет :)
Да, потому что основу для битового поля составляет полноценный целочисленный тип, на широко распространённых современных писюках - 32 бита.
{
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)
};
Оба системы упаковывают ~одинаково. Разница только в том, что при #pragma pack(1) builder не обращает внимание на тип, взятый за основу. Спорный вопрос хорошо это или плохо.
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" че делать не знаю.
но компилироваться это дело не хочет, говорит мол "Call of nofunction" и "'target' is assigned a value that is never used" че делать не знаю.
{
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;
}
Ведь, если я правильно понял, открыть так можно ЛЮБОЙ файл? мне например надо *.wav или *.mp3
ух, спасибо, компилируется теперь на ура, правда как дело доходит то непосредственно момента открытия файла, вылетает ошибка и процесс останавливается насмерть.Ведь, если я правильно понял, открыть так можно ЛЮБОЙ файл? мне например надо *.wav или *.mp3
Может не насмерть. Просто нет памяти и пишется на винт. Открой маленький .mp3. Проверил 5mb файл обрабатывает нормально. Поставь breakpoint на команду if(OpenDialog1->Execute())[F5], а потом в пошаговом режиме [F8]. Так можно определить где зависает, если зависает.
В пошаговом режиме, выполнение программы останавливается на пункте...
хм.. зависает на любых файлах, будь то даже текстовый файлик весом несколько килобайт...
Если дело стоит только в том, что бы просто вывести файл в массив, или на экран (для наглядности), то вот вариант решения, должно компилится в любом С-компилире без проблем (т.к. исползуются только стандартные функции):
{
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 для одного раздела) Считывать можно конечно и не по одному байтику - оптимизируйте и все будет работать на ура.
target->SetSize(src->Size<<3);
ибо если ее не коментируешь, то пишет ошибочку
[COLOR=red]'_fastcall TMemoryStream::SetSize(const __int64)' is not accessible
[/COLOR]
может поэтому у меня и не работает?
2pacific_7
хм.. ща попробую. мне не суть важно, мне лишь бы можно было загнать в массив побитно файл
вообще то я закоментировал строчку
target->SetSize(src->Size<<3);
ибо если ее не коментируешь, то пишет ошибочку
[COLOR=red]'_fastcall TMemoryStream::SetSize(const __int64)' is not accessible
[/COLOR]
может поэтому у меня и не работает?
2pacific_7
хм.. ща попробую. мне не суть важно, мне лишь бы можно было загнать в массив побитно файл
Естественно из-за этого и не работает.
Это как раз выделение памяти для массива. Если ее не сделать - массив не инициализирован (tptr=NULL) поэтому и возникает ошибка.
[COLOR=red]'_fastcall TMemoryStream::SetSize(const __int64)' is not accessible
[/COLOR]
Напиши так:
Да, забыл, можно еще так:
Прога работает.
Осталось добиться, что бы открываешь wav файл и тут же его сохраняешь, и полсле этого он бы еще и проигрывался -)
и почему то открываешь, ну грубо говоря, файл весом 1 метр, сохраняешь его, получаешь файл весом в 5 метров ;)))