Парсинг файла игры


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

Вот некоторые примеры данных, которые я пытаюсь разобрать. Это информация только для одного игрока:

[0] (com.riotgames.platform.gameclient.domain::PlayerParticipantStatsSummary)#8
            _profileIconId = 4
            elo = 0
            eloChange = 0
            gameId = 82736631
            gameItems = (null)
            inChat = false
            leaver = false
            leaves = 1
            level = 5
            losses = 2
            profileIconId = 4
            skinName = "Vladimir"
            statistics = (mx.collections::ArrayCollection)#9
              filterFunction = (null)
              length = 26
              list = (mx.collections::ArrayList)#10
                length = 26
                source = (Array)#11
                  [0] (com.riotgames.platform.gameclient.domain::RawStatDTO)#12
                    displayName = (null)
                    statTypeName = "PHYSICAL_DAMAGE_TAKEN"
                    value = 11156
                  [1] (com.riotgames.platform.gameclient.domain::RawStatDTO)#13
                    displayName = (null)
                    statTypeName = "TOTAL_DAMAGE_TAKEN"
                    value = 20653
                  [2] (com.riotgames.platform.gameclient.domain::RawStatDTO)#14
                    displayName = (null)
                    statTypeName = "ITEM2"
                    value = 3158
                  [3] (com.riotgames.platform.gameclient.domain::RawStatDTO)#15
                    displayName = (null)
                    statTypeName = "ITEM4"
                    value = 3089
                  [4] (com.riotgames.platform.gameclient.domain::RawStatDTO)#16
                    displayName = (null)
                    statTypeName = "WIN"
                    value = 1
                  [5] (com.riotgames.platform.gameclient.domain::RawStatDTO)#17
                    displayName = (null)
                    statTypeName = "PHYSICAL_DAMAGE_DEALT_PLAYER"
                    value = 18413
                  [6] (com.riotgames.platform.gameclient.domain::RawStatDTO)#18
                    displayName = (null)
                    statTypeName = "TOTAL_HEAL"
                    value = 16877
                  [7] (com.riotgames.platform.gameclient.domain::RawStatDTO)#19
                    displayName = (null)
                    statTypeName = "ITEM0"
                    value = 3083
                  [8] (com.riotgames.platform.gameclient.domain::RawStatDTO)#20
                    displayName = (null)
                    statTypeName = "LARGEST_CRITICAL_STRIKE"
                    value = 173
                  [9] (com.riotgames.platform.gameclient.domain::RawStatDTO)#21
                    displayName = (null)
                    statTypeName = "ITEM3"
                    value = 3116
                  [10] (com.riotgames.platform.gameclient.domain::RawStatDTO)#22
                    displayName = (null)
                    statTypeName = "ITEM1"
                    value = 0
                  [11] (com.riotgames.platform.gameclient.domain::RawStatDTO)#23
                    displayName = (null)
                    statTypeName = "GOLD_EARNED"
                    value = 11123
                  [12] (com.riotgames.platform.gameclient.domain::RawStatDTO)#24
                    displayName = (null)
                    statTypeName = "ASSISTS"
                    value = 8
                  [13] (com.riotgames.platform.gameclient.domain::RawStatDTO)#25
                    displayName = (null)
                    statTypeName = "LARGEST_MULTI_KILL"
                    value = 2
                  [14] (com.riotgames.platform.gameclient.domain::RawStatDTO)#26
                    displayName = (null)
                    statTypeName = "MAGIC_DAMAGE_DEALT_PLAYER"
                    value = 103124
                  [15] (com.riotgames.platform.gameclient.domain::RawStatDTO)#27
                    displayName = (null)
                    statTypeName = "BARRACKS_KILLED"
                    value = 0
                  [16] (com.riotgames.platform.gameclient.domain::RawStatDTO)#28
                    displayName = (null)
                    statTypeName = "LARGEST_KILLING_SPREE"
                    value = 5
                  [17] (com.riotgames.platform.gameclient.domain::RawStatDTO)#29
                    displayName = (null)
                    statTypeName = "ITEM5"
                    value = 0
                  [18] (com.riotgames.platform.gameclient.domain::RawStatDTO)#30
                    displayName = (null)
                    statTypeName = "MINIONS_KILLED"
                    value = 176
                  [19] (com.riotgames.platform.gameclient.domain::RawStatDTO)#31
                    displayName = (null)
                    statTypeName = "CHAMPIONS_KILLED"
                    value = 11
                  [20] (com.riotgames.platform.gameclient.domain::RawStatDTO)#32
                    displayName = (null)
                    statTypeName = "MAGIC_DAMAGE_TAKEN"
                    value = 8581
                  [21] (com.riotgames.platform.gameclient.domain::RawStatDTO)#33
                    displayName = (null)
                    statTypeName = "NEUTRAL_MINIONS_KILLED"
                    value = 12
                  [22] (com.riotgames.platform.gameclient.domain::RawStatDTO)#34
                    displayName = (null)
                    statTypeName = "TOTAL_TIME_SPENT_DEAD"
                    value = 189
                  [23] (com.riotgames.platform.gameclient.domain::RawStatDTO)#35
                    displayName = (null)
                    statTypeName = "TURRETS_KILLED"
                    value = 0
                  [24] (com.riotgames.platform.gameclient.domain::RawStatDTO)#36
                    displayName = (null)
                    statTypeName = "NUM_DEATHS"
                    value = 5
                  [25] (com.riotgames.platform.gameclient.domain::RawStatDTO)#37
                    displayName = (null)
                    statTypeName = "TOTAL_DAMAGE_DEALT"
                    value = 121538
                uid = "B6F2F234-2E37-D979-E896-AA7614FCE9CB"
              sort = (null)
              source = (Array)#11
            summonerName = "WeFearTheSun"
            teamId = 100
            userId = 21672484
            wins = 6

Сейчас есть десять игроков в игре, то десять из фрагмента выше, каждый с увеличением счетчика, [1],[2],[3], и так далее.

Как вы можете видеть внутри этой информации есть и другие цифры, т. е.. другое [0].

Если номера были уникальны, я мог бы просто разобрать [0], затем [1], затем [2]и т. д.

Сейчас я парсинг файлов вот так:

private IEnumerable<Player> GetGamePlayers(string content)
{
    List<Player> Players = new List<Player>();

    var location = content.IndexOf("com.riotgames.platform.gameclient.domain::EndOfGameStats");
    var cutContent = content.Substring(location, 65000);

    var playerOneLocation = cutContent.IndexOf("[0]");
    //var playerOneContent = cutContent.Substring(playerOneLocation, 6231);
    var playerOneContent = cutContent.Substring(playerOneLocation, 6255);
    Players.Add(ParsePlayer(playerOneContent));

    cutContent = cutContent.Substring(playerOneLocation + 6229, cutContent.Length - playerOneLocation - 6229);
    var playerTwoLocation = cutContent.IndexOf("[1]");
    var playerTwoContent = cutContent.Substring(playerTwoLocation, 6255);
    Players.Add(ParsePlayer(playerTwoContent));

    cutContent = cutContent.Substring(playerTwoLocation + 6229, cutContent.Length - playerTwoLocation - 6229);
    var playerThreeLocation = cutContent.IndexOf("[2]");
    var playerThreeContent = cutContent.Substring(playerThreeLocation, 6255);
    Players.Add(ParsePlayer(playerThreeContent));

    cutContent = cutContent.Substring(playerThreeLocation + 6229, cutContent.Length - playerThreeLocation - 6229);
    var playerFourLocation = cutContent.IndexOf("[3]");
    var playerFourContent = cutContent.Substring(playerFourLocation, 6255);
    Players.Add(ParsePlayer(playerFourContent));

    cutContent = cutContent.Substring(playerFourLocation + 6229, cutContent.Length - playerFourLocation - 6229);
    var playerFiveLocation = cutContent.IndexOf("[4]");
    var playerFiveContent = cutContent.Substring(playerFiveLocation, 6255);
    Players.Add(ParsePlayer(playerFiveContent));

    location = cutContent.IndexOf("teamPlayerParticipantStats");
    cutContent = cutContent.Substring(location, 32000);
    var playerSixLocation = cutContent.IndexOf("[0]");
    var playerSixContent = cutContent.Substring(playerSixLocation, 6255);
    Players.Add(ParsePlayer(playerSixContent));

    cutContent = cutContent.Substring(playerSixLocation + 6229, cutContent.Length - playerSixLocation - 6229);
    var playerSevenLocation = cutContent.IndexOf("[1]");
    var playerSevenContent = cutContent.Substring(playerSevenLocation, 6255);
    Players.Add(ParsePlayer(playerSevenContent));

    cutContent = cutContent.Substring(playerSevenLocation + 6229, cutContent.Length - playerSevenLocation - 6229);
    var playerEightLocation = cutContent.IndexOf("[2]");
    var playerEightContent = cutContent.Substring(playerEightLocation, 6255);
    Players.Add(ParsePlayer(playerEightContent));

    cutContent = cutContent.Substring(playerEightLocation + 6229, cutContent.Length - playerEightLocation - 6229);
    var playerNineLocation = cutContent.IndexOf("[3]");
    var playerNineContent = cutContent.Substring(playerNineLocation, 6255);
    Players.Add(ParsePlayer(playerNineContent));

    cutContent = cutContent.Substring(playerNineLocation + 6229, cutContent.Length - playerNineLocation - 6229);
    var playerTenLocation = cutContent.IndexOf("[4]");
    var playerTenContent = cutContent.Substring(playerTenLocation, 6255);
    Players.Add(ParsePlayer(playerTenContent));

    return Players;
}

Я могу сказать код ужасен, и есть много возможностей для совершенствования. Как бы я разделить огромный контент на отдельные блоки для каждого отдельного игрока?

Мне нужно получить строку Содержание:

[0] (com.riotgames.platform.gameclient.domain::PlayerParticipantStatsSummary)#8
to
[1] (com.riotgames.platform.gameclient.domain::PlayerParticipantStatsSummary)#8

then:
[1] (com.riotgames.platform.gameclient.domain::PlayerParticipantStatsSummary)#8
to
[2] (com.riotgames.platform.gameclient.domain::PlayerParticipantStatsSummary)#8


798
9
задан 23 января 2011 в 02:01 Источник Поделиться
Комментарии
1 ответ

Некоторые эмпирические правила, которые должны улучшить ваш код:


  • Если у вас есть переменные с именами, напоминающими Вароне, varTwo, varThreeи т. д. - Не важно, какое количество вы должны, вероятно, использовать массив.

  • Если вы делаете несколько одинаковых действий над последовательность значений, вы должны использовать цикл.

  • Код никогда не должен быть повторен.

Теперь с этим в виду, приступим к работе.

private IEnumerable<Player> GetGamePlayers(string content)
{
List<Player> Players = new List<Player>();

// Get the endgame stats text
string endgameStatsMarker = "com.riotgames.platform.gameclient.domain::EndOfGameStats"
int endgameStatsLocation = content.IndexOf(endgameStatsMarker);
string endgameStats = content.Substring(endgameStatsLocation);

// Split the endgame stats text into an array of player information sections
string[] charBeginMarker = new string[] {"(com.riotgames.platform.gameclient.domain::PlayerParticipantStatsSummary)"}
string[] playerInfoSet = endgameStats.Split(charBeginMarker, SplitStringOptions.None);

// don't assume there's 10; get this from the logfile
int numPlayers = GetMaxPlayers();

// playerDataSet[0] is before any playerInfo begins, so we skip it.
for (int i = 1; i <= numPlayers; i++);
{
Players.Add(ParsePlayer(playerData));
// The string passed to ParsePlayer will be a little different now.
// It will contain a [#] on the end except in the case of the last player.
// This is since we split the text at the beginning of the player field
// and AFTER the [#].
// You will have to ensure your ParsePlayer method will work with this
// new input.
}

return Players;
}

... Ну вот весь код не удален, следуйте нескольким простым правилам. История Билла Аткинсона , наверное, вполне уместны. ;)

Лучше на разборе

Существует одна большая проблема в вашем подходе к файл парсинга я должен поговорить с вами.

Вы не предполагаю , как долго данные раздел будет основан на нынешней журнал формат внешний вид и прописать это в программе. Давайте рассмотрим недостатки этого метода. Скажи мне, что происходит, когда любой из этих вещей произошло:


  1. Разделы данных игроков становятся на один символ больше.

  2. Разделы данных игрок получает еще одну строку информации.

  3. Разделы данных игроков есть еще время познакомиться с ними.

Ответы (не подглядывать): 1. Ваш разбор данных игрока может идти смешно. 2. Ваш разбор, вероятно, взорвется. 3. Ваш разбор обязательно взорвется в ужасный беспорядок.

Если вы были парсинг файла правильно, ваша программа будет как минимум на порядок меньше, скорее всего, вещи в каждом конкретном случае, пока серьезных изменений в лог-файл формата.

Ключ для разбора этого файла признавая, что этот файл является полной удобочитаемое и машиночитаемой разметки вы не эксплуатирую вообще.

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

Вот что вы должны делать: Открыть файл. Определить, где разделы сплит. Определите, как вы определили где разделы сплит. Написать код, который способен распознавать этот раскол, разделение, соответственно, содержание файл.

Таким образом, ключ: понимание как вы понимаете, что вы видите, затем учебные программы, чтобы понять, как хорошо!

Например, рассмотрим эти правила:


  • Начинается раздел информационного характера на определенную строку и заканчивается в момент следующего появления одной и той же строки, так что вы можете просто разделить информационный характер разделов на эту строку.

  • Как только вы достигнете # вы нашли специальное поле. Это может быть простой комментарий, или это может быть идентификатор для каждого уникального объекта, что позволяет повторно использовать объекты из кэша в случае, если два объекта идентичны. Это, вероятно, безопасно игнорировать от # до конца строки, Если вы не найдете ему применение.

  • Переменная может быть найден в начале строки после пробела. Количество пробельных символов является значительным (см. Последний пункт).

  • Если первый символ строки является [ это элемент массива, а не имя переменной.

  • Имя переменной заканчивается на первой космической.

  • Значение переменной на другую сторону =, удалением лишних пробелов на другой стороне.

  • Если значение начинается с целого числа это число. Если он начинается с кавычки это строка.

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

  • Содержимое элемента массива всегда отступом. Увеличение глубины отступа означает, что вы сейчас читаете содержимое массива в строку. Уменьшение глубины отступа означает, что вы закончили читать содержимое этого массива.

Девять правил просто от понимания и описания того, как я понимаю, то, что я вижу. Они должны быть достаточно просто реализовать в парсере в виде методов - вдруг парсер уже может справиться с 90% синтаксиса в лог-файл все! Только несколько вещей не хватает на данный момент, такие как парсинг объявление типа элемента массива или определения типа значения переменной (строка? целое число?).

14
ответ дан 23 января 2011 в 04:01 Источник Поделиться