連続で質問しまして、すみません。
もうひとつ、質問させてください。
現在、テキストファイルを読み込み、そのファイルの一部をTMemoで表示させています。
(一部とは、先頭から○○行とかの指定した行数です)
方法は、指定行数分をループでReadlnしながらTStringListに設定します。
そして終えたらTStringListをTMemo.Lines.AddStringsで設定しています。
この方法ですと簡単にできましたが、読み込み速度が遅いようです。
(TMemo.Lines.LoadFromFileで全て読み込んだ時と比べています)
テキストファイルの先頭から一部をもっと速く取得する方法はあるのでしょうか?
よろしくお願いします。
環境:
WindowsXP HOME SP2
Delphi6 Personal
指定行数ではなく、指定文字数を読み込むのなら速くできるけど。
指定文字数でもいいです。
それはどうすればいいんですか?
誤解だったら申し訳ないですが、質問が分かりづらいです。
今
AStrings : TStringList; //全テキストデータ
Memo1: TMemo; //一部を表示するTMemo
for i:=0 to 10 do
Memo1.LInes.AddStrings(AStrings.strings[i]);
みたく、AStringsの内容をMemo1に書き込む速度が気になるのであれば
もうひとつTStringListもしくはstringバッファーを用意して
BStrings:TStringList
BStrings.clear
for i:=0 to 10 do
BStrings.AddStrings(AStrings.strings[i]);
最後に一気にTMemoに出力すると早くなります。
Memo1.text:=BStrings.Text;
'_Test.txt'ファイルの先頭から300文字をMemoに表示。
procedure TForm1.Button1Click(Sender: TObject);
const
READ_SIZE = 300;
var
Buf: PChar;
begin
with TFileStream.Create('_Test.txt', fmOpenRead) do begin
Buf := nil;
try
GetMem(Buf, READ_SIZE+1);
Read(Buf^, READ_SIZE);
Buf[READ_SIZE] := #0;
Memo1.SetTextBuf(Buf);
finally
if Assigned(Buf) then FreeMem(Buf);
Free;
end;
end;
end;
> Read(Buf^, READ_SIZE);
> Buf[READ_SIZE] := #0;
ここは、下のようにするべきだね。
Buf[Read(Buf^, READ_SIZE)] := #0;
300バイトと300文字じゃ全然違うな
質問者は、「ファイル先頭の一部分を読み込みたい」だけなのだから、
300バイト≠300文字であっても問題無し。
みなさん、ありがとうございました。
テストソースをあげておけば良かったですね。
すみませんでした。
大安さん、ダイアンさんの助言を参考に、指定バイト数読みの方法を
作成中のプログラムに取り込んでみたところ、修正前よりかなり速いです。
指定バイト数 = (指定行数 * 80) + (指定行数 * 2) で行っていますので、
※(指定行数 * 80)…1行を80バイトしての指定行数分のバイト
※(指定行数 * 2))…改行コード?とかの指定行数分のバイト
単純に指定行数による1行読み込みよりは確実に速いはずです。
(結果、今の方が読み込む行数が多いだろうから)
大変助かりました。
ありがとうございました。
いまさらですが、テストしてみたソース(一気読み、指定行数読み、指定バイト数読み)を
あげておきます。
ソース:
unit Unit1;
interface
uses
DateUtils,
Unit_LogManager,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
Button2: TButton;
Memo3: TMemo;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
FilePath: String;
procedure TForm1.Button1Click(Sender: TObject);
var
StartDateTime: TDateTime;
EndDateTime: TDateTime;
StartString: String;
EndString: String;
begin
//TMemoで一気に全てテキストファイルを読み込む
StartDateTime := Now;
StartString := FormatDateTime('yyyy/mm/dd hh:mm:ss.zzz', StartDateTime);
Memo1.Lines.LoadFromFile(FilePath);
EndDateTime := Now;
EndString := FormatDateTime('yyyy/mm/dd hh:mm:ss.zzz', EndDateTime);
ShowMessage(StartString + #13 +
EndString + #13 +
'差:' + IntToStr(MilliSecondsBetween(EndDateTime, StartDateTime)));
end;
procedure TForm1.Button2Click(Sender: TObject);
const
READ_SIZE = 300; //指定行数:300行
var
ReadTextFile: TextFile;
LineString: String;
LineCount: Integer;
MemoStringList: TStringList;
StartDateTime: TDateTime;
EndDateTime: TDateTime;
StartString: String;
EndString: String;
begin
//指定行数を1行ずつテキストファイルから読み込む
StartDateTime := Now;
StartString := FormatDateTime('yyyy/mm/dd hh:mm:ss.zzz', StartDateTime);
//初期処理
LineCount := 0;
MemoStringList := TStringList.Create;
AssignFile(ReadTextFile, FilePath);
Reset(ReadTextFile);
if not Eof(ReadTextFile) then
LineCount := LineCount + 1;
while (not Eof(ReadTextFile)) and (LineCount <= READ_SIZE) do
begin
Readln(ReadTextFile, LineString);
MemoStringList.Add(LineString);
LineCount := LineCount + 1;
end;
Memo2.Lines.AddStrings(MemoStringList);
//後処理
CloseFile(ReadTextFile);
MemoStringList.Free;
EndDateTime := Now;
EndString := FormatDateTime('yyyy/mm/dd hh:mm:ss.zzz', EndDateTime);
ShowMessage(StartString + #13 +
EndString + #13 +
'差:' + IntToStr(MilliSecondsBetween(EndDateTime, StartDateTime)));
end;
procedure TForm1.Button3Click(Sender: TObject);
const
READ_SIZE = 300 * 80 + 600; //指定バイト数:300行 * 80 + 600
// (1行を80バイトとしての300行分のバイト数 +
// 300行分の改行文字のバイト数)
var
Buf: PChar;
StartDateTime: TDateTime;
EndDateTime: TDateTime;
StartString: String;
EndString: String;
begin
//指定バイト数をテキストファイルから読み込む
StartDateTime := Now;
StartString := FormatDateTime('yyyy/mm/dd hh:mm:ss.zzz', StartDateTime);
with TFileStream.Create(FilePath, fmOpenRead) do begin
Buf := nil;
try
GetMem(Buf, READ_SIZE + 1);
Buf[Read(Buf^, READ_SIZE)] := #0;
Memo3.SetTextBuf(Buf);
finally
if Assigned(Buf) then FreeMem(Buf);
Free;
end;
end;
EndDateTime := Now;
EndString := FormatDateTime('yyyy/mm/dd hh:mm:ss.zzz', EndDateTime);
ShowMessage(StartString + #13 +
EndString + #13 +
'差:' + IntToStr(MilliSecondsBetween(EndDateTime, StartDateTime)));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
Memo2.Clear;
Memo3.Clear;
FilePath := 'C:\TEST\ファイルサンプル.txt';
end;
end.
1行ずつ追加する場合は、追加し始める前に
Memo1.Lines.BeginUpdate;
全て追加し終えた後に、
Memo1.Lines.EndUpdate;
をすると、少し早くなると思います。
> 300バイト≠300文字であっても問題無し。
そうかもしれないが、300文字とかいってるから期待してたのに期待はずれ
>>にしの さん
ありがとうございます。参考になります。
ツイート | ![]() |