C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Чтение файла FileOpen'ном, в бинарном режыме
dayver2009
Отправлено: 11.01.2007, 01:55


Ученик-кочегар

Группа: Участник
Сообщений: 26



Здравствуйте ! Подскажыте как с помощью функций FileOpen,FileRead,FileClose прочитать в бинарном режыме файл "Key.dat" (его рамер 4 байта). Да еще так прочитать чтоб каждый бит файла записывался в соответствующую ячейку масива int К[32]
Grigoriy
Отправлено: 11.01.2007, 06:42


Мастер участка

Группа: Участник
Сообщений: 381



fn — это нуль-терминальная строка имени файла
m — это массив 32 элементов по 4 байта каждый
младший байт по младшему адресу в файле
биты идут начиная от младшего байта.
В случае успеха возвращает 0, в противном случае возвращает -1.
CODE

int ReadFile32bitToArrayBit(char* fn,int* m)
{
unsigned int t1,t2;
int return1;
void* fh;
if ((fh=CreateFile(fn,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0))!=(void*)-1)
{
asm
{
pushad;
mov return1,0;
lea ebx,t1;
lea edi,t2;
mov t1,0;
push 0;
push ebx;
push 4;
push edi;
push fh;
call ReadFile;
cmp dword ptr [ebx],4;
jnz @pp;
mov edi,m;
cld;
mov ecx,32;
xor eax,eax;
rep stosd;
mov edi,m;
mov edx,t2;
mov ecx,32;
@c1:
rcr edx,1;
rcl dword ptr [edi],1;
add edi,4;
loop @c1;
jmp @p2;
@pp:mov return1,-1;
@p2:
popad;
};
CloseHandle(fh);
}
else return -1;
return return1;
};
AVC
Отправлено: 11.01.2007, 09:40


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

как с помощью функций FileOpen,FileRead,FileClose прочитать в бинарном режыме файл "Key.dat" (его рамер 4 байта). Да еще так прочитать чтоб каждый бит файла записывался в соответствующую ячейку масива int К[32]

CODE

int fhandle = FileOpen(ExtractFilePath(Application->ExeName)+"key.dat", fmOpenRead);
if (fhandle == (-1))    throw Exception("Не могу открыть файл");
__int32 content = 0;
int cou = FileRead(fhandle, &content, sizeof(content));
FileClose(fhandle);
if (cou != sizeof(content))    throw Exception("Проблемы с размером файла данных");
int K[sizeof(content)*8];
for (int i(0); i < (sizeof(K)/sizeof(K[0])); i++)
   K[i] = (content >> i) & 0x01;
dayver2009
Отправлено: 11.01.2007, 17:57


Ученик-кочегар

Группа: Участник
Сообщений: 26



AVC

Не могу понять почему в масив int К[32] каждый байт записывается наоборот(например при бинарном чтении символа "F" ваш пример кода записывает такой байт — "01100010" , а должно записывать "01000110")

Я так полагаю нужно как то исправить вашу строчку
QUOTE
for (int i(0); i < (sizeof(K)/sizeof(K[0])); i++) K[i] = (content>> i) & 0x01;

Но как не знаю.

Grigoriy

Спасибо за предложеную альтернативу FileRead'у но так как я с API не знаком мне это не подошло.
Хотя ради интереса я решыл попробывать ваш код но у мня не получилось его вставить в программу.
Как я понимаю то что вы написали — функция(ее описание).А значит етот код нужно вставлять где то между строками
CODE
...
#pragma resource "*.dfm"
TForm1 *Form1;

и
CODE
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
...

а вот вызов функиции вставлять например сюда
CODE
void __fastcall TForm1::Button1Click(TObject *Sender)
{
...
}


????Я правильно мыслю???

Я попробывал так зделать , но выдало ошыбку в строке вызова функции которую я записал так
CODE
ReadFile32bitToArrayBit("Key1.dat",32);

Ошыбка такая -
[C++ Error] Unit1.cpp(187): E2034 Cannot convert 'int' to 'int *'
[C++ Error] Unit1.cpp(187): E2342 Type mismatch in parameter 'm' (wanted 'int *', got 'int')

Как нужно правильно записывать второй параметр?
AVC
Отправлено: 11.01.2007, 18:16


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

Не могу понять почему в масив int К[32] каждый байт записывается наоборот

Потому как "младший байт по младшему адресу в файле, биты идут начиная от младшего байта." (Grigoriy)

Если нужно от старшего бита к младшему то можно так
for (int i(0); i < (sizeof(K)/sizeof(K[0])); i++)
K[(sizeof(K)/sizeof(K[0]) — i — 1] = (content>> i) & 0x01;

А может вам надо группами (например по 8 или 4 бита)?
Определитесь с термином "соответствующяя ячейка масива" из вашего первого поста.
dayver2009
Отправлено: 11.01.2007, 19:13


Ученик-кочегар

Группа: Участник
Сообщений: 26



Извените не знал что считывать можно по разному.

Нужно считывать — младшый байт по старшему адресу в файле,биты идут от старшего к младшему — Кажется так.

Ну вобщем на примере ето выглядит так :
Если в файле так записано 4 символа — "FuLy"
То К(32) заполним так — "01000110 01110101 01001100 01111001"
(К0=0,К1=1,К2=0,К3=0,К4=0,К5=1,К6=1,К7=0,К8=0,К9=1,К10=1,К11=1,К12=0, ну и т.д.)
Поскольку F=01000110,u=01110101,L=01001100,y=01111001
Grigoriy
Отправлено: 11.01.2007, 23:26


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE

Я попробывал так зделать , но выдало ошыбку в строке вызова функции которую я записал...

Неправильно "ReadFile32bitToArrayBit("Key1.dat",32);"

Я объяснял в своем сообщении, что второй параметр должен быть указателем на массив из 32 чисел, но не значением 32,
с тем расчетом, что функция возвращает результат оповещающий об успехе или неудаче выполнения (так делают АПИ-функции), а подлежащая обработке информация задается указателями.

CODE

__int32 content = 0;
int K[sizeof(content)*8];
if (ReadFile32bitToArrayBit("Key1.dat",K)==-1)
throw Exception("Невозможно открыть файл или размер файла не соответствует требуемому");


Отредактировано Grigoriy — 11.01.2007, 23:31
AVC
Отправлено: 12.01.2007, 09:50


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE (dayver2009 @ 11.01.2007, 18:13)
Извените не знал что считывать можно по разному.

И считывать можно по разному, а уж заполнять массив (визуализировать?) можно таким количеством способов...
Оказывается вам надо так
CODE

int K[sizeof(content)*8];

for (int i(0), n(0); i < sizeof(content); i++)
   for (int j=0x80; j; j >>= 1)
       K[n++] = (content & (j << i*8))? 1 : 0;
Boyko
Отправлено: 12.01.2007, 15:49


Станционный диспетчер

Группа: Участник
Сообщений: 88



QUOTE (dayver2009 @ 11.01.2007, 16:57)


Я так полагаю нужно как то исправить вашу строчку
QUOTE
for (int i(0); i < (sizeof(K)/sizeof(K[0])); i++) K[i] = (content>> i) & 0x01;

Но как не знаю.


Можно вот так:
CODE
unsigned content, K[32];
for (int i(0); i < (sizeof(K)/sizeof(K[0])); i++) K[i] =( (content << i) & 0x80000000)>>31;

dayver2009
Отправлено: 12.01.2007, 22:58


Ученик-кочегар

Группа: Участник
Сообщений: 26



Спасибо ОГРОМНОЕ всем Вам.Теперь я разобрался полностью yahoo.gif yahoo.gif . Тем более предложено такое огромное количество вариантов реализации одной задачи.
dayver2009
Отправлено: 09.02.2007, 19:14


Ученик-кочегар

Группа: Участник
Сообщений: 26



Очень сильно извиняюсь за то что опять вас беспокою но у меня опять вопрос.

Потребовалось модифицыровать программу таким образом что бы она считывала весь файл(любого неограниченого размера). И делала ето шагами по n байт.(int=n может быть любым числом из такого ряда — 2,4,8,16,32,64,128,... и его значение я задам с помощью компонента ComboBox). На каждом шаге такая часть файла заносится в К[n*8] как вы помогли мне выяснить по методу — младшый байт по старшему адресу в файле,биты идут от старшего к младшему.

Хотел сам поправить, но не вышло потому как из-за типа __int32
немогу правильно задать sizeof(content) так что бы он был равен n.

Вот структурно к чему я пришел:
CODE

int n;//Число может быть одним из такой последовательности 2,4,8,16,32,64,128,...
int fhandle = FileOpen(ExtractFilePath(Application->ExeName)+"key.dat", fmOpenRead);
if (fhandle == (-1))    throw Exception("Не могу открыть файл");
__int32 content = 0; //Здесь нужно как то изменить что бы sizeof(content) был равен "n"
int K[sizeof(content)*8]; //Масив должен инцыализироватся нулями
int cou;
for(не знаю как прописать границы выполнения цыкла){//так что бы считывался весь файл с начала до конца шагами по н байт
cou = FileRead(fhandle, &content, n);
for (int i(0), n(0); i < sizeof(content); i++)
  for (int j=0x80; j; j >>= 1)
      K[n++] = (content & (j << i*8))? 1 : 0;
...//здесь я зделаю все нужные мне изменения К и запишу его в другой файл
}
FileClose(fhandle);
nawok78
Отправлено: 12.02.2007, 10:05


Станционный диспетчер

Группа: Участник
Сообщений: 115



абстакционируйся от файла....
считай его целиком в какой-то буфер (не забудь память выделить)
char *bufer;

разумеется тебе нехватит int K[32]; тоже юзай char *bits;
char — потому что места меньше занимает — а на 0/1 — байта хватит
даже прикольней — можешь туда не 0/1 загонять, а '0'/'1' — замечаешь разницу? в итге у тебя готовая к "печати" строка получается smile.gif
разве что в этом случае нужно выделить памяти на 1 байт больше для 0 — конца строки

а потом в цикле с шагом Step — мучай буфер

CODE

int N=ceil(FileLen/Step);
char *bits = calloc (N, sizeof(char));
// ceil — округление в большую сторону

for (int i=0; i<N; i++)
{
// это если 0/1
 bits[i]=ufer[i*Step]....
// или если как '0'/'1'
bits[i]='0'+fufer[i*Step]....
}


Отредактировано nawok78 — 12.02.2007, 10:08
dayver2009
Отправлено: 12.02.2007, 17:38


Ученик-кочегар

Группа: Участник
Сообщений: 26



Решил зделать иначе !

Обернул все ето в функцию :
CODE

bool myread(String inname,int n,int p,int k[4])
{unsigned int y;
int fhandle=FileOpen(inname.c_str(),fmOpenRead);FileSeek(fhandle,p,0);FileRead(fhandle,&y,n);FileClose(fhandle);
for(int i=0,l=0;i<n;i++)for(int j=0x80;j;j>>=1)k[l++]=(y&(j<<i*8))?1:0;
return true;
}


А уже ее пихаю в цыкл который еще не написал поскольку для его условия нужно узнать размер файла и здесь опять остановился .
Остановился поскольку файлы скармлываемые проге могут быть больше 2 гигов а вот это :

CODE

iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
iFileLength = FileSeek(iFileHandle,0,2);
FileClose(iFileHandle);

Возращает -1 в случае большых файлов

искал другую функцию для определения размера файла
нашел здесь cbuilder.ru.... такое: GetFileSize и FileSizeByName(Unit: IdGlobal) но как их юзать не пойму (уже смотрел и в хелпе и в поиске но так толком и не пойму как использовать и какие для них нужны инклуды).

Подскажыте плиз какую функцию мне для етого использовать(чтоб работало и на файлах больше 2 гигов).И примерчик такой функции.
bred
Отправлено: 13.02.2007, 10:23


Ученик-кочегар

Группа: Участник
Сообщений: 15



QUOTE (dayver2009 @ 12.02.2007, 17:38)
Подскажыте плиз какую функцию мне для етого использовать(чтоб работало и на файлах больше 2 гигов).И примерчик такой функции.

CODE
extern PACKAGE __int64 __fastcall FileSeek(int Handle, const __int64 Offset, int Origin);

почему бы ее не использовать?
и написать что-нить типа вот такого:
CODE
__int64 FileLen = FileSeek( iFile, (__int64)0,2);

Вернуться в Вопросы программирования в C++Builder