delphi - Delphi 7中处理海量文本文件数据的最佳解决方案

标签 delphi text-files delphi-7

我有这样的文本文件:

"01","AAA","AAAAA" 
"02","BBB","BBBBB","BBBBBBBB" 
"03","CCC" 
"04","DDD","DDDDD"

我想将此文本文件数据加载到 sybase 数据库中的临时表中。因此,我需要构建一个程序来逐行读取此文本文件,直到 eof。如果文本文件较小,则逐行读取的过程会很快。但如果文本文件太大(可能超过500M),逐行读取的过程就会太慢。我认为逐行读取的方法不适合巨大的文本文件。因此,需要找到其他解决方案将文本文件数据加载到数据库中,而不是逐行读取文本文件的方法。有什么建议吗? 示例代码:

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;

最佳答案

一些一般提示:

  • 确保您的 TempTable 在内存中,或使用快速数据库引擎 - 查看 SQlite3 或其他方式(例如嵌入式 FireBird、NexusDB 或 ElevateDB)作为可能的数据库替代方案;
  • 如果您不使用TTable,而是使用真正的数据库,请确保将插入嵌套在事务内;
  • 对于真正的数据库,请检查您是否无法使用ArrayDML功能,该功能可以更快地根据需要在远程数据库(例如Sybase)中插入大量数据 - such Array DML is handled for instance with FireDAC据我所知;
  • 已知 FieldByName('...') 方法非常慢:请改用本地 TField 变量;
  • 使用 TextFile 时,分配更大的临时缓冲区;
  • 如果您使用的是较新的 Unicode 版本的 Delphi (2009+),那么使用 TextFile 并不是最佳选择。

所以你的代码可能是:

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;

您可以使用嵌入式引擎实现非常高的速度,几乎没有大小限制,但您的存储。例如,参见how fast we can add content to a SQLite3 database in our ORM :数据库文件中每秒大约 130,000/150,000 行,包括所有 ORM 编码。我还发现 SQLite3 生成的数据库文件比替代方案小得多。如果您想快速检索任何字段,请不要忘记在数据库中定义INDEX,如果可能的话插入行数据之后(以获得更好的速度)。对于 SQLite3,已经有一个可用的 ID/RowID 整数主键,我想它映射您的第一个数据字段。此 ID/RowID 整数主键已由 SQLite3 建立索引。顺便说一句,我们的 ORM 现在支持 FireDAC / AnyDAC and its advanced Array DML feature .

关于delphi - Delphi 7中处理海量文本文件数据的最佳解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17712813/

相关文章:

c - 对文本文件中的整数进行计数和求和时遇到问题

c - 读取文本文件并在每次遇到等号时递增变量

c# - 读取大型文本文件(超过 400 万行)并在 .NET 中解析每一行

delphi - 指向(子)方法函数的指针?

delphi - 启动时系统托盘图标不出现

delphi - 在 DWScript 中设置入口点

delphi - Indy TIdFTP - EIdReplyRFCError - "Can' t 打开数据连接”

delphi - 修补公共(public)非虚拟方法

delphi - Delphi中的密码加密

delphi - 如何在一个区域中放置文本?