ListViewのファイルへの一括書込と読込をするには?

解決


武田  2005-04-14 07:03:36  No: 14290  IP: [192.*.*.*]

皆様、また初歩的な質問ですがどうかお許し下さい。WinXP Delphi6 Personalです。
FindFirst()FindNext()で検索したファイルパス付きNameを
 ListBox1.Items.Add(SearchRec.Name);で保存しておき、検索が終わったら
ListBox1.Items.SaveToFile('Temp.txt');でファイルに書き込んでいます。
読む込むときは、
ListBox1.Items.LoadFromFile('Temp.txt') ;を実行しています。
しかし、もっと色々できるような「ListView」があることを知り、ListBoxから乗り換えようとして奮戦しています。
      with ListView1 do 
      begin
        ListItem:=Items.Add;
        ListItem.Caption:=SearchRec.Name;
        ListItem.SubItems.Add(IntToStr(SearchRec.Size));
        ListItem.SubItems.Add(DateToStr(FileDateToDateTime(SearchRec.Time)));
       end;
で抽出しListViewに書いて表示まではできるのですが、このListViewのデータをListBox1.Items.SaveToFile();に変わるファイルに書く方法が解りません。
同時に、ファイルから一括で読み込む方法も解りません。
過去ログの例は、データを加工して書き込む高度な例のような気がします。
上記のデータの登録もリストボックスと大分違っているので、ホントにこれでいいのかなと思っています。
どうぞよろしくお願い致します。m(__)m

編集    削除
通りすがり  2005-04-14 09:34:34  No: 14291  IP: [192.*.*.*]

いっそのこと、別にTstringListなどを用意し、
それに各項目を追加していき、
最後にSaveToFileで保存してみてはいかがでしょうか。

編集    削除
通りすがりV2  2005-04-14 10:07:20  No: 14292  IP: [192.*.*.*]

てきとうに書いたけど、↑は、こんな感じか?

var
  i:Integer;
  f:TStringList;
begin
  f := TStringList.Create;
  for idx := 0 to ListView1.Items.Count -1 do begin
    f.Add(ListView1.Items[i].Caption + ',' + 
          ListView1.Items[i].SubItems.CommaText);
  end;
  f.SaveToFile(てきとうなふぁいる);
  f.Free;
end;

# IDEからのコピペじゃないから、動くかわからんかったりする
# 一応・・・『通りすがり』さんとは、別人です、ハイ。

編集    削除
武田  2005-04-14 20:00:27  No: 14293  IP: [192.*.*.*]

通りすがりさん、通りすがりさんV2さん、ありがとうございます。
私レベルで書いて頂いてお手数かけます。
TStringListを介して、ファイル保存、読み出しをするということですね。
それでやってみます。
ありがとうございました。また教えてください。m(__)m

編集    削除
大豆Z  2005-04-14 20:05:37  No: 14294  IP: [192.*.*.*]

ファイル名には、スペースを含んでいることがあるので
Captionは  修正したほうがいいと思います。

function DoubleQuoteText(Text : String) : string;
 var  s : string; i:integer;
begin
  if (Pos(' ',Text)>0) or(Pos(',',Text)>0)or(Pos('"',Text)>0) then
  begin
    if Length(Text)>0 then
    for i := 1 to Length(Text) do
      if Text[i]='"' then
            s := s+ Text[i] + '"'
       else   s := s+ Text[i];
    Result := '"' +s+ '"';
  end
  else
    Result := Text;
end;

procedure ListViewSaveToFile(aListView : TListView; Filename: string);
var
  i : Integer;
  StrList :TStringList;
begin
  StrList := TStringList.Create;
  try
    for i := 0 to aListView.Items.Count -1 do begin
      StrList.Add(DoubleQuoteText(aListView.Items[i].Caption) + ',' +
         aListView.Items[i].SubItems.CommaText);
    end;
    StrList.SaveToFile(Filename);
  finally
    StrList.Free;
  end;
end;

procedure ListViewLoadFromFile(aListView : TListView; Filename: string);
var
  i , j , Max : Integer;
  StrList , StrList2 :TStringList;
  Str : string;
  NewItem : TListItem;
begin
  StrList := TStringList.Create;
  try
    aListView.Clear;  // クリア
    StrList.LoadFromFile(Filename);
    StrList2 := TStringList.Create;
    try
      Max := 0;
      for i := 0 to StrList.Count -1 do
      begin
        StrList2.CommaText := StrList.Strings[i];
        NewItem := aListView.Items.Add;
        for j := 0 to StrList2.Count -1 do
        begin
          if (j = 0) then
             NewItem.Caption := StrList2.Strings[0]
           else
             NewItem.SubItems.Add(StrList2.Strings[j]);
          // 最大のSubItemsの個数を記録
          if (Max < j) then Max := j;
        end;
      end;
{
      // SubItemsの長さが足りない物があったら最大に調整
      for i := 0 to aListView.Items.Count -1 do
       with aListView.Items[i].SubItems do
        if (Count < Max) then
          for j := Max - Count downto 1 do  Add('');
}
    finally
      StrList2.Free;
    end;
  finally
    StrList.Free;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
   ListViewSaveToFile(ListView1,'Temp.txt');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ListViewLoadFromFile(ListView1,'Temp.txt');
end;

編集    削除
武田  2005-04-15 01:23:29  No: 14295  IP: [192.*.*.*]

大豆Zさん、懇切丁寧な解説をありがとうございました。
じつは、テキストファイルからListViewに戻すのにも困っていました。
それで、再びこのBBSを覗いてみたら天の救いか大豆Zさんのご指導がありました。ありがとうございました助かります。
それで、あれこれやっていて、おもしろいことが解りました。
フォルダの2200個のファイルを検索するのに、ListBox表示で1分3秒、ListView表示で4分強、StringListに記録だけなら1秒、大分差があるのでびっくりです。
ありがとうございました。また教えてください。
(#Delphi6のヘルプを見ていたのですが、私のレベルでは、ヘルプのヘルプが欲しい。)

編集    削除
武田  2005-04-15 01:25:41  No: 14296  IP: [192.*.*.*]

自己レス。
すみません。22000個の間違いでした。

編集    削除
通りすがらないV2  2005-04-15 03:03:21  No: 14297  IP: [192.*.*.*]

大豆Zさんのレスについて補足。
# こんな関数もあるということで

SysUtils.pas ユニットに引用符「"」をつけたりはずしたりする関数あります。
AnsiQuotedStr
AnsiExtractQuotedStr

D5 にあるので、D6 でもあるでしょう。

# 不思議と、AnsiExtractQuotedStrの引数はPCharだったりする。

編集    削除
大豆Z  2005-04-15 04:09:31  No: 14298  IP: [192.*.*.*]

>フォルダの2200個のファイルを検索するのに、ListBox表示で1分3秒、
>ListView表示で4分強、StringListに記録だけなら1秒、大分差があるのでびっくりです。
  激汗  (^_^;)
ごめんなさい。  しばらくListview使っていないので忘れていました・・・
大量のデータを読み書きするには、画面の更新を停止させたほうがいいです。

procedure ListViewLoadFromFile
のほうに  最初と最後に
begin
    aListView.Items.BeginUpdate;
    try


    finally
      aListView.Items.EndUpdate;
    end;
end;

と付け加えてください  m(_ _)m

編集    削除
武田  2005-04-15 06:20:09  No: 14299  IP: [192.*.*.*]

通りすがらないV2さん、大豆Zさん、重ねてありがとうございます。
どちらも、自分なりに消化しながら組み込んでいきます。
AnsiQuotedStr、AnsiExtractQuotedStrはヘルプに解りやすく書いてありましたから取り入れます。
大豆Zさんのは、速度改善のため早速やります。
ありがとうございました。m(__)m

編集    削除