2015-09-17 54 views
2

Delphi不會寫最後幾行。
一個過程爲每一行調用writeToText(a1, a2, ...)Delphi無法正確終止I/O進程

type 
    TQuerySQL = class 
    public 
     Constructor Create; 
     Destructor Destroy; override; 
     procedure writeToText(plate:String; positionNo:String; newOdometer:String; oldOdometer:String); 
    end; 

var 
    tconnect : TADOConnection; 
    tquery : TADOQuery; 
    F_Text: TextFile; 

implementation 

Constructor TQuerySQL.Create; 
begin 
    AssignFile(F_Text, 'results.txt'); 
    ReWrite(F_Text); 
    tquery := TADOQuery.Create(nil); 
    tconnect := TADOConnection.Create(nil); 
    tconnect.Close; 
    tconnect.ConnectionString := 'Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=SOFT20150911;'; 
    tconnect.ConnectOptions := coConnectUnspecified; 
    tconnect.LoginPrompt := False; 
    tconnect.Open; 
    ShowMessage('starting'); 
end; 

Destructor TQuerySQL.Destroy; 
begin 
    tquery.Close; 
    tquery.Free; 
    tconnect.Close; 
    tconnect.Free; 
    CloseFile(F_Text); 
    ShowMessage('finished in destructor'); 
    inherited Destroy; 
end; 

procedure TQuerySQL.writeToText(plate:String; positionNo:String; newOdometer:String; oldOdometer:String); 
begin 
    Write(F_Text, 'UPDATE POSITIONS SET'); 
    Write(F_Text, ' ODOMETER = '+oldOdometer); 
    Write(F_Text, ' WHERE'); 
    Write(F_Text, ' LABEL = '''+plate+''''); 
    Write(F_Text, ' AND POSITIONNO = '''+positionNo+''''); 
    Write(F_Text, ' AND ODOMETER = '+newOdometer+';'); 
    WriteLn(F_Text); 
end; 

樣本輸出:

UPDATE SET倉= ODOMETER WHERE 904068,1 LABEL = '34 XXX 11' 和POSITIONNO =「12110126'AND ODOMETER = 904092,2;

UPDATE POSITIONS SET ODOMETER = 904068,1 WHERE LABEL = '01 AL 101'AND POSITIONNO ='165556'AND ODOMETER = 904092,2;

SET ODOMETER UPDATE位置= 904148,7

+0

爲什麼不是你F_Text你TQuerySql類的字段:

procedure TQuerySQL.writeToTextClose; begin CloseFile(F_Text); tquery.Close; tconnect.Close; ShowMessage('write to text finished'); end; destructor TQuerySQL.Destroy; begin tquery.Free; tconnect.Free; inherited; end; 

任務可以這樣實現的呢?把它作爲一個獨立的全球變量似乎會引起意外誤用。此外,您在執行AssignFile時未指定路徑。順便說一句,你的標題應該是「我不能......」而不是「德爾福不能......」; =) – MartynA

+1

請提供一個[mcve] –

+0

我假設你看到消息「在析構函數中完成」屏幕? –

回答

1

嘗試關閉之前,刷新該文件的緩衝區:

Flush(F_Text); 
+0

你是否100%確定這是必要的。我不認爲這是事實,它看起來像一個猜測。 –

+0

沖洗沖洗Delphi的緩衝區,而不是操作系統的緩衝區,這可能是操作系統關閉應用程序的時間問題。這是一個猜測,這是唯一真正留給我們看的東西。 –

2

也許你的代碼的某些部分從TQuerySQL外訪問F_Text變量在CreateDestroy呼叫之間。

只要在設備的var部分聲明F_Text,如果您同時運行類TQuerySQL的多個實例,也會發生同樣的情況。

如果沒有理由爲什麼發生這種情況,你可以考慮讓它private

type 
    TQuerySQL = class 
    private 
     F_Text: TextFile; 
    public 
     Constructor Create; 
     Destructor Destroy; override; 
     procedure writeToText(plate:String; positionNo:String; newOdometer:String; oldOdometer:String); 
    end; 

這同樣適用於:

tconnect : TADOConnection; 
tquery : TADOQuery; 

爲了使舒爾這種情況不會發生的錯在同一單元中,您還可以考慮將strict關鍵字添加到該類的private部分。


除上述之外,通常不認爲執行除析構函數中釋放的對象以外的任務是一種好的做法。

我的建議是考慮使用額外的公共方法來執行關閉操作並讓析構函數完成其工作。

public 
    procedure writeToTextClose; 

。 。 。

var 
    qSql: TQuerySQL; 

. . . 

qSql := TQuerySQL.Create; 
try 

    try 
    //here multiple calls to writeToText take place 
    qSql.writeToText(a1, a2, ...); 

    finally 
    //ensure CloseFile(F_Text) at least 
    qSql.writeToTextClose; 
    end; 

finally 
    //ensure objects freeing 
    qSql.Free; 
end;