各行の最初の一文字目に、識別用のフラグ文字が入ったテキストファイルを
読み込み、処理を行おうと思っています。
最終的な目標は、行頭のフラグを判別し、
フラグに合致した構造体に名前・項目1〜nを格納したいと考えています。
テキストファイルを読み込み、行頭のフラグを取り出すところで
つまずいてしまったので書き込みさせていただきました。
どなたか、アドバイス・関連リンク等の情報をお持ちでしたら、
教えて頂けないでしょうか?
宜しくお願い致します。
-------- テキストファイル例 --------
フラグ 名前 項目1 … 項目n
フラグ 名前 項目2 … 項目n
フラグ 名前 項目3 … 項目n
: : : … :
(フラグ …「a」「z」などの文字)
読み込みで詰まったのか、フラグの取り出しで詰まったのか解りませんが、とりあえず、「フラグの取り出し」ということで。
例えば、strという文字列型変数に1行が入っているとすれば、
case str[1] of
'a': // フラグがaのとき
;
'b': // フラグがbのとき
;
end;
とかけます。
以下のコードでテキストファイルから各行の各項目のデータを文字列として取り出せます。ShowMessageの行を書き換えて構造体にデータをセットしてください。
var
items, lines: TStrings;
i, j: Integer;
begin
lines := TStringList.Create;
items := TStringList.Create;
try
lines.LoadFromFile('data.txt');
for i := 0 to lines.Count-1 do
begin
items.CommaText := lines[i];
for j := 0 to items.Count-1 do
begin
ShowMessage(Format('%d,%d=%s', [i, j, items[j]]));
end;
end;
finally
lines.Free;
items.Free;
end;
end;
にしのさん、tomoさんありがとうございます。
私が詰まったのは、
「読み込んだデータからどうやって欲しいデータを取り出すか」です。
説明が不十分でごめんなさい。
外部ファイルからデータを読み込む際に、TMemoryStreamを使うとよいといった返信を良く見かけたのですが、
今回頂いたご回答では、TStringListで読み出しています。
こういった、読み込んだデータからほしいデータを抜き出す場合は、
TStringListの方が処理しやすいのでしょうか?
しめされたデータはテキストファイルでデータは1行ごとであり、空白区切り
であるように見えます。でしたら、TStringList で読みこみ、かく行のデータの
内容は tomo さんの示されたように、もう一つ TStringList をつかってその
CommaText で分離して処理します。これがもっとも普通のやり方だと思います。
カンマ区切りでないなら、DelimitedTextのほうが適切かと。
空白をdelimiterに指定すれば出来そうです。
ただ、固定長の場合、recordを定義して、TMemoryStreamでreadしたほうが便利です。
jokさんありがとうございます。
今回の質問のような場合は、TStringListを使うのが一般的がよいということですね。
にしのさん、tomoさんのサンプルプログラムで先程動作を確認いたしました。
私がやりたかった処理が出来そうです。ありがとうございました。
このたびは皆さん、ありがとうございました。助かりました。
jokさんありがとうございます。
今回の質問のような場合は、TStringListを使うのが一般的がよいということですね。
にしのさん、tomoさんのサンプルプログラムで先程動作を確認いたしました。
私がやりたかった処理が出来そうです。ありがとうございました。
このたびは皆さん、ありがとうございました。助かりました。
にしのさん ありがとうございます。
>固定長の場合、recordを定義して、TMemoryStreamでreadしたほうが便利です。
テキストファイルは以下のように固定長になっています。(多少フラグで異なりますが…)
そういった場合は、TMemoryStreamでどのように読み込めばよいでしょうか?
もしよろしければ、教えて頂けないでしょうか?
-------------- テキストファイル例 --------------
フラグ(1) 名前(8) 項目1(8) … 項目n(8)
:
(補足)
・区切りは「半角スペース」
・括弧は最大バイト数、満たない場合は半角スペースを入れる
(名前が「abc」ならば、「abc 」となる)
例えばこんな感じです。
# エラーチェック・整合性などは見ていません
TDataRec=record
dummy0: char;
sName: array[0..7] of char;
dummy1: char;
Item1: array[0..7] of char;
dummy2: char;
Item2: array[0..7] of char;
dummy3: char;
Item3: array[0..7] of char;
dummy4: char;
end;
と定義し、
procedure TForm1.Button1Click(Sender: TObject);
var
fs: TFileStream;
flag: char;
dr: TDataRec;
begin
fs := nil;
try
fs := TFileStream.Create('C:\test.txt', fmOpenRead);
while fs.Read(flag, 1)=1 do
begin
case flag of
'A': // 値は3つ
begin
fs.Read(dr, 1+8+1+8+1+8+1+8+2); // 最後の2はCRLF
Memo1.Lines.Add('Name:[' + String(dr.sName) + ']');
Memo1.Lines.Add('Item1:[' + String(dr.Item1) + ']');
Memo1.Lines.Add('Item2:[' + String(dr.Item2) + ']');
Memo1.Lines.Add('Item3:[' + String(dr.Item3) + ']');
end;
'B': // 値は2つ
begin
fs.Read(dr, 1+8+1+8+1+8+2); // 最後の2はCRLF
Memo1.Lines.Add('Name:[' + String(dr.sName) + ']');
Memo1.Lines.Add('Item1:[' + String(dr.Item1) + ']');
Memo1.Lines.Add('Item2:[' + String(dr.Item2) + ']');
end;
else // 値は1つ
begin
fs.Read(dr, 1+8+1+8+2); // 最後の2はCRLF
Memo1.Lines.Add('Name:[' + String(dr.sName) + ']');
Memo1.Lines.Add('Item1:[' + String(dr.Item1) + ']');
end;
end;
end;
finally
if Assigned(fs) then fs.Free;
end;
end;
TMemoryStreamを使っていませんが、Readの使い方は同じです。
もっと良いやり方もあるかと思いますが、サンプルと言うことで。
にしのさん ご丁寧にありがとうございます。
この方法を改良しても同じ結果が得られそうです。
このサンプルをもとに、TFileStream・TMemoryStreamの勉強をしたいと思います。
ありがとうございました。
ツイート | ![]() |