2012-05-08 1 views
3

in this article delphi.net (프리즘) 지원 비동기 파일 io. 델파이 (Native/VCL)도 Async File IO Class를 가지고 있습니까?델파이의 비동기 파일 I/O

+0

++ 쉽게 델파이에 이식 할 수있는이있다 : http://www.codeproject.com/Articles/174595/A-Simple-Wrapper-for-Asynchronous-File-IO-ReadFil -하지만 내 질문은 왜 귀찮은가. 원시 Win32 API는 클래스 래퍼가 필요하다는 점을 다루기가 어렵지 않습니다. –

+0

관련/관련 : http://stackoverflow.com/questions/2953070/the-most-elegant-way-to-encapsulate-winapi-callbacks-inside-a-class –

답변

2

이 코드를 보았습니까? http://pastebin.com/A2EERtyW

이것은 동기식 파일 입출력의 좋은 시작이지만 개인적으로 VCL/RTL과의 호환성을 유지하기 위해 표준 TStream 클래스 주위에 래퍼를 작성합니다.

편집 2 :이 역시 좋게 보입니다. http://www.torry.net/vcl/filedrv/other/dstreams.zip

난 그냥 경우 여기를 게시하고이 페이스트 빈에서 사라 : VC를 들어

unit xfile; 

{$I cubix.inc} 

interface 

uses 
    Windows, 
    Messages, 
    WinSock, 
    SysUtils, 
    Classes; 

const 
    MAX_BUFFER = 1024 * 32; 

type 
    TFileReadEvent = procedure(Sender: TObject; const Buffer; Count: Integer) of object; 

    TAsyncFile = class 
    private 
    FHandle: THandle; 
    FPosition: Cardinal; 
    FReadPending: Boolean; 
    FOverlapped: TOverlapped; 
    FBuffer: Pointer; 
    FBufferSize: Integer; 
    FOnRead: TFileReadEvent; 
    FEof: Boolean; 
    FSize: Integer; 
    function ProcessIo: Boolean; 
    procedure DoOnRead(Count: Integer); 
    function GetOpen: Boolean; 
    public 
    constructor Create(Filename: string; BufferSize: Integer = MAX_BUFFER); 
    destructor Destroy; override; 
    procedure BeginRead; 
    procedure Seek(Position: Integer); 
    procedure Close; 
    property OnRead: TFileReadEvent read FOnRead write FOnRead; 
    property Eof: Boolean read FEof; 
    property IsOpen: Boolean read GetOpen; 
    property Size: Integer read FSize; 
    end; 

function ProcessFiles: Boolean; 

implementation 

var 
    Files: TList; 

function ProcessFiles: Boolean; 
var 
    i: Integer; 
    AsyncFile: TAsyncFile; 
begin 
    Result := False; 
    for i := Files.Count - 1 downto 0 do 
    begin 
    AsyncFile := TAsyncFile(Files[i]); 
    Result := AsyncFile.ProcessIo or Result; 
    end; 
end; 

procedure Cleanup; 
var 
    i: Integer; 
    AsyncFile: TAsyncFile; 
begin 
    for i := Files.Count - 1 downto 0 do 
    begin 
    AsyncFile := TAsyncFile(Files[i]); 
    AsyncFile.Free; 
    end; 
    Files.Free; 
end; 

{ TAsyncFile } 

constructor TAsyncFile.Create(Filename: string; BufferSize: Integer); 
begin 
    Files.Add(Self); 
    FReadPending := False; 
    FBufferSize := BufferSize; 
    GetMem(FBuffer, FBufferSize); 
    FillMemory(@FOverlapped, SizeOf(FOverlapped), 0); 

    Cardinal(FHandle) := CreateFile(
        PChar(Filename),   // file to open 
        GENERIC_READ,   // open for reading 
        0,      // do not share 
        nil,      // default security 
        OPEN_EXISTING,   // open existing 
        FILE_ATTRIBUTE_NORMAL, //or // normal file 
        //FILE_FLAG_OVERLAPPED, // asynchronous I/O 
        0);      // no attr. template 

    FSize := FileSeek(FHandle, 0, soFromEnd); 
    FileSeek(FHandle, 0, soFromBeginning); 
    FPosition := 0; 
end; 

destructor TAsyncFile.Destroy; 
begin 
    Files.Remove(Self); 
    CloseHandle(FHandle); 
    FreeMem(FBuffer); 
    inherited; 
end; 

function TAsyncFile.ProcessIo: Boolean; 
var 
    ReadCount: Cardinal; 
begin 
    Result := False; Exit; 
    if not FReadPending then 
    begin 
    Exit; 
    end; 

    if GetOverlappedResult(FHandle, FOverlapped, ReadCount, False) then 
    begin 
    FReadPending := False; 
    DoOnRead(ReadCount); 
    end 
    else 
    begin 
    case GetLastError() of 
     ERROR_HANDLE_EOF: 
     begin 
     FReadPending := False; 
     FEof := True; 
     end; 
     ERROR_IO_PENDING: 
     begin 
     FReadPending := True; 
     end; 
     0: 
     begin 
     Result := True; 
     end; 
    end; 
    end; 
end; 

procedure TAsyncFile.BeginRead; 
var 
    ReadResult: Boolean; 
    ReadCount: Cardinal; 
begin 
    ReadCount := 0; 
    Seek(FPosition); 
    ReadResult := ReadFile(FHandle, FBuffer^, FBufferSize, ReadCount, nil);//@FOverlapped); 
    if ReadResult then 
    begin 
    FEof := False; 
    FReadPending := False; 
    FPosition := FPosition + ReadCount; 
    DoOnRead(ReadCount); 
    end 
    else 
    begin 
    case GetLastError() of 
     ERROR_HANDLE_EOF: 
     begin 
     FReadPending := False; 
     FEof := True; 
     end; 
     ERROR_IO_PENDING: 
     begin 
     FReadPending := True; 
     end; 
    end; 
    end; 
end; 

procedure TAsyncFile.DoOnRead(Count: Integer); 
begin 
    if Assigned(FOnRead) then 
    begin 
    FOnRead(Self, FBuffer^, Count); 
    end; 
end; 

function TAsyncFile.GetOpen: Boolean; 
begin 
    Result := Integer(FHandle) >= 0; 
end; 

procedure TAsyncFile.Close; 
begin 
    FileClose(FHandle); 
end; 

procedure TAsyncFile.Seek(Position: Integer); 
begin 
    FPosition := Position; 
    FileSeek(FHandle, Position, soFromBeginning); 
end; 

initialization 
    Files := Tlist.Create; 

finalization 
    Cleanup; 

end. 
+0

async io 기능이이 코드에 숨겨져 있습니다. – MajidTaheri

+0

그런 다음 두 번째 코드를 살펴보십시오. 위 기사의 – Pateman

+0

은 이벤트 기반 (ReadDone 함수)이지만 dstream은 이벤트 기반이 아니며 Read 및 ReadAsync의 매개 변수는 동일합니다. – MajidTaheri

3

비동기 I/O를 파일에 제공하는 RTL/VCL에는 기본 제공되는 것이 없습니다. 덧붙여 Delphi Prism의 지원은 언어 기반이 아니라 .net 프레임 워크에 달려 있습니다.

Win32 API에 대해 직접 코드를 작성하거나 (그다지 재미 있지는 않음) 해당 API에 대한 델파이 래퍼를 검색 할 수 있습니다. 내 머리 꼭대기에서 비동기 파일 I/O의 델파이 래퍼를 모르지만 반드시 존재해야합니다.