Подтвердить что ты не робот

Как анализировать текстовый файл с помощью С#

При форматировании текста я имел в виду нечто более сложное.

Сначала я начал вручную добавлять 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) и вторым символом (1/4/5) не является пробелом, это вкладка. В этом текстовом файле нет пробелов.

Что я хочу:

Я хочу получить второе целое число (в трех строках, которые я написал выше, во вторых целых числах 1,4 и 5), а строка в середине каждой строки указывает путь (начинается с "item \" и заканчивается расширением файла .ddj ").

Моя проблема:

Когда я google "форматирование текста С#" - все, что я получаю, это как открыть текстовый файл и как написать текстовый файл на С#. Я не знаю, как искать текст внутри текстового файла. Также я могу 't искать первое целое число, потому что в случае его маленького целого числа, как в трех строках, которые я разместил выше, я не смогу найти место для корневого каталога, потому что, например, "1" может существовать в другом месте.

Мой вопрос:

Было бы лучше, если я напишу программу, которая удалит что-нибудь, но что мне нужно.

Другим способом в моем уме является прямой поиск внутри этого файла, но, как я уже упоминал выше, я мог бы получить неправильное расположение второго целого числа, если его слишком мало.

Пожалуйста, предложите что-нибудь, я не могу отформатировать все это вручную.

4b9b3361

Ответ 1

ОК, вот что мы делаем: откройте файл, прочитайте его по строкам и разделите его на вкладки. Затем мы возьмем второе целое число и процедим через остальное, чтобы найти путь.

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 your integer.
    // Now let 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.
}

Ответ 2

Другое решение, на этот раз использующее регулярные выражения:

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 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 the meat. This matches: "item\<one or more of anything but a tab>.ddj"

Ответ 3

Вы можете сделать что-то вроде:

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

Причина, по которой вы не нашли соответствующего результата при поиске форматирования, заключается в том, что выполняемая вами операция называется "разбор".

Ответ 4

Как уже упоминалось, я настоятельно рекомендую использовать регулярное выражение (в System.Text), чтобы выполнить эту работу.

В комбинации с твердым инструментом, например RegexBuddy, вы смотрите на обработку любых сложных ситуаций синтаксического анализа текстовых записей, а также быстро получать результаты. Инструмент делает его очень легким.

Надеюсь, что это поможет.

Ответ 5

Попробуйте регулярные выражения. Вы можете найти определенный образец в своем тексте и заменить его тем, что хотите. Я не могу дать вам точный код прямо сейчас, но вы можете проверить свои выражения, используя это.

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

Ответ 6

Вы можете открыть файл и использовать StreamReader.ReadLine для чтения файла в строке. Затем вы можете использовать String.Split, чтобы разбить каждую строку на части (используйте разделитель \t), чтобы извлечь второй номер.

Поскольку количество элементов различно, вам нужно будет искать строку для шаблона 'item\*.ddj'.

Чтобы удалить элемент, который вы могли бы (например) сохранить все содержимое файла в памяти и выписать новый файл, когда пользователь нажимает "Сохранить".

Ответ 7

Один из способов, который я нашел очень полезным в таких ситуациях, - это пойти в старую школу и использовать поставщика Jet OLEDB вместе с файлом schema.ini для чтения больших файлов с разделителями-табуляторами с использованием 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...
                }
            }
        }
    }
} 

Как только у вас есть данные в хорошем формате, например, в формате datatable, фильтрация данных, которые вам нужны, становится довольно тривиальной.