2012-05-30 117 views
2

我試圖測量FILE_FLAG_WRITE_THROUGHFILE_FLAG_NO_BUFFERING對文件中一系列寫入的影響,如another question中的請求。但是我發現我不能用FILE_FLAG_NO_BUFFERING組寫一個文件。爲什麼使用FILE_FLAG_NO_BUFFERING打開文件時寫入失敗?

當我使用它時,德爾福返回EWriteError與消息stream read error

使用的代碼如下:

procedure TForm1.btn1Click(Sender: TObject); 
var 
    fsFSArquivoAAC: TFileStream; 
    L, lastErr: Cardinal; 
    R: WideString; 
    hn: THandle; 
begin 
    hn := Windows.CreateFile(PChar('TesteAAC.AAC2'), 
       GENERIC_READ or GENERIC_WRITE, 
       FILE_SHARE_READ or FILE_SHARE_WRITE, nil, CREATE_ALWAYS, 
       FILE_ATTRIBUTE_NORMAL or FILE_FLAG_WRITE_THROUGH or FILE_FLAG_NO_BUFFERING, 0); 

    lastErr := GetLastError(); 

    if (lastErr <> ERROR_SUCCESS) then 
    begin 
    if (lastErr <> ERROR_ALREADY_EXISTS) then 
    begin 
     MessageDlg('Whoops, something went wrong with CreateFile!', 
        mtError, [mbOK], 0); 
    end 
    else 
    begin 
     SetLastError(ERROR_SUCCESS); 
    end; 

    end; 

    fsFSArquivoAAC := TFileStream.Create(hn); 

    try 
    R := 'BatatinhaquandoNasceEspalharamapelochao'; 

    // write WideString 
    L := Length(R); 
    fsFSArquivoAAC.WriteBuffer(L, SizeOf(integer)); 
    if L > 0 then 
     fsFSArquivoAAC.WriteBuffer(R[1], L * SizeOf(WideChar)); 
    finally 
    fsFSArquivoAAC.Free; 
    end; 

如果你對此有何評論FILE_FLAG_NO_BUFFERING代碼工作。爲什麼?

+1

請注意,您沒有正確處理錯誤。你只是創建一個異常對象,然後丟棄它。你打算使用'raise',但更好的是,使用'RaiseLastOSError'來代替。但是由於在調用'CreateFile'和檢查失敗的時間之間可能會調用大量的OS函數,因此最好將文件句柄存儲在單獨的變量中,立即檢查*,然後*將它傳遞給構造函數。並記住'try'''finally',這樣你就可以釋放流並在異常情況下關閉文件句柄(比如'EWriteError')。 –

+0

@RobKennedy感謝您的編輯。你是對的。該代碼根本沒有做異常處理。另外,我並不想將它複雜化,因爲簡單的代碼只是顯示錯誤。我希望現在好一點。還是想到了同樣的錯誤。 – EMBarbosa

回答

7

如果您使用FILE_FLAG_WRITE_THROUGHFILE_FLAG_NO_BUFFERING,則有various requirements用於在內存中對齊緩衝區,將寫入與磁盤扇區對齊,(我認爲)以多個扇區大小寫入。你似乎沒有在做這些事情。

+0

你可能是對的。也許我很困惑,錯誤是「流**讀**錯誤」。我試圖驗證。 – EMBarbosa

+0

[Old New Thing中的相關帖子](http://blogs.msdn.com/b/oldnewthing/archive/2010/04/14/9995509.aspx)顯示了相同的行爲但是不同的錯誤。 – EMBarbosa

相關問題