[英]Is using TStringList to load huge text file the best way in Delphi?
[英]The best solution to process the huge text file data in Delphi 7
我有這樣的文本文件:
"01","AAA","AAAAA"
"02","BBB","BBBBB","BBBBBBBB"
"03","CCC"
"04","DDD","DDDDD"
我想將此文本文件數據加載到sybase db中的temp表中。 因此,我需要構建一個程序來逐行讀取該文本文件直到eof。 如果文本文件較小,則逐行讀取的過程會很快。 但是,如果文本文件太大(可能超過500M),則逐行讀取的過程太慢。 我認為逐行讀取方法不適合大型文本文件。 因此,需要找到其他解決方案以將文本文件數據加載到db中,而不是逐行讀取文本文件。 有什么建議嗎? 示例代碼:
var
myFile : TextFile;
text : string;
begin
// Try to open the Test.txt file for writing to
AssignFile(myFile, 'Test.txt');
// Display the file contents
while not Eof(myFile) do
begin
ReadLn(myFile, text);
TempTable.append;
TempTable.FieldByName('Field1').asstring=Copy(text,2,2);
TempTable.FieldByName('Field2').asstring=Copy(text,7,3);
TempTable.FieldByName('Field3').asstring=Copy(text,13,5);
TempTable.FieldByName('Field4').asstring=Copy(text,21,8);
TempTable.post;
end;
// Close the file for the last time
CloseFile(myFile);
end;
文本文件通常具有非常小的緩沖區。 考慮使用SetTextBuf函數來提高性能。
var
myFile : TextFile;
text : string;
myFileBuffer: Array[1..32768] of byte;
begin
// Try to open the Test.txt file for writing to
AssignFile(myFile, 'Test.txt');
SetTextBuf(MyFile, myFileBuffer);
Reset(MyFile);
// Display the file contents
while not Eof(myFile) do
begin
ReadLn(myFile, text);
end;
// Close the file for the last time
CloseFile(myFile);
end;
一些一般性提示:
TempTable
在內存中,或者使用快速的數據庫引擎-查看SQlite3或其他方式(例如FireBird嵌入式,NexusDB或ElevateDB)作為可能的數據庫替代方案; TTable
而是真正的數據庫,請確保將插入嵌套在Transaction中 ; FieldByName('...')
方法非常慢:使用locals TField
變量代替; 因此,您的代碼可能是:
var
myFile : TextFile;
myFileBuffer: array[word] of byte;
text : string;
Field1, Field2, Field3, Field4: TField;
begin
// Set Field* local variables for speed within the main loop
Field1 := TempTable.FieldByName('Field1');
Field2 := TempTable.FieldByName('Field2');
Field3 := TempTable.FieldByName('Field3');
Field4 := TempTable.FieldByName('Field4');
// Try to open the Test.txt file for writing to
AssignFile(myFile, 'Test.txt');
SetTextBuf(myFile, myFileBuffer); // use 64 KB read buffer
// Display the file contents
while not Eof(myFile) do
begin
ReadLn(myFile, text);
TempTable.append;
Field1.asInteger := StrToInt(Copy(text,2,2));
Field2.asString := Copy(text,7,3);
Field3.asString := Copy(text,13,5);
Field4.asString := Copy(text,21,8);
TempTable.post;
end;
// Close the file for the last time
CloseFile(myFile);
end;
使用嵌入式引擎可以實現非常高的速度,幾乎沒有大小限制,但是可以存儲。 例如,查看我們可以在ORM中向SQLite3數據庫添加內容的速度 :在數據庫文件中,包括所有ORM編組,每秒大約130,000 / 150,000行。 我還發現, SQLite3生成的數據庫文件比替代文件小得多。 如果要快速檢索任何字段,請不要忘了在數據庫中定義INDEX ,如果可能的話,在插入行數據之后(以提高速度)。 對於SQLite3 ,我想已經有一個ID/RowID
整數主鍵可用,它映射了您的第一個數據字段。 該ID/RowID
整數主鍵已被SQLite3索引。 順便說一下,我們的ORM現在支持FireDAC / AnyDAC及其高級Array DML功能 。
除了已經說過的內容,我還將避免使用任何TTable組件。 使用TQuery類型的組件會更好(取決於您使用的訪問層)。 像這樣的東西:
qryImport.SQL := 'Insert Into MyTable Values (:Field1, :Field2, :Field3, :Field4);';
Procedure ImportRecord(Const pField1, pField2, pField3, pField4 : String);
Begin
qryImport.Close;
qryImport.Params[0].AsString := pField1;
qryImport.Params[1].AsString := pField2;`
qryImport.Params[2].AsString := pField3;
qryImport.Params[3].AsString := pField4;
qryImport.ExecSQL;
End;
希望這可以幫助。
另一種方法是使用內存映射文件(您可以在google或torry.net上找到實現)。 對於> 1gb的文件,它不能很好地工作(在Win32中,在Win64中您幾乎可以映射任何文件)。 它將所有文件轉換成PAnsiChar
,您可以像掃描一個大緩沖區一樣進行掃描,搜索#10和#13(單獨或成對),從而手動分割字符串。
如果您使用(或不介意開始使用) JEDI Jvcl ,則它們具有TJvCSVDataSet
,使您可以像在Delphi中使用任何其他數據集一樣簡單地使用CSV文件,包括能夠定義持久字段和使用“標准” Delphi數據庫功能:
JvCSVDataSet1.FileName := 'MyFile.csv';
JvCSVDataSet1.Open;
while not JvCSVDataSet1.Eof do
begin
TempTable.Append; // Posts last appended row automatically;
// no need to call Post here.
// Assumes TempTable has same # of fields in the
// same order
for i := 0 to JvCSVDataSet1.FieldCount - 1 do
TempTable.Fields[i].AsString := JvCSVDataSet1.Fields[i].AsString;
JvCSVDataSet1.Next;
end;
// Post the last row appended when the loop above exited
if TempTable.State in dsEditModes then
TempTable.Post;
在Delphi 7中,您可以使用Turbo Power SysTools TStAnsiTextStream()以面向行的方式進行讀寫,但要使用線程安全的TStream實現而不是不安全的舊pascal文件接口。 在更高的Delphi版本中,您會在標准RTL中找到類似的東西(盡管它們在實現上有所不同),但是Delphi 7在文本文件操作方面沒有提供太多功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.