|
Вопрос # 908/ вопрос решён / |
|
Доброго времени суток, уважаемые эксперты!
подскажите пожалуйста как работать с любым видом файла по битно
 |
Вопрос задал: Stepani4 (статус: Посетитель)
Вопрос отправлен: 11 сентября 2007, 12:08
Состояние вопроса: решён, ответов: 2.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Stepani4!
Работать с файлом можно только байтами и крупнее. Побитно читать/писать нельзя!
Прийдётся прочитать нужный байт, модифицировать, а потом записать назад.
например так
fs:TFileStream;
b:byte;
begin
fs:=TFileStream.create("имяфайла",fmOpenRead)
fs.position:=100;//перешли к 100 байту.
fs.read(b,1);
модифицируем b
//Теперь запись
fs.position:=100;//перешли к 100 байту, так как при чтении указатель сдвинулся к 101:)
fs.write(b,1);
fs.free;//закрыли файл и удалили класс для работы с ним.
Если нужно изменять именно 100 бит, то можно рассчитать где он находиться и изменить его.
номер нужно байта - 100 mod 8. Номер бита - 100 div 8
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 11 сентября 2007, 12:21
Оценка за ответ: 5
|
Ответ #2. Отвечает эксперт: Feniks
Здравствуйте, Stepani4!
А также, можно еще использовать функции BlockRead, BlockWrite для работы с нетипизированными файлами, т.е. объявляется переменная "var F: File;". И лучше всего читать и писать по блокам, а не по одному байту. Для этого берете массив длинной например 2048 байт и читаете по 2048 байт. Выбирать длинну буфера (массива) надо исходя из того, с какими файлами Вы собираетесь работать, какие их размеры. Чем больше буфер, тем быстрей скорость читать/писать, но больше памяти жрет.
Так что, выбирайте сами.
А для работы с битами есть много функций (зарезервированных слов), например, xor, or, and, mod, div, shr, shl, not.
 |
Ответ отправил: Feniks (статус: Бакалавр)
Время отправки: 11 сентября 2007, 15:15
Оценка за ответ: 5
|
Мини-форум вопроса
Всего сообщений: 18; последнее сообщение — 18 сентября 2007, 22:52; участников в обсуждении: 3.
|
Stepani4 (статус: Посетитель), 11 сентября 2007, 12:33 [#1]:
а как изменить бит?
|
|
Вадим К (статус: Академик), 11 сентября 2007, 12:44 [#2]:
Вот общеизвестные алгоритмы.
выставить бит номер n в еденичку
b := b or (1 shl n);
выставить бит номер n в нолик
b := b and not(1 shl n);
Предупреждение: биты в байте считаются с нуля и справа на лево!
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Feniks (статус: Бакалавр), 11 сентября 2007, 15:45 [#3]:
В дагонку к моему ответу...
Забыл еще добавить функции Low и High.
|
|
Stepani4 (статус: Посетитель), 13 сентября 2007, 09:47 [#4]:
что делает low и High с массивами и строками типа String я знаю. а здесь что делает? плюс работал с функциями BlockRead, BlockWrite что-то у меня не получилось. где можно выложить исходник? дело в том что читается отлично, а записывае "коряво"
|
|
Feniks (статус: Бакалавр), 13 сентября 2007, 10:05 [#5]:
Вот еще несколько примерчиков по работе с файлами :
Копирование методом Pascal
Type
TCallBack=procedure (Position,Size:Longint); {Для индикации процесса копирования}
procedure FastFileCopy(Const InfileName, OutFileName: String; CallBack: TCallBack);
Const BufSize = 3*4*4096; { 48Kbytes дает прекрасный результат }
Type
PBuffer = ^TBuffer;
TBuffer = array [1..BufSize] of Byte;
var
Size : integer;
Buffer : PBuffer;
infile, outfile : File;
SizeDone,SizeFile: Longint;
begin
if (InFileName <> OutFileName) then
begin
buffer := Nil;
AssignFile(infile, InFileName);
System.Reset(infile, 1);
try
SizeFile := FileSize(infile);
AssignFile(outfile, OutFileName);
System.Rewrite(outfile, 1);
try
SizeDone := 0; New(Buffer);
repeat
BlockRead(infile, Buffer^, BufSize, Size);
Inc(SizeDone, Size);
CallBack(SizeDone, SizeFile);
BlockWrite(outfile,Buffer^, Size)
until Size < BufSize;
FileSetDate(TFileRec(outfile).Handle,
FileGetDate(TFileRec(infile).Handle));
finally
if Buffer <> Nil then Dispose(Buffer);
System.close(outfile)
end;
finally
System.close(infile);
end;
end else
Raise EInOutError.Create(\'File cannot be copied into itself\');
end;
Копирование методом потока
Procedure FileCopy(Const SourceFileName, TargetFileName: String);
Var
S,T : TFileStream;
Begin
S := TFileStream.Create(sourcefilename, fmOpenRead );
try
T := TFileStream.Create(targetfilename, fmOpenWrite or fmCreate);
try
T.CopyFrom(S, S.Size ) ;
FileSetDate(T.Handle, FileGetDate(S.Handle));
finally
T.Free;
end;
finally
S.Free;
end;
end;
Копирование методами Windows
uses ShellApi; // !!! важно
function WindowsCopyFile(FromFile, ToDir : string) : boolean;
var F : TShFileOpStruct;
begin
F.Wnd := 0; F.wFunc := FO_COPY;
FromFile:=FromFile+#0; F.pFrom:=pchar(FromFile);
ToDir:=ToDir+#0; F.pTo:=pchar(ToDir);
F.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
result:=ShFileOperation(F) = 0;
end;
// пример копирования
procedure TForm1.Button1Click(Sender: TObject);
begin
if not WindowsCopyFile(\'C:\UTIL\ARJ.EXE\', GetCurrentDir) then
ShowMessage(\'Copy Failed\');
end;
|
|
Feniks (статус: Бакалавр), 13 сентября 2007, 10:09 [#6]:
Как вычислить CRC (контрольную сумму) для файла?
function GetCheckSum(FileName: string): DWORD;
var
F: file of DWORD;
P: Pointer;
Fsize: DWORD;
Buffer: array [0..500] of DWORD;
begin
FileMode := 0;
AssignFile(F, FileName);
Reset(F);
Seek(F, FileSize(F) div 2);
Fsize := FileSize(F) - 1 - FilePos(F);
if Fsize > 500 then Fsize := 500;
BlockRead(F, Buffer, Fsize);
Close(F);
P := @Buffer;
asm
xor eax, eax
xor ecx, ecx
mov edi , p
@again:
add eax, [edi + 4*ecx]
inc ecx
cmp ecx, fsize
jl @again
mov @result, eax
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(GetCheckSum(\'c:\Autoexec.bat\')));
end;
|
|
Feniks (статус: Бакалавр), 13 сентября 2007, 10:22 [#7]:
Есть еще Lo и Hi. Из Хелпа...
LO:
Returns the low order Byte of argument X.
Unit
System
Category
miscellaneous routines
Delphi syntax:
function Lo(X): Byte;
Description
In Delphi code, Lo returns the low-order Byte of the argument X as an unsigned value. X is an expression of type Integer.
var B: Byte;
begin
B := Lo($1234); { $34 }
end;
HI:
Returns the high-order byte of X as an unsigned value.
Description
In Delphi code, use Hi to obtain the high-order byte of an expression of type Word or Integer.
Note: Hi treats Integer as a 16-bit value, even if it is 32-bit.
var B: Byte;
begin
B := Lo($1234); { $12 }
end;
|
|
Stepani4 (статус: Посетитель), 14 сентября 2007, 16:07 [#8]:
цитирую "И лучше всего читать и писать по блокам, а не по одному байту" почему мне нежны блоки по 64 бит следовательно по 8 байт. и функция Blockwrite() делает после записи перевод "каретки"
|
|
Вадим К (статус: Академик), 14 сентября 2007, 16:17 [#9]:
>>и функция Blockwrite() делает после записи перевод "каретки"
Да вроде никогда не делала
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Feniks (статус: Бакалавр), 17 сентября 2007, 10:39 [#10]:
Не делает она никакого перевода корретки. Перевод карретки - это байты CR LF и они применимы для текстовых файлов. Вот ReadLn и WriteLn как раз и делают перевод карретки.
|
|
Stepani4 (статус: Посетитель), 17 сентября 2007, 15:05 [#11]:
дело в том, что я в файл без расширения записывая 8 символов, потом считываю в переменную типа Byte. затем xor\'ом изменяю и опять записываю Blockwrite\'ом в файл без расширения открываю Far\'ом в формате HEX , а там вместо одной строки три
|
|
Вадим К (статус: Академик), 17 сентября 2007, 15:17 [#12]:
8 символов в переменную типа byte?
К тому же при записи с помощью BlockWrite нужно указывать размер записываемых данных, иначе могут быть проблемы.
Мой способ (предложенный в первом ответе) должен работать. Или вы эксперементируете с BlockWrite?
может приведёте код, а мы его поругаем?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Stepani4 (статус: Посетитель), 17 сентября 2007, 17:20 [#13]:
type
mas: array of byte;
var
massiv:mas;
|
|
Stepani4 (статус: Посетитель), 17 сентября 2007, 17:22 [#14]:
код завтра,
плюс я нашел одну ошбку
исправлю посмотрю что получается
|
|
Stepani4 (статус: Посетитель), 18 сентября 2007, 10:36 [#15]:
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
massiv=array of byte;
mass=array of char;
var
fe,fd:file;
mas:massiv;
j, i:integer;
c, b:Byte;
cim: mass;
begin
b:=32; i:=0;
AssignFile(fe,\'h:\f\');
AssignFile(fd,\'h:\d\');
reset(fe,1);
Rewrite(fd,8);
//SetLength(mas,1);
while (not eof(fe)) do
begin
BlockRead(fe,c,1);
inc(i);
SetLength(mas,i);
mas[i-1]:=c;
setlength(cim,length(mas));
Writeln(i);
if i=8 then
begin
setlength(cim,length(mas));
for j:=0 to 7 do
begin
mas[j]:=mas[j] xor b;
cim[j]:=chr(mas[j]);
end;
BlockWrite(fd,mas,8);
i:=0;
setlength(mas,0);
end;
end;
//
if (i<8) and eof(fe) then
begin
//Append(fd);
for i:=0 to high(mas) do
cim[i]:=chr(mas[i] xor b);
BlockWrite(fd,mas,length(mas));
end;
writeln(\'vse\');
readln;
CloseFile(fd);
CloseFile(fe);
{ TODO -oUser -cConsole Main : Insert code here }
end.
|
|
Вадим К (статус: Академик), 18 сентября 2007, 12:20 [#16]:
Если вы считаете, что строка
BlockWrite(fd,mas,8);
запишет содержимое файла, то спешу разочаровать. Нет. она не запишет. Она запишет адрес этого массива в памяти и ещё 4 байта мусора
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Feniks (статус: Бакалавр), 18 сентября 2007, 19:36 [#17]:
Не совсем понятен алгоритм. Можно изложит весь алгоритм ? Что вообще надо сделать ? Уж очень замудренный код получился.
|
|
Вадим К (статус: Академик), 18 сентября 2007, 22:52 [#18]:
Feniks
Алгоритм у него не мутный, просто он хочет это сделать через голову.
Галочка "подтверждения прочтения" - вселенское зло.
|
31 января 2011, 19:29: Статус вопроса изменён на решённый (изменил модератор Ерёмин А.А.): Автоматическая обработка (2 и более ответов с оценкой 5)
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|