2009-05-13 18 views
22

テキストの書式設定では、私はもっと複雑なものを意味していました。C#でテキストファイルを解析する方法

私は最初に、私のプロジェクトにこの質問をしているテキストファイルから5000行を手動で追加し始めました。

テキストファイルは、異なるlength.For例に5000本のラインた:最初の文字(1)と第2の文字(1/4/5)間

1 1 ITEM_ETC_GOLD_01 골드(소) xxx xxx xxx_TT_DESC 0 0 3 3 5 0 180000 3 0 1 0 0 255 1 1 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 0 -1 0 -1 0 0 0 0 0 0 0 100 0 0 0 xxx item\etc\drop_ch_money_small.bsr xxx xxx xxx 0 2 0 0 1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0 0 0 0 0 0 0 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1 표현할 골드의 양(param1이상) -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx 0 0 

1 4 ITEM_ETC_HP_POTION_01 HP 회복 약초 xxx SN_ITEM_ETC_HP_POTION_01 SN_ITEM_ETC_HP_POTION_01_TT_DESC 0 0 3 3 1 1 180000 3 0 1 1 1 255 3 1 0 0 1 0 60 0 0 0 1 21 -1 0 -1 0 -1 0 -1 0 -1 0 0 0 0 0 0 0 100 0 0 0 xxx item\etc\drop_ch_bag.bsr item\etc\hp_potion_01.ddj xxx xxx 50 2 0 0 1 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0 0 0 0 0 0 0 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 120 HP회복양 0 HP회복양(%) 0 MP회복양 0 MP회복양(%) -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx 0 0 

1 5 ITEM_ETC_HP_POTION_02 HP 회복약 (소) xxx SN_ITEM_ETC_HP_POTION_02 SN_ITEM_ETC_HP_POTION_02_TT_DESC 0 0 3 3 1 1 180000 3 0 1 1 1 255 3 1 0 0 1 0 110 0 0 0 2 39 -1 0 -1 0 -1 0 -1 0 -1 0 0 0 0 0 0 0 100 0 0 0 xxx item\etc\drop_ch_bag.bsr item\etc\hp_potion_02.ddj xxx xxx 50 2 0 0 2 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0 0 0 0 0 0 0 0 0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 220 HP회복양 0 HP회복양(%) 0 MP회복양 0 MP회복양(%) -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx -1 xxx 0 0 

テキストが空白ではない、それはですそのテキストファイルには空白がありません。私が欲しいもの

私はパスを示す第2の整数(私は上記の投稿三行では、第二の整数は1,4および5です)と、各ラインの中央に文字列を取得したいです( "item \"で始まり、ファイル拡張子 ".ddj"で終わります)。

私の問題:

私は「テキストフォーマットのC#を」Googleの場合は - 私が得るすべては、テキストファイルを開く方法とテキストを検索する方法がわからないC#.Iでテキストファイルを作成する方法であります上記の3行のような小さな整数の場合は、 "1"が存在するかもしれないので、私はcorrentの場所を見つけることができませんので、私は最初の整数を検索することはできません別の場所に

私の質問:私は何も削除だろうプログラムを書くが、私は必要なものならば

それが最善でしょう。

私は上記のように、私の心の中で他の方法は、直接そのファイルの中身を検索することですが、 - その低すぎる場合、私は2番目の整数の間違った場所を取得する可能性があります。

何かお勧めしますが、私はこれを手作業でフォーマットすることはできません。

+7

"そのテキストファイルには空白がありません" FYI:タブ文字は空白です。あなたがここ –

+0

私の努力である「というテキストファイルにスペースが含まれていない」意味: は、[ラインの解析およびCSV文字列を作成する間にカンマを設定]が[1] [1]:HTTP ://stackoverflow.com/a/27244009/1147352 – DareDevil

答えて

48

OKは、ここで我々は何をすべきかです。次に、2番目の整数を取得し、残りの部分をループしてパスを探します。

StreamReader reader = File.OpenText("filename.txt"); 
string line; 
while ((line = reader.ReadLine()) != null) { 
    string[] items = line.Split('\t'); 
    int myInteger = int.Parse(items[1]); // Here's your integer. 
    // Now let's find the path. 
    string path = null; 
    foreach (string item in items) { 
     if (item.StartsWith("item\\") && item.EndsWith(".ddj")) { 
      path = item; 
     } 
    } 

    // At this point, `myInteger` and `path` contain the values we want 
    // for the current line. We can then store those values or print them, 
    // or anything else we like. 
} 
+0

ありがとう、私はそれをテストし、フィードバックを与えるでしょう! –

+0

作品ありがとう、ありがとう! –

+1

素晴らしい。私はこのマシンにC#コンパイラを持っていないので、私はそれを持っていなければなりませんでした。それを聞いてうれしいですが、それは箱の外で動作します。 –

5

あなたが何か行うことができます:

using (TextReader rdr = OpenYourFile()) { 
    string line; 
    while ((line = rdr.ReadLine()) != null) { 
     string[] fields = line.Split('\t'); // THIS LINE DOES THE MAGIC 
     int theInt = Convert.ToInt32(fields[1]); 
    } 
} 

「フォーマット」を検索するときに、関連する結果が見つかりませんでした理由は、あなたが行っている操作は、「構文解析」と呼ばれていることです。

+1

これは "パスを示す各行の真中の文字列"(質問から直接取ったもの)を取得しません。 –

+0

申し訳ありませんが、非常に便利ですが、どのように文字列を見つけるのですか? –

+0

バージョン(IIRC)に応じてline.Split( "\ t" .ToCharArray())を使用する必要があります。 注意してください。行の15番目の項目にアクセスしたいが、作業中の行に12個の項目しかない場合は、例外が発生します。このようなことを可能な限り避けてください。また、line.split( "\ t")コマンドは空の要素が1つしかない配列を返しますので、空の行は混乱を招きます。 – ZombieSheep

0

正規表現を試してください。あなたはあなたのテキストに特定のパターンを見つけ、あなたが望むものと置き換えることができます。私は今あなたに正確なコードを与えることはできませんが、これを使って式をテストすることができます。 、ファイルを開く行ずつそれを読んで、そしてタブで、それを分割:

http://www.radsoftware.com.au/regexdesigner/

0

ファイルを開き、StreamReader.ReadLineを使用してファイルを行単位で読み取ることができます。次に、String.Splitを使用して、各行を分割して(\ t区切り文字を使用して)2番目の番号を抽出することができます。

項目の数が異なっているとして、あなたはパターンの文字列を検索する必要があるだろう「\ *アイテム。DDJ」。

アイテムを削除するには、ユーザーが[保存]をクリックしたときにファイルの内容をすべてメモリに保存し、新しいファイルを書き込むことができます。

32

別の解決策、今回の正規表現を使用すること:

using System.Text.RegularExpressions; 

... 

Regex parts = new Regex(@"^\d+\t(\d+)\t.+?\t(item\\[^\t]+\.ddj)"); 

StreamReader reader = FileInfo.OpenText("filename.txt"); 
string line; 
while ((line = reader.ReadLine()) != null) { 
    Match match = parts.Match(line); 
    if (match.Success) { 
     int number = int.Parse(match.Group(1).Value); 
     string path = match.Group(2).Value; 

     // At this point, `number` and `path` contain the values we want 
     // for the current line. We can then store those values or print them, 
     // or anything else we like. 
    } 
} 

式は少し複雑だということは、そうここにそれが分解されています

^  Start of string 
\d+  "\d" means "digit" - 0-9. The "+" means "one or more." 
     So this means "one or more digits." 
\t  This matches a tab. 
(\d+) This also matches one or more digits. This time, though, we capture it 
     using brackets. This means we can access it using the Group method. 
\t  Another tab. 
.+?  "." means "anything." So "one or more of anything". In addition, it's lazy. 
     This is to stop it grabbing everything in sight - it'll only grab as much 
     as it needs to for the regex to work. 
\t  Another tab. 

(item\\[^\t]+\.ddj) 
    Here's the meat. This matches: "item\<one or more of anything but a tab>.ddj" 
+2

どちらの回答が受け入れられるかわかりませんが、どちらもうまくいっています。 私はこれをもう1つ好きです。理由と理由を説明したので、これまでにそれを見たことがないからです! –

+0

正規表現が好きなら、次回このようなファイルを処理したいPerlのようなものを使うことをお勧めします。それらを中心に設計されており、好きなように簡単にファイルをフォーマットするために使用することができます。 –

+1

Samir Talwar:私はあなたが正規表現を教えるようになるはずです。あなたがすべてを説明したやり方は華麗でした。とても詳細な先生はいませんでした。 +1 –

1

それはすでに述べているように、私は非常だろうこの種の仕事を行うには、正規表現(System.Text内)を使用することをお勧めします。

RegexBuddyのような実用的なツールと組み合わせると、複雑なテキストレコードの解析状況を処理するだけでなく、結果をすばやく得ることができます。このツールは本当に簡単です。

希望に役立ちます。

0

このような状況で本当に便利な方法の1つは、old-schoolに行き、schema.iniファイルと共にJet OLEDBプロバイダを使用して、ADO.Netを使用して大きなタブ区切りファイルを読み取ることです。明らかに、このメソッドは実際にインポートするファイルの形式を知っている場合にのみ便利です。

public void ImportCsvFile(string filename) 
{ 
    FileInfo file = new FileInfo(filename); 

    using (OleDbConnection con = 
      new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" + 
      file.DirectoryName + "\"; 
      Extended Properties='text;HDR=Yes;FMT=TabDelimited';")) 
    { 
     using (OleDbCommand cmd = new OleDbCommand(string.Format 
            ("SELECT * FROM [{0}]", file.Name), con)) 
     { 
      con.Open(); 

      // Using a DataReader to process the data 
      using (OleDbDataReader reader = cmd.ExecuteReader()) 
      { 
       while (reader.Read()) 
       { 
        // Process the current reader entry... 
       } 
      } 

      // Using a DataTable to process the data 
      using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd)) 
      { 
       DataTable tbl = new DataTable("MyTable"); 
       adp.Fill(tbl); 

       foreach (DataRow row in tbl.Rows) 
       { 
        // Process the current row... 
       } 
      } 
     } 
    } 
} 

データテーブルのような素敵なフォーマットでデータを取得したら、必要なデータを除外することはかなり簡単になります。

+1

接続文字列でJETをACEに、12を4に置き換える必要があります。 32ビットでコンパイルされ、64ビットでコンパイルされていないことを確認してください。 – TamusJRoyce

関連する問題