Текущий архив: 2003.01.27;
Скачать: CL | DM;
Вниз
Скорость работы AssignFile(); Найти похожие ветки
← →
3223(jab) (2002-11-11 22:35) [0]Помогите разобраться с AssignFile();
Вопрос в скорости работы с диском, а именно мне нужно из одного файла переписать данный в другой. Для этого я работаю в цикле:
var
i:Integer;
buf:Byte;
f1,f2:File;
begin
AssignFile(f1,"c:\1.dat");AssignFile(f2,"c:\2.dat");
Reset(f1,1);ReWrite(f2,1); //создаю второй файл и открываю на
//запись
for i:=0 to 120 do begin
seek(f1,0+i);seek(f2,51+i);
BlockRead(f1,buf,1);BlockWrite(f2,buf,1);
//Не имеет значения адресация
end;
CloseFile(f1);CloseFile(f2);
end;
Проблема в том, что если у меня файл в 500Кб и выше у меня очень медленно это происходит. Я так понял он каждый раз обращается к файля, чтоб считать байт, потом переключается на другой файл и т.д. что очень тормозит! Как мне считать из файла кусок в 120(к примеру) килобайт, а потом его записать в другой файл???
← →
Snap (2002-11-11 22:38) [1]Тупой вопрос!
Делай больше буфер и пиши в blockread blockwrite последний параметр не 1 , а 120. Но тогда ещё нужна проверка на то что осталось ли нескопированное место. Но это уж сам сделай
← →
Dr_Mike (2002-11-11 22:51) [2]А в винде есть еще такие классные штучки, как отображение файлов и т.д. - открой хелп, и почитай, что расскажет по поводу "File mapping"...
← →
3223(jab) (2002-11-11 22:51) [3]Знаю что тупой вопрос, но реализовать не получается по непонятной причине...
Если можно примерчик!? Не могу понять как оно работает.
← →
Snap (2002-11-11 22:57) [4]var
i:Integer;
buf:array [0..101] of Byte;
f1,f2:File;
readed,all:longint;
begin
AssignFile(f1,"c:\1.dat");AssignFile(f2,"c:\2.dat");
Reset(f1,1);ReWrite(f2,1); //создаю второй файл и открываю на
//запись
all:=filesize(f1);
readed:=0;
repeat
if readed+102>all then
begin
BlockRead(f1,buf,all-readed);BlockWrite(f2,buf,all-readed);
readed:=all;
end else begin
BlockRead(f1,buf,102);BlockWrite(f2,buf,102);
inc(readed,102);
end;
until readed<>all;
//Не имеет значения адресация
CloseFile(f1);CloseFile(f2);
end;
← →
3223(jab) (2002-11-11 22:59) [5]Может кто знает ещё какой способ считать с 50 по n байты и записать их в другой файл, только с максимальным быстродействием.
Позарез нужно, а то пока обработаю файл в 106 Мб можно приготовить покушать и принять ванну.
← →
Dm9 (2002-11-11 23:58) [6]Сам ничего, кроме 1-го метода не использовал, так что разбирайся сам.
From FAQ:
Копирование файлов
Копирование методом TurboPascal
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;
Копирование методом LZExpand
uses LZExpand;
procedure CopyFile(FromFileName, ToFileName : string);
var
FromFile, ToFile: File;
begin
AssignFile(FromFile, FromFileName);
AssignFile(ToFile, ToFileName);
Reset(FromFile);
try
Rewrite(ToFile);
try
if LZCopy(TFileRec(FromFile).Handle, TFileRec(ToFile).Handle)<0 then
raise Exception.Create("Error using LZCopy")
finally
CloseFile(ToFile);
end;
finally
CloseFile(FromFile);
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;
← →
Dm9 (2002-11-11 23:59) [7]Надеюсь, поможет
← →
3223(jab) (2002-11-12 00:16) [8]тоже надеюсь
← →
3223(jab) (2002-11-12 00:18) [9]Dm9 Спасибо!
← →
3223(jab) (2002-11-12 00:22) [10]Dm9, просто мне важно было не только файл целиком копировать, но и копировать пол файла или вообще избирательно например с 0x0A по 0xFA1 потом ещё какой нибуть кусок(файл по кускам) С AssignFile(); понятно как, но медленно у меня получалось... Ладно испробую все выше перечисленные способы.
Спасибо всем!
← →
apay (2002-11-12 00:53) [11]2 Dm9
никак не пойму зачем нужно следующее:
FromFile:=FromFile+#0;
вроде бы не требо чтобы строка кончалась двойным нулем Ж)
← →
Dm9 (2002-11-12 02:34) [12]apay © (12.11.02 00:53)
Честно говоря, не знаю. Я пользовался только первым методом - как-то не было необходимости в быстром копировании больших файлов.
FromFile:=FromFile+#0; - действительно странно, так как PChar, по идее, добавляет ноль в конец. А не пробовал удалить строки с прибавлением нуля? У меня просто Delphi не работает, а переустанавливать сейчас не охота.
Кстати, никто не знает, что это такое: "Read error on "C:\Program Files\Borland\Delphi6\Lib\SysUtils.dcu""? Файл, существует. Поврежён, может? Или это глюк Delphi?
← →
3223(jab) (2002-11-14 10:48) [13]Самый путёвый способ(на мой взгляд) через массив!
var
buf:Array[0..2048] of Byte;
Но как можно по ходу программы изменя размерность массива т.е.
buf:Array[0..2048] of Byte; изменять [0..2048] этот кусок в нужных мне приделах, например мне нужно [0..5] или [0..10] или любой другой, а не из начала [0..100000] на все случаи жизни так сказать!
← →
Romeo (2002-11-15 11:33) [14]Что бы добиться максимальной скорости нужно использовать прямой асинхронный доступ к устройству.
Могу дать исходник на Visual C
Надо? пиши tiraspol_romeo@rambler.ru
← →
apay (2002-11-16 01:18) [15]если читать из файла данные подряд, т.е. не перемещать все время указатель ф-ей SetFilePointer (seek по-простому), то вроде достаточно при открытии файла ф-ей CreateFile поставить FILE_FLAG_SEQUENTIAL_SCAN и можно не делать большой буфер для чтения
← →
3223(jab) (2002-11-16 15:16) [16]В общем, то всё понятно стало.
При переписывании не возникает проблем! Всем спасибо.
Через буфер в 2048 байт работает очень быстро! Даже превзошло мои ожидания!
_______________________________
Страницы: 1 вся ветка
Текущий архив: 2003.01.27;
Скачать: CL | DM;
Память: 0.49 MB
Время: 0.011 c