2012-05-08 3 views
3

dans ce article delphi.net (prism) support async file io. Delphi (Native/VCL) a Async File IO Class aussi?E/S du fichier asynchrone dans Delphi

+0

Pour VC++ il y a ce qui pourrait être facilement porté à Delphes: http://www.codeproject.com/Articles/174595/A-Simple-Wrapper-pour-Asynchronous-File-IO-ReadFil - mais ma question est pourquoi s'embêter. L'API Win32 brute n'est pas si difficile à gérer que vous avez besoin d'un wrapper de classe. –

+0

pertinent/en relation: http://stackoverflow.com/questions/2953070/le-plus-delegant-way-to-encapsulate-winapi-callbacks-inside-a-class –

Répondre

2

Avez-vous vu ce code? C'est un bon début pour les E/S de fichiers anynchrones, mais personnellement j'écrirais un wrapper autour de la classe standard TStream pour maintenir la compatibilité avec VCL/RTL.

EDIT 2: Celui-ci a l'air bien aussi. http://www.torry.net/vcl/filedrv/other/dstreams.zip

Je signale ici juste au cas où il disparaît de Pastebin:

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

La fonction async io est cachée (remarquée) dans ce code – MajidTaheri

+0

Jetez donc un coup d'oeil au deuxième code. – Pateman

+0

dans l'article est basé sur les événements (fonction ReadDone) mais dstream n'est pas basé sur les événements, les paramètres de Read et ReadAsync sont identiques – MajidTaheri

3

La bibliothèque RTL/VCL ne comporte aucun élément qui offre des E/S asynchrones pour les fichiers. Incidemment, le support de Delphi Prism est basé sur le framework .net plutôt que sur le langage.

Vous pouvez soit coder directement par rapport à l'API Win32 (ce qui n'est pas très amusant), soit rechercher un wrapper Delphi pour cette API. De prime abord, je ne connais aucun wrapper Delphi d'E/S de fichiers asynchrones mais ils doivent exister.