C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力


(過去ログ 41 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■21475 / inTopicNo.1)  画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
  
□投稿者/ kaoru (5回)-(2008/07/03(Thu) 00:06:15)

分類:[C#] 

いつもお世話になります。昨日はありがとうございました。
引き続きWindowsXP Pro SP2でVisual C# 2008 Express Editionを使ってプログラムをしています。
オープンダイアログで指定した画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力したいと思っています。
http://dobon.net/vb/dotnet/graphics/getexifinfo.html
などを参考に次のようにしてみました。

//ログファイルのパス
private string logfilePath = System.Windows.Forms.Application.StartupPath + "\\photo.list";

private void selectPhotoButton_Click_1(object sender, EventArgs e)
{
  openFileDialog1.Multiselect = true;
  openFileDialog1.Filter = "Image Files (*.jpg)|*.jpg"; 
  openFileDialog1.Title = "Jpegファイルを選択してください";

  if (openFileDialog1.ShowDialog() == DialogResult.OK)
  {
foreach (string nFileName in openFileDialog1.FileNames)
{
  //MessageBox.Show(nFileName);
  //Console.WriteLine(nFileName);

  //ログファイルへの書き出し用StreamWriterオブジェクトを生成
  System.IO.StreamWriter writer
= new System.IO.StreamWriter(logfilePath, true, System.Text.Encoding.Default);
  //画像ファイル名
  string imgFile = "nFileName";

  //読み込む
  System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(imgFile);
  foreach (System.Drawing.Imaging.PropertyItem item in bmp.PropertyItems)
  {
//Exif情報から撮影時間を取得する
if (item.Id == 0x9003 && item.Type == 2)
{
  //文字列に変換する
  string val = System.Text.Encoding.ASCII.GetString(item.Value);
  val = val.Trim(new char[] { '\0' });
  //DateTimeに変換
  DateTime dt = DateTime.ParseExact(val, "yyyy:MM:dd HH:mm:ss", null);
     }
  }
  bmp.Dispose();

  // ディレクトリ名 (最後に'\\'は付かない)
  // ファイル名と拡張子
  writer.WriteLine(Path.GetDirectoryName(nFileName) + "\\t" + Path.GetFileName(nFileName) + "\\t" + DateTime);
  //閉じる
  writer.Close();
  //戻り値を返す
  //return;

  }
  }
}
これでビルドを実行すると、
エラー	1	'System.DateTime' は '型' ですが、'変数' のように使用されています。
とエラーが出ます。
どのように修正したらよいか、アドバイスいただければと。
よろしくお願いします。

引用返信 編集キー/
■21476 / inTopicNo.2)  Re[1]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
□投稿者/ れい (686回)-(2008/07/03(Thu) 00:27:52)
No21475 (kaoru さん) に返信
> writer.WriteLine(Path.GetDirectoryName(nFileName) + "\\t" + Path.GetFileName(nFileName) + "\\t" + DateTime);

この最後のDateTimeの部分が問題なのですよね。
kaoruさんがここで何をどうしたいのかというのと、
PC(コンパイラ)がこれをどう解釈するかというのと、
食い違っちゃってますよね。

エラーどおり、DateTimeは型なので「値では無い」のです。
取得した「値」が入った入れ物=変数を指定してやらないと
何をWriteLineしたらいいのか分からないです。

#がんばって説明してみましたが…いまいちですね。

引用返信 編集キー/
■21477 / inTopicNo.3)  Re[2]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
□投稿者/ bad14mg (18回)-(2008/07/03(Thu) 00:50:14)
No21476 (れい さん) に返信
> ■No21475 (kaoru さん) に返信
> エラーどおり、DateTimeは型なので「値では無い」のです。
> 取得した「値」が入った入れ物=変数を指定してやらないと
> 何をWriteLineしたらいいのか分からないです。

『画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力したい』
とのことなので、撮影時刻が入った入れ物は?
引用返信 編集キー/
■21479 / inTopicNo.4)  Re[3]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
□投稿者/ ぽぴ王子 (394回)-(2008/07/03(Thu) 06:16:03)
ぽぴ王子 さんの Web サイト
No21475 (kaoru さん) に返信

回答としては、れいさんとbad14mgさんが書かれているとおりだと思います。
あとはどこでエラーが出たのかはちゃんと記述した方がいいですね。
(結局ソースを全部解析してしまった)


このエラーが出る原因は

>                 // ディレクトリ名 (最後に'\\'は付かない)
>                 // ファイル名と拡張子
>                 writer.WriteLine(Path.GetDirectoryName(nFileName) + "\\t" + Path.GetFileName(nFileName) + "\\t" + DateTime);

の部分で、日付型変数ではなく日付型そのものを指定しているためです。

>                         //DateTimeに変換
>                         DateTime dt = DateTime.ParseExact(val, "yyyy:MM:dd HH:mm:ss", null);

ソースを読むに、この変数 dt を使用するのだと思いますが、このままではスコープ外になるので指定できません。
dt をループの外からも参照できるようにしなくてはいけません。
あと DateTime 型の変数をそのまま使うわけにはいきませんので、文字列型に変換する必要があります。

>                         string val = System.Text.Encoding.ASCII.GetString(item.Value);
>                         val = val.Trim(new char[] { '\0' });

むしろここで取り出した val そのままでいいのではないかという気もします(スコープの問題は残りますが)。


あといくつかツッコミ。

>     //ログファイルのパス
>     private string logfilePath = System.Windows.Forms.Application.StartupPath + "\\photo.list";

パスの接続は System.IO.Path.Combine を使用した方がいいかと思います。

>                 // ディレクトリ名 (最後に'\\'は付かない)
>                 // ファイル名と拡張子
>                 writer.WriteLine(Path.GetDirectoryName(nFileName) + "\\t" + Path.GetFileName(nFileName) + "\\t" + DateTime);

タブ区切りにするなら \\t ではなくて \t だと思いますが、大丈夫でしょうか。

>                 //ログファイルへの書き出し用StreamWriterオブジェクトを生成
>                 System.IO.StreamWriter writer = new System.IO.StreamWriter(logfilePath, true, System.Text.Encoding.Default);

どこでエラーが出るかわからないので、StreamWriter は使用する直前でオープンした方がいいでしょうね。

引用返信 編集キー/
■21480 / inTopicNo.5)  Re[3]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
□投稿者/ kaoru (6回)-(2008/07/03(Thu) 06:48:08)
おはようございます。れいさん、bad14mgさん、コメント&ヒントをありがとうございます。
gawk歴は長いのですが、型とか変数という考え方じたいにぜんぜんなじんでいないようです。
「C# 型 変数」で検索したところ、型といってもいろいろあるらしい、ということと、「データ型をあらかじめ宣言しておくことで、メモリを効率よく使うことができます。」ということはわかりました。
いやいや、今回のは変数のようなので、変数を指定すればいいんでしょうか。
「C# 変数を指定」で検索してみました。
ふむ。gawkにも変数はあるということを、去年知ったばかりで、まだうまく使えていません。
いやSystem.DateTimeは型だというのだから、型らしく(?)使わなきゃならないんでしょうか。
入れ物??? とは変数のことですよね? まだ五里霧中です。
「C# 変数」で検索してみました。変数には型があるのですね。「型が変数のように使われている」というエラーメッセージを読むと、型と変数には重複がない別個のもののように読めますが、じつは変数にも型がある(変数の真部分集合が型)なの? かな。
で、変数の型には、論理型だの文字型だの数字型だのがあり、というのがすこし進んだ理解。
え〜と…。
System.DateTimeというのは、
char c; // 文字型の変数 c
string s; // 文字列型の変数 s
…う〜む。

あまりにも険しそうなので、別の道から考えてみました。
「DateTime C#」で検索。

DateTime dt = DateTime.ParseExact(val, "yyyy:MM:dd HH:mm:ss", null);
}
}
bmp.Dispose();
writer.WriteLine(Path.GetDirectoryName(nFileName) + "\\t" + Path.GetFileName(nFileName) + "\\t" + DateTime);
を、
DateTime dt = DateTime.ParseExact(val, "yyyy:MM:dd HH:mm:ss", null);
bmp.Dispose();
writer.WriteLine(Path.GetDirectoryName(nFileName) + "\t" + Path.GetFileName(nFileName) + "\t" + dt.ToString());
}
}
と修正しました。これでビルドは正常終了。お、これで正解?

と思いきや、じっさいにビルドしてアプリケーションを起動して選択してみると、今度は「アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました。」とのこと。
86行目。行数を表示するにはどうしたらいいんだ。あ、ウィンドウの最下部に行数出てますね。
86行は、
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(imgFile);
らしい…。

引用返信 編集キー/
■21481 / inTopicNo.6)  Re[4]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
□投稿者/ kaoru (7回)-(2008/07/03(Thu) 07:12:49)
ぽぴ王子さん、コメントありがとうございます。入れ違いになったようですね。ソースぜんぶ読んでいただいたとのこと。お手数おかけします。まだ解決も理解もできていなかった部分を補足していただいて感謝です。
え〜と、先の検索で、修正したとおり、スコープというのは、{ }のことだと理解しました。これはうまくいったと思います。
さらに、日付型変数でなくて日付型ということなのですね。
おっしゃるように、日付は数字でなくて文字なのじゃないかと思ったので、これまたおっしゃるように、取り出したvalをそのまま使えばいいような気もしてました。
やっぱりそれでいいんだ!
どのみち別の箇所でエラーも出ているので、ということで、
writer.WriteLine(Path.GetDirectoryName(nFileName) + "\t" + Path.GetFileName(nFileName) + "\t" + val.Trim());
と修正してみました。これでもビルドは正常終了。お、これのほうが正解に近そう。
しかし、依然として、例外でアプリケーションが落ちます。う〜む。
あとほかの件。
・System.IO.Path.Combineを使う???
というのは、冒頭で、
using System.IO;
の代わりに、(あるいは追加して?)
using System.IO.Path.Combine;
とするってこと???
あ、そうじゃなくて、
System.IO.StreamWriterをSystem.IO.Path.Combineとするってことですか?
・\\tはタイプミスでした。失礼しました。\\でフォルダの最後の\を書いたつもりで、\tと頭のなかがダブってました。
・System.IO.StreamWriter writer
= new System.IO.StreamWriter(logfilePath, true, System.Text.Encoding.Default);
の2行を、次の行の直前に移動しました。

System.IO.StreamWriter writer
= new System.IO.StreamWriter(logfilePath, true, System.Text.Encoding.Default);
writer.WriteLine(Path.GetDirectoryName(nFileName) + "\t" + Path.GetFileName(nFileName) + "\t" + val.Trim());

というように。これで悪くないような気がするんだけど、う〜む。

現在の問題は、
writer.WriteLine(Path.GetDirectoryName(nFileName) + "\t" + Path.GetFileName(nFileName) + "\t" + val.Trim());
でよさそうなのだけど、ビルドは成功しても、今度は、
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(imgFile);
のところ。
デバッグしてみると、
「ArgumentExceptionはハンドルされませんでした」「使用されたパラメータが有効ではありません。」と。ふむ。

引用返信 編集キー/
■21482 / inTopicNo.7)  Re[5]: 画像ファイルのパス、ファイル名、撮影時刻をタブ区切りで出力
□投稿者/ kaoru (8回)-(2008/07/03(Thu) 07:21:04)
解決しました。
string imgFile = "nFileName";

string imgFile = nFileName;
としたところ、うまく動作し、
パス、ファイル名、撮影時刻をファイルに出力できました。
ありがとうございました!

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -