Autor Beitrag
AScomp
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 162


Delphi 5, Delphi 7, Delphi 2007, Delphi 2009, Delphi XE, Delphi 10 Seattle
BeitragVerfasst: Mo 22.06.15 00:00 
Hallo zusammen,

ich versuche verzweifelt, größere Dateien (200 MB und größer) von einem Windows-Rechner auf einen Mac zu kopieren, indem ich die WriteFile-Funktion verwende. Das Problem ist, dass z.B. beim WriteFile -1 zurückgegeben wird, nachdem einige Blöcke geschrieben wurden. RaiseLastOSError gibt 112 zurück, es ist aber ausreichend Speicherplatz vorhanden.

Wenn ich denselben Block mit WriteFile wieder und wieder versuche zu schreiben, klappt es nach einigen Versuchen (ca. 20-40).

Kopiere ich die Datei mit dem Windows Explorer (bzw. ShFileOperation), dann funktionert es. Ist in meinem Fall aber keine Alternative, ich möchte das mit WriteFile gelöst bekommen.

Das Problem lässt sich mit jedem beliebigen Mac reproduzieren. Einfach größere Dateien über's Netzwerk vom PC auf einen Mac per WriteFile kopieren - die Puffergröße scheint nicht relevant zu sein (in meinem Fall 64 KB).

Hat da jemand eine Idee? Mir ist völlig unklar, was da genau die Ursache sein soll.

Viele Grüße

Andy

Moderiert von user profile iconNarses: Beiträge zusammengefasst

Anbei mal eine Beispielfunktion, die ich zum Testen geschrieben habe:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
function GetFileSizeBytes(Filename: String): Int64;
var
   SRec: TSearchRec;
   Found: Integer;
begin
     try
        Found := FindFirst(Filename, faAnyFile, SRec);
        if Found = 0 then
           Result := SRec.Size
        else
           Result := -1;
     finally
        FindClose(SRec);
     end;
end;

function SynchronizeFile(Source, Destination: String): Boolean;
var
   NumRead, NumWritten: Integer;
   ReadFileHandle, WriteFileHandle: THandle;
   DestinationExists, Hashing: Boolean;
   Buffer: Array of char;
   FileLength: Int64;
begin
     result := false;
     SetLength(Buffer, (64 * 1024) - 1);

     ReadFileHandle := FileOpen(Source, fmOpenRead or fmShareDenyNone);
     if ReadFileHandle = INVALID_HANDLE_VALUE then
        exit;

     try
        FileLength := GetFileSizeBytes(Source);
        Application.ProcessMessages;
        if not DirectoryExists(ExtractFilePath(Destination)) then
           ForceDirectories(ExtractFilePath(Destination));

        WriteFileHandle := FileCreate(Destination);
        if WriteFileHandle = INVALID_HANDLE_VALUE then
           exit;

        with Form1.ProgressBar1 do begin
             Min := 0;
             Max := (FileLength div ((64 * 1024) - 1));
             Position := 0;
             repeat
                   NumRead := FileRead(ReadFileHandle, Buffer[0], (64 * 1024) - 1);
                   if NumRead > 0 then begin
                      NumWritten := FileWrite(WriteFileHandle, Buffer[0], NumRead);
                      if NumWritten <> NumRead then begin
                         ShowMessage('Failed');
                         exit;
                      end;
                   end;
                   Position := Position + 1;
                   Application.ProcessMessages;
             until (NumRead <= 0);
             if NumRead = -1 then begin
                ShowMessage('Failed');
                exit;
             end;

             result := true;
        end;
     finally
        FileClose(ReadFileHandle);
        FileClose(WriteFileHandle);
     end;
end;


Moderiert von user profile iconNarses: Beiträge zusammengefasst

Ich nochmal. ;-)

Damit es auf dem Mac auch funktioniert, muss ich die Datei mit FileCreate erstellen, schließen und mit FileOpen im Schreibmodus (fmOpenWrite) wieder öffnen. Oder eben direkt mit CreateFile im Schreibmodus erstellen/öffnen.