Разбор файла .dat в C # и отправка его в DTO - PullRequest
0 голосов
/ 07 мая 2018

Прежде всего, формат этого файла .dat выглядит примерно так: (Пробелы между символами являются символами табуляции, пробелов нет).

    VNUM    1   70
    NAME    zts3e
    INDEX   0   0   0   0   1   0
    TYPE    0   1
    FLAG    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    DATA    1   20  28  20  4   70  0   0   0   0   0   0   0   0   0   0   0   0   0   0
    BUFF    -1  80  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    LINEDESC    1
zts4e
    END
#========================================================
    VNUM    2   400
    NAME    zts5e
    INDEX   0   0   0   0   2   0
    TYPE    0   1
    FLAG    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    DATA    4   29  43  32  4   70  0   0   0   0   0   0   0   0   0   0   0   0   0   0
    BUFF    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    LINEDESC    1
zts6e
    END
#========================================================
    VNUM    3   910
    NAME    zts7e
    INDEX   0   0   0   0   3   2
    TYPE    0   1
    FLAG    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    DATA    7   39  57  44  4   70  0   0   0   0   0   0   0   0   0   0   0   0   0   0
    BUFF    0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    LINEDESC    1
zts8e
    END
#========================================================

Когда я гуглю "Форматирование текста C #" - все, что я получаю, это как открыть текстовый файл и как написать текстовый файл в C #. Я не знаю, как искать текст внутри текстового файла. И вещи, которые я нашел, не такие продвинутые.

Так, как я могу построить парсер для этого? Добавить это в мой пользовательский DTO нет ничего сложного, но разобрать весь этот текст (потому что мне нужно преобразовать эти числа в байты, bools, shorts, int, long и некоторые другие пользовательские типы, которые я сделал.

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

Код на самом деле работает, но мне не нравится:

        internal void ImportItems()
        {
            string fileId = $"{_folder}\\Item.dat";
            string fileLang = $"{_folder}\\_code_{ConfigurationManager.AppSettings["Language"]}_Item.txt";
            Dictionary<string, string> dictionaryName = new Dictionary<string, string>();
            string line;
            List<ItemDTO> items = new List<ItemDTO>();

            using (StreamReader npcIdStream = new StreamReader(fileId, Encoding.GetEncoding(1252)))
            {
                ItemDTO item = new ItemDTO();
                bool itemAreaBegin = false;
                int itemCounter = 0;

                while ((line = npcIdStream.ReadLine()) != null)
                {
                    string[] currentLine = line.Split('\t');

                    if (currentLine.Length > 3 && currentLine[1] == "VNUM")
                    {
                        itemAreaBegin = true;
                        item.VNum = short.Parse(currentLine[2]);
                        item.Price = long.Parse(currentLine[3]);
                    }
                    else if (currentLine.Length > 1 && currentLine[1] == "END")
                    {
                        if (!itemAreaBegin)
                        {
                            continue;
                        }
                        if (DAOFactory.ItemDAO.FirstOrDefault(s => s.VNum.Equals(item.VNum)) == null)
                        {
                            items.Add(item);
                            itemCounter++;
                        }
                        item = new ItemDTO();
                        itemAreaBegin = false;
                    }
                    else if (currentLine.Length > 2 && currentLine[1] == "NAME")
                    {
                        item.Name = dictionaryName.TryGetValue(currentLine[2], out string name) ? name : string.Empty;
                    }
                    else if (currentLine.Length > 7 && currentLine[1] == "INDEX")
                    {
                        switch (Convert.ToByte(currentLine[2]))
                        {
                            case 4:
                                item.Type = InventoryType.Equipment;
                                break;

                            case 8:
                                item.Type = InventoryType.Equipment;
                                break;

                            case 9:
                                item.Type = InventoryType.Main;
                                break;

                            case 10:
                                item.Type = InventoryType.Etc;
                                break;

                            default:
                                item.Type = (InventoryType)Enum.Parse(typeof(InventoryType), currentLine[2]);
                                break;
                        }
                        item.ItemType = currentLine[3] != "-1" ? (ItemType)Enum.Parse(typeof(ItemType), $"{(short)item.Type}{currentLine[3]}") : ItemType.Weapon;
                        item.ItemSubType = Convert.ToByte(currentLine[4]);
                        item.EquipmentSlot = (EquipmentType)Enum.Parse(typeof(EquipmentType), currentLine[5] != "-1" ? currentLine[5] : "0");

                        // item.DesignId = Convert.ToInt16(currentLine[6]);
                        switch (item.VNum)
                        {
                        // lots of cases
                            case 9115:
                                item.Morph = 3679;
                                item.Speed = 21;
                                item.WaitDelay = 3000;
                                break;

                            default:
                                if (item.EquipmentSlot.Equals(EquipmentType.Amulet))
                                {
                                    switch (item.VNum)

                                    // lots of cases
                                        case 4503:
                                            item.EffectValue = 4544;

                                        default:
                                            item.EffectValue = Convert.ToInt16(currentLine[7]);
                                            break;
                                    }
                                }
                                else
                                {
                                    item.Morph = Convert.ToInt16(currentLine[7]);
                                }
                                break;
                        }
                    }
                    else if (currentLine.Length > 3 && currentLine[1] == "TYPE")
                    {
                        // currentLine[2] 0-range 2-range 3-magic
                        item.Class = item.EquipmentSlot == EquipmentType.Fairy ? (byte)15 : Convert.ToByte(currentLine[3]);
                    }
                    else if (currentLine.Length > 3 && currentLine[1] == "FLAG")
                    {
                        item.IsSoldable = currentLine[5] == "0";
                        item.IsDroppable = currentLine[6] == "0";
                        item.IsTradable = currentLine[7] == "0";
                        item.IsMinilandActionable = currentLine[8] == "1";
                        item.IsWarehouse = currentLine[9] == "1";
                        item.Flag9 = currentLine[10] == "1";
                        item.Flag1 = currentLine[11] == "1";
                        item.Flag2 = currentLine[12] == "1";
                        item.Flag3 = currentLine[13] == "1";
                        item.Flag4 = currentLine[14] == "1";
                        item.Flag5 = currentLine[15] == "1";
                        item.IsColored = currentLine[16] == "1";
                        item.Sex = currentLine[18] == "1" ? (byte)1 : currentLine[17] == "1" ? (byte)2 : (byte)0;
                        //not used item.Flag6 = currentLine[19] == "1";
                        item.Flag6 = currentLine[20] == "1";
                        if (currentLine[21] == "1")
                        {
                            item.ReputPrice = item.Price;
                        }
                        item.IsHeroic = currentLine[22] == "1";
                        item.Flag7 = currentLine[23] == "1";
                        item.Flag8 = currentLine[24] == "1";

                    }
                    else if (currentLine.Length > 1 && currentLine[1] == "DATA")
                    {
                        switch (item.ItemType)
                        {
                            case ItemType.Weapon:
                                item.LevelMinimum = Convert.ToByte(currentLine[2]);
                                item.DamageMinimum = Convert.ToInt16(currentLine[3]);
                                item.DamageMaximum = Convert.ToInt16(currentLine[4]);
                                item.HitRate = Convert.ToInt16(currentLine[5]);
                                item.CriticalLuckRate = Convert.ToByte(currentLine[6]);
                                item.CriticalRate = Convert.ToInt16(currentLine[7]);
                                item.BasicUpgrade = Convert.ToByte(currentLine[10]);
                                item.MaximumAmmo = 100;
                                break;

                            case ItemType.Armor:
                                item.LevelMinimum = Convert.ToByte(currentLine[2]);
                                item.CloseDefence = Convert.ToInt16(currentLine[3]);
                                item.DistanceDefence = Convert.ToInt16(currentLine[4]);
                                item.MagicDefence = Convert.ToInt16(currentLine[5]);
                                item.DefenceDodge = Convert.ToInt16(currentLine[6]);
                                item.DistanceDefenceDodge = Convert.ToInt16(currentLine[6]);
                                item.BasicUpgrade = Convert.ToByte(currentLine[10]);
                                break;

                            case ItemType.Box:
                                switch (item.VNum)
                                {
                                    // lots of cases

                                    case 287:
                                        item.Effect = 69;
                                        item.EffectValue = 1;
                                        break;

                                    default:
                                        item.Effect = Convert.ToInt16(currentLine[2]);
                                        item.EffectValue = Convert.ToInt32(currentLine[3]);
                                        item.LevelMinimum = Convert.ToByte(currentLine[4]);
                                        break;
                                }
                                break;

                            case ItemType.Fashion:
                                item.LevelMinimum = Convert.ToByte(currentLine[2]);
                                item.CloseDefence = Convert.ToInt16(currentLine[3]);
                                item.DistanceDefence = Convert.ToInt16(currentLine[4]);
                                item.MagicDefence = Convert.ToInt16(currentLine[5]);
                                item.DefenceDodge = Convert.ToInt16(currentLine[6]);
                                if (item.EquipmentSlot.Equals(EquipmentType.CostumeHat) || item.EquipmentSlot.Equals(EquipmentType.CostumeSuit))
                                {
                                    item.ItemValidTime = Convert.ToInt32(currentLine[13]) * 3600;
                                }
                                break;

                            case ItemType.Food:
                                item.Hp = Convert.ToInt16(currentLine[2]);
                                item.Mp = Convert.ToInt16(currentLine[4]);
                                break;

                            case ItemType.Jewelery:
                                switch (item.EquipmentSlot)
                                {
                                    case EquipmentType.Amulet:
                                        item.LevelMinimum = Convert.ToByte(currentLine[2]);
                                        break;
                                    case EquipmentType.Fairy:
                                        item.Element = Convert.ToByte(currentLine[2]);
                                        item.ElementRate = Convert.ToInt16(currentLine[3]);
                                        break;
                                    default:
                                        item.LevelMinimum = Convert.ToByte(currentLine[2]);
                                        item.MaxCellonLvl = Convert.ToByte(currentLine[3]);
                                        item.MaxCellon = Convert.ToByte(currentLine[4]);
                                        break;
                                }
                                break;

                            case ItemType.Event:
                                switch (item.VNum)
                                {
                                    // lots of cases
                                    default:
                                        item.EffectValue = Convert.ToInt16(currentLine[7]);
                                        break;
                                }
                                break;

                            case ItemType.Special:
                                switch (item.VNum)
                                {
                                    // lots of cases
                                    default:
                                        if (item.VNum > 5891 && item.VNum < 5900 || item.VNum > 9100 && item.VNum < 9109)
                                        {
                                            item.Effect = 69; // imagined number as for I = √(-1), complex z = a + bi
                                        }
                                        else
                                        {
                                            item.Effect = Convert.ToInt16(currentLine[2]);
                                        }
                                        break;
                                }
                                switch (item.Effect)
                                {
                                    case 150:
                                    case 151:
                                        if (Convert.ToInt32(currentLine[4]) == 1)
                                        {
                                            item.EffectValue = 30000;
                                        }
                                        else if (Convert.ToInt32(currentLine[4]) == 2)
                                        {
                                            item.EffectValue = 70000;
                                        }
                                        else if (Convert.ToInt32(currentLine[4]) == 3)
                                        {
                                            item.EffectValue = 180000;
                                        }
                                        else
                                        {
                                            item.EffectValue = Convert.ToInt32(currentLine[4]);
                                        }
                                        break;

                                    case 204:
                                        item.EffectValue = 10000;
                                        break;

                                    case 305:
                                        item.EffectValue = Convert.ToInt32(currentLine[5]);
                                        item.Morph = Convert.ToInt16(currentLine[4]);
                                        break;

                                    default:
                                        item.EffectValue = item.EffectValue == 0 ? Convert.ToInt32(currentLine[4]) : item.EffectValue;
                                        break;
                                }
                                item.WaitDelay = 5000;
                                break;

                            case ItemType.Magical:
                                if (item.VNum > 2059 && item.VNum < 2070)
                                {
                                    item.Effect = 10;
                                }
                                else
                                {
                                    item.Effect = Convert.ToInt16(currentLine[2]);
                                }
                                item.EffectValue = Convert.ToInt32(currentLine[4]);
                                break;

                            case ItemType.Specialist:

                                // item.isSpecialist = Convert.ToByte(currentLine[2]); item.Unknown = Convert.ToInt16(currentLine[3]);
                                item.ElementRate = Convert.ToInt16(currentLine[4]);
                                item.Speed = Convert.ToByte(currentLine[5]);
                                item.SpType = Convert.ToByte(currentLine[13]);

                                // item.Morph = Convert.ToInt16(currentLine[14]) + 1;
                                item.FireResistance = Convert.ToByte(currentLine[15]);
                                item.WaterResistance = Convert.ToByte(currentLine[16]);
                                item.LightResistance = Convert.ToByte(currentLine[17]);
                                item.DarkResistance = Convert.ToByte(currentLine[18]);

                                // item.PartnerClass = Convert.ToInt16(currentLine[19]);
                                item.LevelJobMinimum = Convert.ToByte(currentLine[20]);
                                item.ReputationMinimum = Convert.ToByte(currentLine[21]);

                                Dictionary<int, int> elementdic = new Dictionary<int, int> { { 0, 0 } };
                                if (item.FireResistance != 0)
                                {
                                    elementdic.Add(1, item.FireResistance);
                                }
                                if (item.WaterResistance != 0)
                                {
                                    elementdic.Add(2, item.WaterResistance);
                                }
                                if (item.LightResistance != 0)
                                {
                                    elementdic.Add(3, item.LightResistance);
                                }
                                if (item.DarkResistance != 0)
                                {
                                    elementdic.Add(4, item.DarkResistance);
                                }

                                item.Element = (byte)elementdic.OrderByDescending(s => s.Value).First().Key;
                                if (elementdic.Count > 1 && elementdic.OrderByDescending(s => s.Value).First().Value == elementdic.OrderByDescending(s => s.Value).ElementAt(1).Value)
                                {
                                    item.SecondaryElement = (byte)elementdic.OrderByDescending(s => s.Value).ElementAt(1).Key;
                                }

                                // needs to be hardcoded
                                switch (item.VNum)
                                {
                                    case 901:
                                        item.Element = 1;
                                        break;

                                    case 903:
                                        item.Element = 2;
                                        break;

                                    case 906:
                                        item.Element = 3;
                                        break;

                                    case 909:
                                        item.Element = 3;
                                        break;
                                }
                                break;

                            case ItemType.Shell:

                                // item.ShellMinimumLevel = Convert.ToInt16(linesave[3]);
                                // item.ShellMaximumLevel = Convert.ToInt16(linesave[4]);
                                // item.ShellType = Convert.ToByte(linesave[5]); // 3 shells of each type
                                break;

                            case ItemType.Main:
                                item.Effect = Convert.ToInt16(currentLine[2]);
                                item.EffectValue = Convert.ToInt32(currentLine[4]);
                                break;

                            case ItemType.Upgrade:
                                item.Effect = Convert.ToInt16(currentLine[2]);
                                switch (item.VNum)
                                {
                                    // UpgradeItems (needed to be hardcoded)
                                    case 1218:
                                        item.EffectValue = 26;
                                        break;

                                    case 1363:
                                        item.EffectValue = 27;
                                        break;

                                    case 1364:
                                        item.EffectValue = 28;
                                        break;

                                    case 5107:
                                        item.EffectValue = 47;
                                        break;

                                    case 5207:
                                        item.EffectValue = 50;
                                        break;

                                    case 5369:
                                        item.EffectValue = 61;
                                        break;

                                    case 5519:
                                        item.EffectValue = 60;
                                        break;

                                    default:
                                        item.EffectValue = Convert.ToInt32(currentLine[4]);
                                        break;
                                }
                                break;

                            case ItemType.Production:
                                item.Effect = Convert.ToInt16(currentLine[2]);
                                item.EffectValue = Convert.ToInt32(currentLine[4]);
                                break;

                            case ItemType.Map:
                                item.Effect = Convert.ToInt16(currentLine[2]);
                                item.EffectValue = Convert.ToInt32(currentLine[4]);
                                break;

                            case ItemType.Potion:
                                item.Hp = Convert.ToInt16(currentLine[2]);
                                item.Mp = Convert.ToInt16(currentLine[4]);
                                break;

                            case ItemType.Snack:
                                item.Hp = Convert.ToInt16(currentLine[2]);
                                item.Mp = Convert.ToInt16(currentLine[4]);
                                break;

                            case ItemType.Teacher:
                                item.Effect = Convert.ToInt16(currentLine[2]);
                                item.EffectValue = Convert.ToInt32(currentLine[4]);

                                // item.PetLoyality = Convert.ToInt16(linesave[4]); item.PetFood = Convert.ToInt16(linesave[7]);
                                break;

                            case ItemType.Part:

                                // nothing to parse
                                break;

                            case ItemType.Sell:

                                // nothing to parse
                                break;

                            case ItemType.Quest2:

                                // nothing to parse
                                break;

                            case ItemType.Quest1:

                                // nothing to parse
                                break;

                            case ItemType.Ammo:

                                // nothing to parse
                                break;
                        }

                        if (item.Type == InventoryType.Miniland)
                        {
                            item.MinilandObjectPoint = int.Parse(currentLine[2]);
                            item.EffectValue = short.Parse(currentLine[8]);
                            item.Width = Convert.ToByte(currentLine[9]);
                            item.Height = Convert.ToByte(currentLine[10]);
                        }

                        if (item.EquipmentSlot != EquipmentType.Boots && item.EquipmentSlot != EquipmentType.Gloves || item.Type != 0)
                        {
                            continue;
                        }
                        item.FireResistance = Convert.ToByte(currentLine[7]);
                        item.WaterResistance = Convert.ToByte(currentLine[8]);
                        item.LightResistance = Convert.ToByte(currentLine[9]);
                        item.DarkResistance = Convert.ToByte(currentLine[11]);
                    }
                    else if (currentLine.Length > 1 && currentLine[1] == "BUFF")
                    {
                        for (int i = 0; i < 5; i++)
                        {
                            byte type = (byte)int.Parse(currentLine[2 + 5 * i]);
                            if (type == 0 || type == 255)
                            {
                                continue;
                            }
                            int first = int.Parse(currentLine[3 + 5 * i]);
                            BCardDTO itemCard = new BCardDTO
                            {
                                ItemVNum = item.VNum,
                                Type = type,
                                SubType = (byte)((int.Parse(currentLine[5 + 5 * i]) + 1) * 10 + 1),
                                IsLevelScaled = Convert.ToBoolean(first % 4),
                                IsLevelDivided = (first % 4) == 2,
                                FirstData = (short)(first / 4),
                                SecondData = (short)(int.Parse(currentLine[4 + 5 * i]) / 4),
                                ThirdData = (short)(int.Parse(currentLine[6 + 5 * i]) / 4),
                            };
                            itemCards.Add(itemCard);
                        }
                    }
                }
            }
}

PD: Я хочу добавить, что я не могу сделать это вручную, потому что этот .dat имеет 52306 строк, и это невозможно сделать

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Окончательное решение:

 public string[] getBlocks(string path)
        {
            string[] blocks = File.ReadAllText(path).Split(new string[] { "#========================================================" }, StringSplitOptions.None);
            return blocks;
        }
        public Dictionary<string, string[]> getValues(string block)
        {
            Dictionary<string, string[]> dictionary = new Dictionary<string, string[]>();
            var foos = new List<string>(Regex.Split(block, "\t"));
            foos.RemoveAt(0);
            string[] values = Regex.Split(String.Join("\t", foos.ToArray()), "\r");
            values = values.Take(values.Count() - 1).ToArray();
            foreach (string value in values)
            {
                string[] fieldName = Regex.Split(value, "\t");
                fieldName = fieldName.Where(x => !string.IsNullOrEmpty(x)).ToArray();
                var newList = new List<string>(fieldName);
                if(newList.Count >= 1)
                {
                    newList.RemoveAt(0);
                    string[] valueList = newList.ToArray();
                    dictionary.Add(fieldName[0], valueList);
                }
                else
                {
                }

            }
            return dictionary;
}
0 голосов
/ 07 мая 2018

Вы можете сделать что-то подобное. Разобрать все строки и добавить его в свой объект. Например, создайте объект DTO :

class DTO
{
string Name{get;set;}
List<short> Index{get;set;}
//etc
}

и синтаксический анализ строк до объектов DTO .

var lines = System.IO.File.ReadAllLines("somedoc.txt");
List<DTO> dtos = new List<DTO>();
foreach(var line in lines)
{

   Console.WriteLine(line);
   //split it to words
   var lineFields = line.Split(null);

   //first will be the field's value
   var field = lineFields.FirstOrDefault(f => !string.IsNullOrEmpty(f));

   //others will be the field's values
   var values = line.Where(val => !string.IsNullOrEmpty(val) && !string.Equals(field, val)).Select(elem => short.Parse(elem)).ToList();
   DTO dtoObj = new DTO();
   if(field.Equals("NAME"))dtoObj.Name = field;
   if(field.Equals("INDEX")) dtoObj.Index.AddRange(values);
   if(line.Contains("END")
   {
      //end it, and parse it to next object.
   }
}

Это не полный пример, но вы можете начать работу таким образом.

...