ディレクトリ内の指定した画像の次の画像ファイルの読み込み

解決


谷町  2015-02-23 19:02:39  No: 47067

指定した画像の次の画像ファイルの読み込み

ファイルは画像ファイルで
フォルダ名が年月
ファイル名は年月+連番という仕組みの中で
例)
C:\image\2505\2505000001.jpg
C:\image\2506\2506000001.jpg

ファイル名を昇順にした時の指定したファイルの
次の画像を読込させたいのです。

FileListBoxを使用して次の様にしてみたのですが、
1ディレクトリでファイルが5万個ぐらいあり、速度が遅いので、
早く表示するにはどうすれば良いかご教示お願いします。

下記は現在選択されているTImageのファイル名をFileListBoxのパスに関連付、
次の画像を探して表示するというものです。
これがディレクトリが変わる毎にApplyFilePathをするのですが、
すごく遅くて、もう少し早い方法はないかな、と思って質問させて頂きました。

宜しくお願い致します。

if FileExists(Image.Picture.GetFileName) = true then begin
  FileListBox1.ApplyFilePath(Image.Picture.GetFileName);
  //フォルダ内個数を超えた場合
  if FileListBox1.Items.Count = Succ(FileListBox1.ItemIndex) then begin
    MessageDlg('次の画像が存在しません。', mtInformation,[mbOk], 0);
    exit;
  end;
  FileListBox1.ItemIndex := Succ(FileListBox1.ItemIndex);
  Image.Picture.LoadFromFile(FileListBox1.FileName);
  label.Caption:=FileListBox1.FileName;
end;


igy  2015-02-23 20:48:13  No: 47068

> 1ディレクトリでファイルが5万個ぐらいあり、速度が遅いので、

1つのフォルダに格納するファイルの数を減らす のは、いかがですか?


通りすがり  2015-02-23 22:02:21  No: 47069

FileListBoxを使わず、自前でFindFirst/FindNext/FindCloseでファイルを検索し、表示も必要な範囲に絞ってみる、
というのはどうでしょう?
http://docwiki.embarcadero.com/Libraries/XE7/ja/System.SysUtils.FindFirst

FileListBoxが遅いのは、ListBoxとしての表示内容をWindowsの管理下においているから、ということがあります。


deldel  2015-02-23 22:45:42  No: 47070

例えば、以下のようにファイル名を全部リストアップし、
後から1つずつ見るような感じですかね?

var
  iFound : integer;
  SearchRec : TSearchRec;
begin
  iFound := FindFirst('C:\image\2505\*.jpg', faAnyFile, SearchRec);
  while iFound = 0 do begin
    ListBox1.Items.Add(SearchRec.Name);
    iFound := FindNext(SearchRec);
  end;
  FindClose(SearchRec);
end;


谷町  2015-02-23 23:06:47  No: 47071

皆様 素早い回答ありがとうございました。

igy様
ファイルの数を減らしたいのは山々なんですが、元々決まってるところを変えるのは難しくて断念しました。

通りすがり様
>FileListBoxが遅いのは、ListBoxとしての表示内容をWindowsの管理下においているから、ということがあります。

やはりそうなんですね。なんとなくそんな気はしてました。

deldel様
今回配列にディレクトリ全部を入れて
回すほうが早かったのでそのようにしました。

一応できたプログラムが以下です。
もっといいやりようはあるのかもしれませんが。。
問題なく動作しているようなのでこれで行こうかと思います。

XE3でしたので、こちらを参考にしました
http://www.gesource.jp/weblog/?p=5959

uses System.IOUtils, System.Types;

function Show_Next_Image(strFilePath:string):boolean;
var
  intCnt:integer;
  strFileDir:string;
  strFileName:string;
  strSearchPattern: string;
  Option:TSearchOption;
  arrFileNames:TStringDynArray;
begin
  result:=false;
  //ファイルのディレクトリを取り出す
  strFileDir:=IncludeTrailingPathDelimiter(ExtractFilePath(strFilePath));
  //ファイル名に一致する検索パターン
  strSearchPattern := '*.jpg';
  //ディレクトリの列挙モード
  Option := TSearchOption.soTopDirectoryOnly; // トップレベル列挙モード
  //指定のディレクトリ内のファイルのリスト
  arrFileNames := TDirectory.GetFiles(strFileDir,strSearchPattern, Option);
  //指定カウント用
  intCnt:=0;
  //配列ループ
  for strFileName in arrFileNames do begin
    //現在表示中の画像が最後かどうか
    if strFilePath = arrFileNames[High(arrFileNames)] then begin
      MessageDlg('次の画像が存在しません。', mtInformation,[mbOk], 0);
      exit;
    end;
    //現在開いているファイル名までループ
    try
      if strFileName = strFilePath then
        Image.Picture.LoadFromFile(arrFileNames[Succ(IntCnt)])
    except
      on e:Exception do begin
        MessageDlg('画像表示中に不具合が発生しました。'+#13#10 +
                   '[Err] ' +e.Message, mtError,[mbOk], 0);
        exit;
      end;
    end;
    Inc(IntCnt);
  end;

  result:=true;
end;


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加