web-dev-qa-db-ja.com

C#でテキストファイルを解析する方法

テキストの書式設定では、もっと複雑なものを意味していました。

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

テキストファイルには、長さが異なる5000行があります。例:

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

最初の文字(1)と2番目の文字(1/4/5)の間のテキストは空白ではなく、タブです。そのテキストファイルには空白はありません。

私が欲しいもの:

2番目の整数(上記の3行で、2番目の整数は1,4と5)と、各行の中央にあるパスを示す文字列(「item \」で始まり、ファイル拡張子「.ddj」)。

私の問題:

「テキストフォーマットC#」をグーグルで検索すると、テキストファイルを開く方法とC#でテキストファイルを書き込む方法しか得られません。テキストファイル内のテキストを検索する方法がわかりません。また、検索することもできません。最初の整数については、上記の3行のような小さな整数の場合、たとえば「1」が別の場所に存在する可能性があるため、現在の場所を見つけることができません。

私の質問:

何かを削除するプログラムを書くなら最高ですが、必要なものは。

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

何か提案してください、これをすべて手作業でフォーマットすることはできません。

25
Ivan Prodanov

OK、これが私たちの仕事です。ファイルを開き、1行ずつ読み取り、タブで分割します。次に、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.
}
53
Samir Talwar

別の解決策、今回は正規表現を使用します:

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"
34
Samir Talwar

次のようなことができます:

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]);
    }
}

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

5
erikkallen

既に述べたように、この種の仕事をするために(System.Textで)正規表現を使用することを強くお勧めします。

RegexBuddy のような堅実なツールとの組み合わせでは、複雑なテキストレコード解析状況の処理と、すぐに結果。このツールにより、本当に簡単になります。

お役に立てば幸いです。

1
Vin

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

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
Mark Green

正規表現を試してください。テキスト内の特定のパターンを見つけて、必要なパターンに置き換えることができます。現在、正確なコードを提供することはできませんが、これを使用して式をテストできます。

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

0
Marc Vitalis

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

アイテムの数が異なるため、パターン「item\*。ddj」の文字列を検索する必要があります。

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

0
Justin Ethier