Wednesday, June 30, 2004
Tuesday, June 29, 2004
Monday, June 28, 2004
Sunday, June 27, 2004
Friday, June 25, 2004
Thursday, June 24, 2004
Wednesday, June 23, 2004
Tuesday, June 22, 2004
Monday, June 21, 2004
Sunday, June 20, 2004
Friday, June 18, 2004
Thursday, June 17, 2004
Wednesday, June 16, 2004
I wrote a small copy file routine that support overlaped reading and writing, it suppose to has better performance.
procedure RSICopyFile(ASourceFileName, ADestFileName: string; ABuffSize: integer; AOverLaped: boolean);
const
MaxBufSize = 1024 * 1024 * 50; // 50mb
var
FReadhandle: THandle;
FWritehandle: THandle;
FBuffer: Pointer;
BufSize, FBytesInBuff, FFilePos, FBytesRead, FBytesWrite: Integer;
FFileSize: Integer;
FRead_os, FWrite_os: TOverlapped;
ErrorFlag: Dword;
begin
//open the source file
if not AOverLaped then
FReadhandle := CreateFile(PChar(ASourceFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0)
else
begin
FReadhandle := CreateFile(PChar(ASourceFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);
FillChar(FRead_os, SizeOf(FRead_os), 0);
FRead_os.hEvent := CreateEvent(nil, True, False, nil);
FRead_os.Offset := 0;
FRead_os.OffsetHigh := 0;
end;
if FReadhandle = 0 then
begin
raise exception.create('Cannot open the readding file');
end;
// get the size of source file
FFileSize := GetFileSize(FReadhandle, 0);
//open the dest file, create anew one if not exist
if not AOverLaped then
FWritehandle := CreateFile(PChar(ADestFileName), GENERIC_READ or GENERIC_WRITE,
0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
else
begin
FWritehandle := CreateFile(PChar(ADestFileName), GENERIC_READ or GENERIC_WRITE,
0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);
FillChar(FWrite_os, SizeOf(FWrite_os), 0);
FWrite_os.hEvent := CreateEvent(nil, True, False, nil);
FWrite_os.Offset := 0;
FWrite_os.OffsetHigh := 0;
end;
if FWritehandle = 0 then
begin
raise exception.create('Cannot open the writting file ');
end;
//Set the buffer size
if ABuffSize > MaxBufSize then
BufSize := MaxBufSize
else
BufSize := Integer(ABuffSize);
FBuffer := VirtualAlloc(0, BufSize, Mem_ReServe or Mem_Commit, PAGE_READWRITE);
try
if FFileSize > 0 then
begin
if FFileSize > MaxInt then
FFilePos := MaxInt
else
FFilePos := FFileSize;
while FFilePos > 0 do
begin
if FFilePos > BufSize then FBytesInBuff := BufSize else FBytesInBuff := FFilePos;
//clean up before read
FillChar(FRead_os, SizeOf(FRead_os), 0);
//Read file to buff
if not AOverLaped then
begin
if not ReadFile(FReadhandle, FBuffer^, FBytesInBuff, LongWord(FBytesRead), nil) then
begin
raise exception.create('file cannot be read');
end;
end
else
begin
if not ReadFile(FReadhandle, FBuffer^, FBytesInBuff, LongWord(FBytesRead), @FRead_os) then
begin
ErrorFlag := GetLastError;
if ErrorFlag <> 0 then
begin
if ErrorFlag = ERROR_IO_PENDING then
begin
if WaitForSingleObject(FRead_os.hEvent, INFINITE) = WAIT_OBJECT_0 then
if not GetOverlappedResult(FReadhandle, FRead_os,
LongWord(FBytesRead), False) then
begin
ErrorFlag := GetLastError;
if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end;
end;
end
else if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end
else
begin
raise exception.create('file cannot be read');
end;
end;
end;
inc(FRead_os.Offset, FBytesRead);
end;
//Write buff to file
if not AOverLaped then
begin
if FBytesRead = 0 then
begin
exit; // The end of the stream was hit.
end;
if not WriteFile(FWritehandle, FBuffer^, FBytesInBuff, LongWord(FBytesWrite), nil) then
begin
raise exception.create('file cannot be written');
end;
end
else
begin
if not WriteFile(FWritehandle, FBuffer^, FBytesInBuff, LongWord(FBytesWrite), @FWrite_os) then
begin
ErrorFlag := GetLastError;
if ErrorFlag <> 0 then
begin
if ErrorFlag = ERROR_IO_PENDING then
begin
if WaitForSingleObject(FWrite_os.hEvent, INFINITE) = WAIT_OBJECT_0 then
if not GetOverlappedResult(FWritehandle, FWrite_os,
LongWord(FBytesWrite), False) then
begin
ErrorFlag := GetLastError;
if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end;
end;
end
else if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end
else
begin
raise exception.create('file cannot be writeen');
end;
end;
end;
Inc(FWrite_os.Offset, FBytesWrite);
end;
//Change the position
Dec(FFilePos, FBytesRead);
end;
end;
finally
VirtualFree(FBuffer, BufSize, Mem_DeCommit or Mem_Release);
CloseHandle(FReadhandle);
CloseHandle(FWritehandle);
end;
end;
procedure RSICopyFile(ASourceFileName, ADestFileName: string; ABuffSize: integer; AOverLaped: boolean);
const
MaxBufSize = 1024 * 1024 * 50; // 50mb
var
FReadhandle: THandle;
FWritehandle: THandle;
FBuffer: Pointer;
BufSize, FBytesInBuff, FFilePos, FBytesRead, FBytesWrite: Integer;
FFileSize: Integer;
FRead_os, FWrite_os: TOverlapped;
ErrorFlag: Dword;
begin
//open the source file
if not AOverLaped then
FReadhandle := CreateFile(PChar(ASourceFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0)
else
begin
FReadhandle := CreateFile(PChar(ASourceFileName), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);
FillChar(FRead_os, SizeOf(FRead_os), 0);
FRead_os.hEvent := CreateEvent(nil, True, False, nil);
FRead_os.Offset := 0;
FRead_os.OffsetHigh := 0;
end;
if FReadhandle = 0 then
begin
raise exception.create('Cannot open the readding file');
end;
// get the size of source file
FFileSize := GetFileSize(FReadhandle, 0);
//open the dest file, create anew one if not exist
if not AOverLaped then
FWritehandle := CreateFile(PChar(ADestFileName), GENERIC_READ or GENERIC_WRITE,
0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
else
begin
FWritehandle := CreateFile(PChar(ADestFileName), GENERIC_READ or GENERIC_WRITE,
0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0);
FillChar(FWrite_os, SizeOf(FWrite_os), 0);
FWrite_os.hEvent := CreateEvent(nil, True, False, nil);
FWrite_os.Offset := 0;
FWrite_os.OffsetHigh := 0;
end;
if FWritehandle = 0 then
begin
raise exception.create('Cannot open the writting file ');
end;
//Set the buffer size
if ABuffSize > MaxBufSize then
BufSize := MaxBufSize
else
BufSize := Integer(ABuffSize);
FBuffer := VirtualAlloc(0, BufSize, Mem_ReServe or Mem_Commit, PAGE_READWRITE);
try
if FFileSize > 0 then
begin
if FFileSize > MaxInt then
FFilePos := MaxInt
else
FFilePos := FFileSize;
while FFilePos > 0 do
begin
if FFilePos > BufSize then FBytesInBuff := BufSize else FBytesInBuff := FFilePos;
//clean up before read
FillChar(FRead_os, SizeOf(FRead_os), 0);
//Read file to buff
if not AOverLaped then
begin
if not ReadFile(FReadhandle, FBuffer^, FBytesInBuff, LongWord(FBytesRead), nil) then
begin
raise exception.create('file cannot be read');
end;
end
else
begin
if not ReadFile(FReadhandle, FBuffer^, FBytesInBuff, LongWord(FBytesRead), @FRead_os) then
begin
ErrorFlag := GetLastError;
if ErrorFlag <> 0 then
begin
if ErrorFlag = ERROR_IO_PENDING then
begin
if WaitForSingleObject(FRead_os.hEvent, INFINITE) = WAIT_OBJECT_0 then
if not GetOverlappedResult(FReadhandle, FRead_os,
LongWord(FBytesRead), False) then
begin
ErrorFlag := GetLastError;
if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end;
end;
end
else if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end
else
begin
raise exception.create('file cannot be read');
end;
end;
end;
inc(FRead_os.Offset, FBytesRead);
end;
//Write buff to file
if not AOverLaped then
begin
if FBytesRead = 0 then
begin
exit; // The end of the stream was hit.
end;
if not WriteFile(FWritehandle, FBuffer^, FBytesInBuff, LongWord(FBytesWrite), nil) then
begin
raise exception.create('file cannot be written');
end;
end
else
begin
if not WriteFile(FWritehandle, FBuffer^, FBytesInBuff, LongWord(FBytesWrite), @FWrite_os) then
begin
ErrorFlag := GetLastError;
if ErrorFlag <> 0 then
begin
if ErrorFlag = ERROR_IO_PENDING then
begin
if WaitForSingleObject(FWrite_os.hEvent, INFINITE) = WAIT_OBJECT_0 then
if not GetOverlappedResult(FWritehandle, FWrite_os,
LongWord(FBytesWrite), False) then
begin
ErrorFlag := GetLastError;
if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end;
end;
end
else if ErrorFlag = ERROR_HANDLE_EOF then
begin
exit; // The end of the stream was hit.
end
else
begin
raise exception.create('file cannot be writeen');
end;
end;
end;
Inc(FWrite_os.Offset, FBytesWrite);
end;
//Change the position
Dec(FFilePos, FBytesRead);
end;
end;
finally
VirtualFree(FBuffer, BufSize, Mem_DeCommit or Mem_Release);
CloseHandle(FReadhandle);
CloseHandle(FWritehandle);
end;
end;
Tuesday, June 15, 2004
Monday, June 14, 2004
Sunday, June 13, 2004
Thursday, June 10, 2004
Tuesday, June 08, 2004
Tuesday, June 01, 2004
Subscribe to:
Posts (Atom)