指定したDirのファイル一覧を表示させるには?

解決


MONTA  2013-03-28 09:00:28  No: 44132

作成したいプログラムは、 VCL のフォームに
EditBOX、ListBox、ボタンを貼り付けます。
EditBox に、Dirパスを入力し、ボタンを押すと、
ListBox に、指定した拡張子のファイル一覧が表示される
というものです。

http://www.gesource.jp/weblog/?p=4509

上記 URL のコードを Delphi で確認したいと思い、
下記のように書き換えてみました。
ところが、①〜④の行でエラーが出ます。
どのようにコード修正すればいいでしょうか。

ご指導の程よろしくお願い致します。

使用環境
WIN 7 64bit SP2
Delphi XE3 Update2

procedure TForm1.Button1Click(Sender: TObject);

  var
  i : integer;
  Path, SearchPattern : UnicodeString;

begin

  //ファイルを列挙したいディレクトリのパス
  Path := Edit1.Text;

  //ファイル名に一致する検索パターン
  SearchPattern := '*.txt';

  //ディレクトリの列挙モード
① TSearchOption Option := TSearchOption::soTopDirectoryOnly;  //トップレベル列挙モード

  //TSearchOption option = TSearchOption::soAllDirectories;  //再帰列挙モード
② TStringDynArray files := TDirectory::GetFiles(Path, SearchPattern, Option);
③ for i := 0 to files.Length-1 do begin
④   ListBox1.Items.Add(files[i]);
  end;

end;


DEKO  2013-03-28 09:47:44  No: 44133

> ところが、①〜④の行でエラーが出ます。
そりゃ、出ると思います。
C++Builder の書式が混ざっていますから。
(ブログのカテゴリーが Delphi じゃなく、C++Builderですよ)

[System.IOUtils.TDirectory]
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.IOUtils.TDirectory

ドキュメントをちゃんと読んでみてください。


DEKO  2013-03-28 15:02:16  No: 44134

1.C++ のスコープ解決演算子(::) は使えません。
  Delphi の場合には .(ドット) を使います。

2.Delphi は変数をその場で定義できません。
  メソッド内の var セクションで、
  変数を前もって定義する必要があります。

3.C++Builder の TStringDynArray は動的配列テンプレートですが、
  Delphi の TStringDynArray は単なる string の動的配列です。
  よって、配列のサイズを得るには Files.Length メソッドではなく、
  Length(Files) のように関数を使う必要があります。

  または、

  for i := Low(files) to High(files) do 

  のようにします (Low / High は配列の要素の下限/上限を返す関数です)。

4.TDirectory を使うためには uses 節に System.IOUtils が必要です。

5.TStringDynArray を使うためには uses 節に System.Types が必要です。


Mr.XRAY  2013-03-28 15:15:29  No: 44135

TDirectory を使いたいというわけではないようですが,
折角 Delphi XE3 ですので.
「TDirectory Delphi」と「ディレクトリ  リスト Delphi」でググッてみました.

結構でてきますが,宣伝を兼ねて
[817_ディレクトリとファイルのリスト]
http://mrxray.on.coocan.jp/Delphi/plSamples/817_DirFileListTest.htm#01

なんかは参考にならないでしょうか.
わざわざ C++ のコードを参考にすることはないと思いますよ.


take  2013-03-28 18:14:33  No: 44136

ものすごく古いやり方だとこれかな

var
  sr : TSearchRec;
begin
  ListBox1.Items.Clear;
  if FindFirst(Path + SearchPattern,$0, sr) = 0 then begin
    repeat
      ListBox1.Items.Add(sr.Name);
    until FindNext(sr) <> 0;
  end;
  FindClose(sr);
end;


tok3  2013-03-28 18:44:59  No: 44137

for 〜 in 〜 do を使うとこんな感じですかね。

var
  S : String;
  :
begin
  :
  for S in TDirectory.GetFiles(Path, SearchPattern, SOption) do begin
    ListBox1.Items.Add(S);
  end;
end;


MONTA  2013-03-28 22:35:04  No: 44138

■恥を偲んで質問します。

●DEKO 先生へ
提示して頂いた下記 URL を質問する前に見たのですが、
文字の羅列にしか見えませんでした。
どういう見方をすればいいか教えて頂けないでしょうか。

[System.IOUtils.TDirectory]
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.IOUtils.TDirectory

お手数かけますがご指導の程よろしくお願い致します。

●Mr.XRAY 先生へ
http://mrxray.on.coocan.jp/Delphi/plSamples/817_DirFileListTest.htm#01

上記 URL を参考に、VCL フォームに、Panal、StatusBar、Button1、Button2、
ListBox を配置して、Button1、Button2 に、コードをコピペしたのですが、
エラーメッセージが出ます。
勿論 Begin end は重複していません。
2010とXE3では、文法が変わってしまったのでしょうか。

お手数かけますがご指導の程よろしくお願い致します。


Mr.XRAY  2013-03-29 00:01:18  No: 44139

>どういう見方をすればいいか教えて頂けないでしょうか。

こちらは,後で,ということで.

>エラーメッセージが出ます。

どういうエラーなのか分からないないと,対処方法は分かりませんね.
「せんしぇい」はエスパーではありません.
エラーをタイプしていたのでは,間違うこともあります.
そんな時は,

[コンパイルのエラーメッセージ等のコピー方法 ( エラー報告用 )]
http://mrxray.on.coocan.jp/Delphi/Others/RunError.htm#03

それと,申し訳ありませんが,MONTAさん場合,
サンプルをダウンロードして,動作を確認した方がいいでしょう.
提示したサンプルは,Delphi 2010 から Delphi XE3 で動作します.

http://mrxray.on.coocan.jp/Delphi/plSamples/817_DirFileListTest.htm#01

↑のページの一番上の方に,フォルダのアイコンがあります.
これをクリックすると,サンプルがダウンとロードできます.
ダウンロードしたら解凍します.
その中の [01_DirFilesListTest01] というフォルダの中にあるのが該当のサンプルです.
Delphi XE3 でそのままプロジェクトを開いて実行すると,いっぱいファイルが
できてしまいます.
以下の図1のように,3 つだけにしてプロジェクトを開いた方がいいかも知れません.

[別のバージョンで作成された Delphi プロジェクトの利用]
http://mrxray.on.coocan.jp/Delphi/Others/Delphi_Versionl.htm#01

ところでいつから「先生」になったのかしら.記憶がないのですが,
でも,中国では,日本の「さん」にあたる敬称が「先生」らしいですね.

>2010とXE3では、文法が変わってしまったのでしょうか。

勝手に決めないでね.まだ決めてはいないようですが.


DEKO  2013-03-29 00:22:17  No: 44140

> どういう見方をすればいいか教えて頂けないでしょうか。

ヘルプの [メソッド] から コードで使われている GetDirectories() メソッドを辿ると、
Delphi と C++Builder の記述の違いが解るハズです。

[System.IOUtils.TDirectory.GetDirectories]
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.IOUtils.TDirectory.GetDirectories

これ以上の事になると、Delphi と C++ の双方の文法をちゃんと理解している必要があります。

> どのようにコード修正すればいいでしょうか。
...という事で付けたのが後のレスです。
ステップバイステップでやると以下のようになります。

var
  i: integer;
  Path, SearchPattern: String;
begin
  //ファイルを列挙したいディレクトリのパス
  Path := Edit1.Text;
  //ファイル名に一致する検索パターン
  SearchPattern := '*.txt';
  //ディレクトリの列挙モード
  TSearchOption Option := TSearchOption::soTopDirectoryOnly;  //トップレベル列挙モード
  TStringDynArray files := TDirectory::GetFiles(Path, SearchPattern, Option);
  for i := 0 to files.Length-1 do 
    ListBox1.Items.Add(files[i]);
end;


>1.C++ のスコープ解決演算子(::) は使えません。

  //ディレクトリの列挙モード
  TSearchOption Option := TSearchOption.soTopDirectoryOnly;  //トップレベル列挙モード  // <- 置換 (1.)
  TStringDynArray files := TDirectory.GetFiles(Path, SearchPattern, Option);           // <- 置換 (1.)


> 2.Delphi は変数をその場で定義できません。

var
  ...
  Option: TSearchOption;   // <- ここに定義 (2.)
  files: TStringDynArray;  // <- ここに定義 (2.)
begin
...  
  //ディレクトリの列挙モード
  Option := TSearchOption.soTopDirectoryOnly;  //トップレベル列挙モード // <- 修正 (2.)
  files := TDirectory.GetFiles(Path, SearchPattern, Option);            // <- 修正 (2.)


> 3.C++Builder の TStringDynArray は動的配列テンプレートですが、

  for i:=Low(files) to High(files) do // <- 変更 (3.)


4.TDirectory を使うためには uses 節に System.IOUtils が必要です。
5.TStringDynArray を使うためには uses 節に System.Types が必要です。

uses
  ..., System.IOUtils, System.Types; // ← 上の方にある uses に追加するという意味 (4. 5.)

# 一つずつこなしていけば動作するハズですが...試されましたか?


MONTA  2013-03-31 10:08:50  No: 44141

Mr.XRAY 先生、DEKO 先生 ご指導ありがとうございました。
DEKO 先生にご指導して頂いたとおりにコードを追加して
動作する事を確認しました。
自分の未熟さが分かり恥ずかしいです。
Mr.XRAY 先生のサンプルコードも非常に参考になります。
この質問をする前に、VC# 2012 で同等のものを作成しようと思い、
WEBを自力で調べてなんとかできたのですが、
(Delphi より C# の方がユーザーが多いのでしょうか?)
ちょっとびっくりしたのは、Delphi XE3 だと
uses に、System.IOUtils, System.Types を手書きで追加する
必要があるのですね。
フォームに部品をペタペタ貼り付ける Delphi なら
こんな事は必要ないという先入観がありました。
Delphi は、Fire Monkey が導入され、Mac 対応や、3D の強化、64bit対応、
また今後は、iOS や アンドロイド対応ということで期待していました。
Visual Studio と完全におさらばして、
RAD 1本で行こうかと考えていましたが
もう少し様子を見ようという考えになりました。


DEKO  2013-03-31 13:39:37  No: 44142

> ちょっとびっくりしたのは、Delphi XE3 だと
> uses に、System.IOUtils, System.Types を手書きで追加する
> 必要があるのですね。

Delphi に限らず、ほぼすべての言語で同様の作業が必要だと思います。
C / C++ では #include がありますし、C# にも using があるでしょう?

[プログラムとユニット (DocWiki)]
http://docwiki.embarcadero.com/RADStudio/XE3/ja/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%A8%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88

> フォームに部品をペタペタ貼り付ける Delphi なら
> こんな事は必要ないという先入観がありました。

コンポーネントをフォームに貼り付けた場合には、
そのコンポーネントが利用するユニットが自動的に uses に追加されます。

関数やクラスをコード中で使う場合には、
自分で uses 節に追加しなければなりません。

同じ名前の関数やクラス名が複数のユニットに存在する場合、
どちらを参照すればいいのかなんて、コンパイラが判断できる訳ないですからね。

> Delphi は、Fire Monkey が導入され、Mac 対応や、3D の強化、64bit対応、
> また今後は、iOS や アンドロイド対応ということで期待していました。
> Visual Studio と完全におさらばして、
> RAD 1本で行こうかと考えていましたが
> もう少し様子を見ようという考えになりました。

uses しなければいけない事と、マルチプラットフォームに何の因果関係があるのでしょう?
C++ / C# でも同じような機構があるのに、どうして Delphi "だけ" ダメなのでしょう?

以下に列挙されているユニットを、あらかじめ "すべて" uses 節に記述しておけば、
大抵のものは使えますよ。その結果出来上がったバイナリがどんだけ肥大化していようが知りませんけど。

[ユニット スコープ名]
http://docwiki.embarcadero.com/RADStudio/XE3/ja/%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88_%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97%E5%90%8D#.E3.83.A6.E3.83.8B.E3.83.83.E3.83.88_.E3.82.B9.E3.82.B3.E3.83.BC.E3.83.97

普通は逆なのです。
使いたい機能があるのであれば、それが属するユニット名はその時点で知り得ます。
ですからそれを uses に追加するだけの話なのです。

ところが、Web 等に上がっているコードをコピペすると、
そこで使われている機能 (関数やクラス) がどのユニットに属するのかを自前で調べなくてはなりません。
サンプルコードは実際のプロジェクトの一部を切り出したものだったりするため、
uses 節に追加すべきユニットまでは記載してない事があるからです。

# uses 節に追加すべきユニットが記載されていなくても、
# 情報提供者に文句を言える立場にありません。あなたが情報提供する側だったら、
# 皆が既知の事項をわざわざ何度も書きますか?という話ですから。

そのような場合には $(BDS)\Source 内を Grep するなり (Pro 以上の SKU)、
DocWiki で検索するなりして、属するユニットを探さなくてはなりません。

例えば今回の例だと、

[DocWiki]
http://docwiki.embarcadero.com/RADStudio/XE3/ja/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8

TDirectory を検索すると
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.IOUtils.TDirectory
が見つかります。
親: のリンクを辿ると、属するユニットが判りますし、URL にもそれが含まれています。

同様に TStringDynArray だと以下ですね。
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.Types.TStringDynArray
System.Types が属するユニット (名前空間) です。

ちなみに今回の件に関して、
山本隆さんが Delphi でのコードを書いてらっしゃいます。

[DelphiのTDirectory.GetFilesでファイルの一覧を取得する]
http://www.gesource.jp/weblog/?p=5959

# 親切だなぁ... (^^;A


Mr.XRAY  2013-03-31 14:37:42  No: 44143

>フォームに部品をペタペタ貼り付ける Delphi なら

>こんな事は必要ないという先入観がありました。

ビジュアルなコンポならそうですね.
もしかして,最近のマイクロソフトの開発言語は,
インクルードも自動で挿入してくれるのかと思ってしまいました.

>本隆さんが Delphi でのコードを書いてらっしゃいます。

にくいんですよね.山本さん,
それとなく,さりげなくやってしまうんですから.紳士です.


MONTA  2013-04-02 09:29:14  No: 44144

Mr.XRAY 先生、DEKO 先生 ご指導ありがとうございました。
教えて頂いた URL をよく見て勉強を深めたいと思います。

冷静に考えてみました。
Delphi は、Fire Monkey が導入され、Mac 対応や、3D の強化、64bit対応、
また今後は、iOS や アンドロイド対応になります。
もうこれだけで、Visual Studio より優位なのは明らかですね。

じゃあ、Visual Studio と完全におさらばして、
いつ RAD に切り替えるんですか?
(皆様ご唱和ください)


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

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






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