サンプル集  >  C#  >  find+grep⑤
find+grep⑤
2017/11/14

指定したフォルダにあるファイル内の指定した文字列を含む行を抽出します。

◆動作環境
OS Windows 7 Professional Service Pack 1 64bit

変更点

find+grep④に以下の変更を行いました。

  1. アクセスが拒否された場合の処理を追加。
  2. エラーを表示している行に行数設定がないため、ファイルに出力できない不具合を修正。

Form1.cs
  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
134: 
135: 
136: 
137: 
138: 
139: 
140: 
141: 
142: 
143: 
144: 
145: 
146: 
147: 
148: 
149: 
150: 
151: 
152: 
153: 
154: 
155: 
156: 
157: 
158: 
159: 
160: 
161: 
162: 
163: 
164: 
165: 
166: 
167: 
168: 
169: 
170: 
171: 
172: 
173: 
174: 
175: 
176: 
177: 
178: 
179: 
180: 
181: 
182: 
183: 
184: 
185: 
186: 
187: 
188: 
189: 
190: 
191: 
192: 
193: 
194: 
195: 
196: 
197: 
198: 
199: 
200: 
201: 
202: 
203: 
204: 
205: 
206: 
207: 
208: 
209: 
210: 
211: 
212: 
213: 
214: 
215: 
216: 
217: 
218: 
219: 
220: 
221: 
222: 
223: 
224: 
225: 
226: 
227: 
228: 
229: 
230: 
231: 
232: 
233: 
234: 
235: 
236: 
237: 
238: 
239: 
240: 
241: 
242: 
243: 
244: 
245: 
246: 
247: 
248: 
249: 
250: 
251: 
252: 
253: 
254: 
255: 
256: 
257: 
258: 
259: 
260: 
261: 
262: 
263: 
264: 
265: 
266: 
267: 
268: 
269: 
270: 
271: 
272: 
273: 
274: 
275: 
276: 
277: 
278: 
279: 
280: 
281: 
282: 
283: 
284: 
285: 
286: 
287: 
288: 
289: 
290: 
291: 
292: 
293: 
294: 
295: 
296: 
297: 
298: 
299: 
300: 
301: 
302: 
303: 
304: 
305: 
306: 
307: 
308: 
309: 
310: 
311: 
312: 
313: 
314: 
315: 
316: 
317: 
318: 
319: 
320: 
321: 
322: 
323: 
324: 
325: 
326: 
327: 
328: 
329: 
330: 
331: 
332: 
333: 
334: 
335: 
336: 
337: 
338: 
339: 
340: 
341: 
342: 
343: 
344: 
345: 
346: 
347: 
348: 
349: 
350: 
351: 
352: 
353: 
354: 
355: 
356: 
357: 
358: 
359: 
360: 
361: 
362: 
363: 
364: 
365: 
366: 
367: 
368: 
369: 
// 2016.01.08 サブフォルダの検索指定ができるよう機能追加。
//            ファイルを開くときにIOExceptionが発生した場合、
//            処理を続行するよう修正。
//            出力結果の表示をListBoxからListViewへ変更。
// 2016.01.27 ListViewのAnchorプロパティにBottom、Rightを追加。
//            「結果をファイルに出力」ボタンを移動。
// 2017.09.11 文字列を見つけた行数を表示するよう変更。
//            行数を表示するカラムを右詰め表示にしたいため、
//            ListViewをオーナードローへ変更。
// 2017.11.14 アクセスが拒否された場合の処理を追加。
//            エラーを表示している行に行数設定がないため、
//            ファイルに出力できない不具合を修正。
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
                                   , "0"
                                   };
                    listView_Result
                        .Items.Add( new ListViewItem( row ) );
                }
                catch ( UnauthorizedAccessException uae )
                {
                    // ファイルへのアクセスが拒否されると
                    // UnauthorizedAccessExceptionが発生する。
                    string[] row = { file_path
                                   , uae.Message
                                   , "0"
                                   };
                    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
                                         );
                }
            }
        }
    }
}

▲ PageTop  ■ Home


Copyright (C) 2017 ymlib.com