// 2016.01.08 サブフォルダの検索指定ができるよう機能追加。 // ファイルを開くときにIOExceptionが発生した場合、 // 処理を続行するよう修正。 // 出力結果の表示をListBoxからListViewへ変更。 // 2016.01.27 ListViewのAnchorプロパティにBottom、Rightを追加。 // 「結果をファイルに出力」ボタンを移動。 // 2017.09.11 文字列を見つけた行数を表示するよう変更。 // 行数を表示するカラムを右詰め表示にしたいため、 // ListViewをオーナードローへ変更。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace MyFindAndGrep { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int ret = 0; int cnt = 0; if ( ( textBox_Folder.Text.Count() <= 0 ) || ( textBox_Letter.Text.Count() <= 0 ) ) { MessageBox.Show( "対象フォルダと検索文字列を" + "入力してください。" , "Question" , MessageBoxButtons.OK , MessageBoxIcon.Question ); return; } // リストボックスの消去 listView_Result.Items.Clear(); // find+grepの実行 ret = DoFindAndGrep( textBox_Folder.Text , textBox_Letter.Text , checkBox_SubFolder.Checked , listView_Result , ref cnt ); // 結果表示 MessageBox.Show( "検索が終わりました。\n" + "発見した数:" + cnt + "\n" + "終了コード:" + ret , "Information" , MessageBoxButtons.OK , MessageBoxIcon.Information ); } private int DoFindAndGrep( string folder , string letter , bool subfolder , ListView listView_Result , ref int cnt ) { int ret = 0; // サブフォルダーの検索指示があるか if ( subfolder ) { // 指定されたディレクトリ配下の // ディレクトリを取得 string[] dirs = Directory.GetDirectories( folder ); foreach ( string s in dirs ) { // 再帰呼び出し ret = DoFindAndGrep( s , letter , subfolder , listView_Result , ref cnt ); } } // 指定されたディレクトリ配下のファイルを取得 string[] files = Directory.GetFiles( folder ); foreach( string file_path in files ) { try { ret = DoFileRead( file_path , letter , listView_Result , ref cnt ); if (ret != 0) { break; } } catch ( IOException ioe ) { // ファイルが別のプロセスで使用中だと // IOExceptionが発生する。 string[] row = { file_path , ioe.Message }; listView_Result .Items.Add( new ListViewItem( row ) ); } } return ret; } private int DoFileRead( string file_path , string letter , ListView listView_Result , ref int cnt ) { int ret = 0; // ファイルを開く StreamReader sr = new StreamReader( file_path , Encoding.GetEncoding( "Shift_JIS" ) ); // ファイルを1行ずつ読み込む string line = ""; for ( int i = 0; ; i++ ) { line = sr.ReadLine(); if ( line == null ) { break; } ret = DoGrep( line, letter ); if ( ret == 0 ) { // 取得結果をListViewへ設定 string[] row = { file_path , (i+1).ToString() , line }; listView_Result .Items.Add( new ListViewItem( row ) ); cnt++; } } // ファイルを閉じる sr.Close(); return 0; } private int DoGrep( string line , string letter ) { // lineにletterが含まれるか調べる int idx = line.IndexOf( letter ); if ( idx >= 0 ) { // 含まれる return 0; } // 含まれない return -1; } // 検索フォルダを選択するボタンの処理 private void button2_Click( object sender, EventArgs e ) { FolderBrowserDialog fbd = new FolderBrowserDialog(); // 説明テキスト fbd.Description = "フォルダを指定してください"; // デフォルトフォルダー fbd.RootFolder = Environment.SpecialFolder.Desktop; // ダイアログを表示 DialogResult rslt = fbd.ShowDialog( this ); if ( rslt == DialogResult.OK ) { textBox_Folder.Text = fbd.SelectedPath; textBox_Letter.Focus(); } } // 出力結果(リストの内容)をファイルに書き出す // ボタンの処理 private void button3_Click( object sender, EventArgs e ) { // 出力リストの件数を確認 if ( listView_Result.Items.Count <= 0 ) { // 結果表示 MessageBox.Show( "出力する内容がありません。" , "Information" , MessageBoxButtons.OK , MessageBoxIcon.Exclamation ); return; } SaveFileDialog sfd = new SaveFileDialog(); // 説明テキスト sfd.Title = "保存先のファイルを指定してください"; // 保存するファイルの名前 sfd.FileName = textBox_Letter.Text + ".txt"; // ダイアログを表示 DialogResult rslt = sfd.ShowDialog( this ); if ( rslt != DialogResult.OK ) { return; } // ファイルを開く StreamWriter sw = new StreamWriter( sfd.FileName , true , Encoding.GetEncoding( "Shift_JIS" ) ); // 取得した出力リストの内容を1行ずつファイルに // 書き込む for ( int i = 0; i < listView_Result.Items.Count; i++ ) { ListViewItem item = listView_Result.Items[i]; sw.WriteLine( item.SubItems[0].Text + "\t" + item.SubItems[1].Text + "\t" + item.SubItems[2].Text ); } // ファイルを閉じる sw.Close(); // 結果表示 MessageBox.Show( "リストの内容をファイルに出力しました。\n" + "ファイル名:" + sfd.FileName , "Information" , MessageBoxButtons.OK , MessageBoxIcon.Information ); } private void Form1_Load( object sender, EventArgs e ) { // 行番号のカラムのデータを右詰めにするために、 // ListViewをオーナードローに変更 listView_Result.OwnerDraw = true; // ListViewを詳細表示に設定 listView_Result.View = View.Details; // ListViewにタイトル行を追加 listView_Result.Columns.Add("ファイル名"); listView_Result.Columns.Add("行番号"); listView_Result.Columns.Add("行の内容"); } private void listView_Result_DrawSubItem ( object sender , DrawListViewSubItemEventArgs e ) { switch (e.ColumnIndex) { case 1: // 行番号のカラムだけ右寄せ e.DrawText(TextFormatFlags.Right); break; case 0: case 2: default: // 他のカラムはデフォルト e.DrawText(TextFormatFlags.Default); break; } } private void listView_Result_DrawColumnHeader ( object sender , DrawListViewColumnHeaderEventArgs e ) { using ( StringFormat sf = new StringFormat() ) { e.DrawBackground(); using ( Font headerFont = new Font( "MS UI Gothic" , 9 , FontStyle.Regular ) ) { // 水平方向の配置 sf.Alignment = StringAlignment.Center; // 垂直方向の配置 sf.LineAlignment = StringAlignment.Center; e.Graphics.DrawString( e.Header.Text , headerFont , Brushes.Black , e.Bounds , sf ); } } } } }