こんにちは。
TObjectListとTStringListを使って、ファイルを入出力したいのですが、
StringGridのデータが、以下の場合、*2の部分だけが、登録されてしまいます。
------------
*1
Bamei := 'はるうらら';
Comment := 'はるが好き';
-----------
*2
Bamei:= 'はいせいこー';
Comment := 'わからん';
------------
*1*2続けてファイルに入力するにはどうすればいいのでしょうか。
TComment=class(TObject)
Bamei:string;//馬名
Comment:string;//コメント
end;
------
var
TC:TComment;
sl:TStringList;
nTosu,Code,i:integer;
begin
TC:=TComment.Create;
sl := TStringList.Create;
try
val(den1.TorokuTosu,nTosu,Code);
for i:=0 to nTosu-1 do begin
if(StringGrid2.Cells[10,i+1]<>'')then begin//コメントが空白でなければ
TC.Bamei:=StringGrid2.Cells[3,i+1];
//Showmessage(TC.Bamei);
TC.Comment:=StringGrid2.Cells[10,i+1];
//Showmessage(TC.Comment);
ol.Add(TC);//登録
end;
end;
for i := 0 to ol.Count-1 do begin
sl.Add(TComment(ol[i]).Bamei);
sl.Add(TComment(ol[i]).Comment);
end;
sl.SaveToFile('c:\TestBamei.txt');
finally
sl.Free;
TC.Free;
end;
end;
ol[0]とol[1]が同じインスタンスになっています。
forの中でcreateすべきです。
解放も、ol[0],ol[1]それぞれ解放しなければ行けません。
# 今の仕様だと、ol[0]を解放した後ol[1]を解放するときエラーになりませんか?
こんにちは。
for i
TC:=TComment.create;
*処理1
end;
sl:=TStringList.Create;
try
*処理2
finally
sl.free;
end;
解放はTStringListだけ記入したのですが、エラー出ずに登録できるようになりました。ただ、新しいデータを登録しようとすると、ボタンを押すたびにデータが削除されて蓄積されません。
チャーリーさん、こんにちは。
以前の質問と同じですね。
既にデータがある場合と、無い場合を分けて考えましょう。
同じところをうろうろしてます。同じくファイルを開けるところで以前と同じエラーが出ているのですが、TStringList.SaveToStreamで、TFileStream.Seekを加える場合どうしたらいいのでしょうか。
TStringListのSaveToFileでする場合、ファイルがある場合とない場合でできますか?
-----------------------------------
ファイルがあってもなくても最初は登録できますが、次登録しようとするとエラーが出ます。
if(FileExists(Filename))then begin
sl.SaveToStream(TFileStream.Create(Filename,fmOpenReadWrite))
else
sl.SaveToStream(TFileStream.Create(Filename,fmCreate));
チャーリーさん、こんにちは。
あれ?質問の最初の時はSaveToFileだったのに、変更したのですか?
データの追加に難儀してますね。
論理を単純にすると本質が見えてくることが多いです。
ファイルにデータを追加して行くのに最も効率がいいのは TFileStream を
使うことです。データが文字列だとして、一行づつ追加していく例を示します。
var
counter:integer;
procedure TForm1.Button1Click(Sender: TObject);
var
fs:TFileStream;
fn,s:string;
begin
fn := 'c:\TestData.txt';
if FileExists(fn) then
fs := TFileStream.Create(fn,fmOpenReadWrite or fmShareDenyWrite)
else
fs := TFileStream.Create(fn,fmCreate or fmShareDenyWrite);
try
s := 'data : '+IntToStr(counter)+#13#10; // 改行を入れておく
Inc(counter);
fs.Seek(0,soFromEnd);// ファイルの末尾にシークして移動
fs.Write(PChar(s)^,Length(s)); // データを追加
finally
fs.Free;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.Lines.LoadFromFile('c:\TestData.txt');// モニタ
end;
Button1 を押すたびに1行ずつ増えていくのが Button2 を押すと見えるでしょう。
TStringList をつかうと、全部読み込んで1行追加し、それから全部上書きすること
になりコードは簡単ですが、効率は良くありません。こんな感じです。
procedure TForm1.Button3Click(Sender: TObject);
var
sl:TStringList;
fn,s:string;
begin
fn := 'c:\TestData.txt';
sl := TStringList.Create;
try
if FileExists(fn) then sl.LoadFromFile(fn);
s := 'data : '+IntToStr(counter);
Inc(counter);
sl.Add(s); // データ追加。この場合は改行は自動的につく
sl.SaveToFile(fn);
finally
sl.Free;
end;
end;
やはり、Button3 を押してから Button2 を押して一行ずつ増えていくのが見てえるでしょう。
繰り返しますが、やりたいことの本質を見極めるには論理を単純化するといいです。
つっかさんこんにちは。
横からすいません。テキストファイルの入出力に自分は、readln,writelnを使っていますが、TFileStreamの方が効率が良いのでしょうか?
AssignFile, Reset, Readln, Writeln, CloseFile などは、古い Pascal
スタイルのファイルアクセス方法ですね。利点は、多分高速で、しかも
OS に依存しない事でしょう。でも事実上 Delphi は Windows 専用です
けどね。
これに対して、Windows API のファイルアクセスをラップした FileOpen,
FileCreate, FileRead, FileWrite, FileSeek, FileClose などの関数も
あります。これらはあまり使われませんが、THandleStream,TFileStream
の実装に使われています。VCL のストリーミングも TFileStream を使って
います。Windows で便利にランダムアクセスするには、TFileStream の方
が圧倒的に便利です。そして、多分、AssignFile などから比較しても
そんなに速度が落ちるわけでもないと思います。
クラスベースのプログラミングでは TFileStream を使っていくべきだ、と
思っています。
テキストファイルに限定すると Readln Writeln は行単位にアクセスできて
便利ですね。これらに相当するメソッドは TFileStream にはありませんし。
簡単につくることは出来ます。
一方、TStringList のように全部読み込んでから操作する場合は、行単位に
アクセスするのも簡単ですし、3行目を削除する、7行目に1行挿入する、
といった行単位の変更が簡単にできます。
このスレッドの質問では既存ファイルの末尾に1行テキストを追加する場合
ですから、簡単にシークできる TFileStream を使いました。
要は、テキストファイルにどのような操作を行いたいかにより使い分けると
いいです。
一般論としては、TFileStream が最も低レベルで便利だと思います。
つっかさん丁寧な解説ありがとうございます。Append 手続で既存のテキストファイルの追加書き込みはできます。
またwriteln(F,値,値2,・・・値n)というふうに複数の文字列を一度に書き込みでき、改行も自動的に付与されるので、writelnは便利です。
スレッドの質問から多少外れてしまい失礼しました。
そうですね。できる、できないの比較では大差ないですね。
ファイルハンドルをつかって、個々の関数や手続きを使って操作するか、
それをラップしたクラスを使うか、の違いだと思います。
わたしにはクラスの方が使いやすいと。
解決しました。
分からないところも多々ありますが。。。
ツイート | ![]() |