Как разобрать данные из файла CSV с одним заголовком на экземпляры разных типов с помощью GetRecord?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Гость
 Как разобрать данные из файла CSV с одним заголовком на экземпляры разных типов с помощью GetRecord?

Сообщение Гость »


Я попробовал использовать подход, описанный в ссылке https://joshclose.github.io/CsvHelper/e ... ord-types/, чтобы реализовать конкретное требование по преобразованию одного файла CSV в экземпляры Различные типы. Однако в примере, приведенном в ссылке, заголовок CSV не записывается, что создало для меня проблему. В моих реализациях ClassMap я не могу использовать Name и AutoMap, поскольку удаление заголовка вызывает проблемы. И вручную указывать индекс в каждой карте классов кажется утомительным.

Поэтому я попытался записать заголовок в CSV-файл и установить для свойства HasHeaderRecord CsvConfiguration, используемого CsvReader, значение true. В то же время я временно сохранил отображение, используя Index Way. Основной код выглядит следующим образом:

public void CSVDeserialize() { вар config = новый CsvConfiguration(CultureInfo.InvariantCulture) { Хасхеадеррекорд = правда, MissingFieldFound = ноль }; используя (var Reader = новый StreamReader(Application.dataPath + "/Data/Events/0.csv")) используя (вар csv = новый CsvReader (читатель, конфигурация)) { csv.Context.RegisterClassMap(); csv.Context.RegisterClassMap(); Диалоги List = новый List(); Список аватаров = новый список (); в то время как (csv.Read()) { переключатель (csv.GetField(0)) { кейс «Диалог»: диалоги.Добавить(csv.GetRecord()); перерыв; кейс «Аватар»: avatars.Add(csv.GetRecord()); перерыв; } } // Печать результатов foreach (аватар FUF_Event_Avatar в аватарах) { Debug.Log($"[Avatar] ID: {avatar.ID}, Delay: {avatar.Delay}, IsAsync: {avatar.IsAsync}, Animation: \"{avatar.Animation.AvatarId + "," + avatar. Animation.Label + "," + avatar.Animation.Emotion + "," + avatar.Animation.IsShutUp + "," + avatar.Animation.IsSkipPreAnim}\", Движение: {avatar.Movement.TimeSpeed ​​+ (avatar.Movement) .UseSpeed ​​? "/s" : "ms") + "=>" + avatar.Movement.Position.x + "," + avatar.Movement.Position.y}"); } foreach (диалог FUF_Event_Dialogue в диалогах) { Debug.Log($"[Dialogue] ID: {dialogue.ID}, Задержка: {dialogue.Delay}, IsAsync: {dialogue.IsAsync}, Содержимое: {dialogue.Content.ID}, Метка: {dialogue.Label} , Ветви: \"{dialogue.Branches?.Select(b => b.Content.ID + "," + b.GotoId).Aggregate((c, n) => c + ";" + n)}\ ""); } } } общественный класс FUF_Event_Dialogue: IFUF_Event { общественный int ID {получить; набор; } общественная задержка с плавающей запятой {get; набор; } общественный bool IsAsync {получить; набор; } общественный FUF_String Content {get; набор; } публичная строка Label {get; набор; } public FUF_Branch[] Ветви => ветки ??= BranchEnumerable?.ToArray(); FUF_Branch[] ветки; IEnumerable BranchEnumerable; общедоступный запечатанный класс ClassMap: ClassMap { общественная Карта Классов () { Карта(м => m.ID).Индекс(1); Карта(м => м.Задержка).Индекс(2); Map(m => m.IsAsync).Index(3).Default(false); Map(m => m.Content).Index(4).Default(null).TypeConverter(); Map(m => m.Label).Index(5).Default(""); Map(m => m.branchEnumerable).Index(6).TypeConverter(); } } } публичный класс FUF_Event_Avatar: IFUF_Event { общественный int ID {получить; набор; } общественная задержка с плавающей запятой {get; набор; } общественный bool IsAsync {получить; набор; } общественная FUF_Animation Анимация {get; набор; } общественное движение FUF_Movement {get; набор; } общедоступный запечатанный класс ClassMap: ClassMap { общественная Карта Классов () { Карта(м => m.ID).Индекс(1); Карта(м => м.Задержка).Индекс(2).По умолчанию(0); Map(m => m.IsAsync).Index(3).Default(false); Map(m => m.Animation).Index(4).TypeConverter(); Карта(м => m.Movement).Index(5).TypeConverter(); } } } После этого я заметил, что первая строка после заголовка игнорируется и не анализируется успешно. Вот мой CSV и журнал вывода:

CSV:

Тип,ID,Задержка,IsAsync,Property_4,Property_5,Property_6 Аватар,0,0,ЛОЖЬ,"0,Джек,Стой,Ложь,Истина","100мс=>256,128" Аватар,1,0,ЛОЖЬ,"0,Мэри,Стой,Ложь,Истина","20/с=>-256,128" Диалог, 2,0, ЛОЖЬ, 1001, Джек Диалог,3,0,ЛОЖЬ,1002,Мэри,"9001,1005;9002,1006" Диалог, 4,0, ЛОЖЬ, 1003, Джек Диалог,5,0,ЛОЖЬ,1004,Джек,"256128;257129" Журнал:

Идентификатор [Аватара]: 1, Задержка: 0, IsAsync: False, Анимация: «0,Mary,Stand,False,True», Движение: 20/с=>-256,128 Идентификатор [Диалога]: 2, Задержка: 0, IsAsync: False, Содержимое: 1001, Метка: Jack, Ветви: «» Идентификатор [Диалога]: 3, Задержка: 0, IsAsync: False, Содержимое: 1002, Метка: Мэри, Ветви: «9001,1005;9002,1006» Идентификатор [Диалога]: 4, Задержка: 0, IsAsync: False, Содержимое: 1003, Метка: Jack, Ветви: «» Идентификатор [Диалога]: 5, Задержка: 0, IsAsync: False, Содержимое: 1004, Метка: Jack, Ветви: «256,128;257,129» Почему это происходит? (Я могу подтвердить, что без указания заголовка и установки HasHeaderRecord в значение false все анализируется успешно.)

Далее, если я изменю свойства в ClassMap, которые имеют те же имена, что и заголовок в CSV, чтобы использовать синтаксический анализ на основе имени по умолчанию или использовать AutoMap, я столкнусь с проблемой, когда все эти свойства анализируются как значения по умолчанию, например 0 или ложь. Вот код, который я изменил, и соответствующий журнал:

общедоступный запечатанный класс ClassMap : ClassMap { общественная Карта Классов () { Карта(м => m.ID); Карта(м => м.Задержка); Карта(м => m.IsAsync).Default(false); Map(m => m.Content).Index(4).Default(null).TypeConverter(); Map(m => m.Label).Index(5).Default(""); Map(m => m.branchEnumerable).Index(6).TypeConverter(); // Или AutoMap, вызывает ту же проблему /*AutoMap(new CsvConfiguration(CultureInfo.InvariantCulture) { Хасхеадеррекорд = правда, MissingFieldFound = ноль });*/ } } Журнал:

Идентификатор [Аватара]: 0, Задержка: 0, IsAsync: False, Анимация: «0,Mary,Stand,False,True», Движение: 20/с=>-256,128 Идентификатор [Диалога]: 0, Задержка: 0, IsAsync: False, Содержимое: 1001, Метка: Jack, Ветви: «» Идентификатор [Диалога]: 0, Задержка: 0, IsAsync: False, Содержимое: 1002, Метка: Мэри, Ветви: «9001,1005;9002,1006» Идентификатор [Диалога]: 0, Задержка: 0, IsAsync: False, Содержимое: 1003, Метка: Jack, Ветви: «» Идентификатор [Диалога]: 0, Задержка: 0, IsAsync: False, Содержимое: 1004, Метка: Jack, Ветви: «256,128;257,129» Как видите, в этом сценарии использование AutoMap или синтаксического анализа на основе имени для поля «ID» не будет работать правильно, и в результате вы получите только 0.

Если вы измените ClassMap для типа первой строки, которая была проигнорирована после заголовка, могут возникнуть еще более серьезные проблемы:

общедоступный запечатанный класс ClassMap : ClassMap { общественная Карта Классов () { Карта(м => m.ID); Карта(м => м.Задержка).По умолчанию(0); Карта(м => m.IsAsync).Default(false); Map(m => m.Animation).Index(4).TypeConverter(); Map(m => m.Movement).Index(5).TypeConverter(); // Или AutoMap, вызывает ту же проблему /*AutoMap(new CsvConfiguration(CultureInfo.InvariantCulture) { Хасхеадеррекорд = правда, MissingFieldFound = ноль });*/ } } EROOR:

HeaderValidationException: заголовок с именем «ID»[0] не найден. Заголовок с именем «Delay»[0] не найден. Заголовок с именем IsAsync[0] не найден. Заголовки: «Аватар», «0», «0», «ЛОЖЬ», «0, Джек, Стенд, Ложь, Истина», «100 мс => 256 128». Заголовки: «Аватар», «0», «0», «ЛОЖЬ», «0, Джек, Стенд, Ложь, Истина», «100 мс => 256 128». Заголовки: «Аватар», «0», «0», «ЛОЖЬ», «0, Джек, Стенд, Ложь, Истина», «100 мс => 256 128». Заголовки: «Аватар», «0», «0», «ЛОЖЬ», «0, Джек, Стенд, Ложь, Истина», «100 мс => 256 128». Заголовки: «Аватар», «0», «0», «ЛОЖЬ», «0, Джек, Стенд, Ложь, Истина», «100 мс => 256 128». Заголовки: «Аватар», «0», «0», «ЛОЖЬ», «0, Джек, Стенд, Ложь, Истина», «100 мс => 256 128». Если вы ожидаете, что некоторые заголовки будут отсутствовать, и хотите игнорировать эту проверку, установите для конфигурации HeaderValidated значение null. Вы также можете изменить функцию, чтобы сделать что-то еще, например, зарегистрировать проблему. Состояние IReader: Коломнкаунт: 0 ТекущийИндекс: 0 ЗаголовокЗапись: ["Аватар","0","0","FALSE","0,Джек,Стенд,False,True","100ms=>256,128"] Состояние IParser: БайтКаунт: 0 Число символов: 117 Ряд: 2 РауРоу: 2 Количество: 6 Сырая запись: Аватар,0,0,ЛОЖЬ,"0,Джек,Стой,Ложь,Истина","100мс=>256,128" CsvHelper.Configuration.ConfigurationFunctions.HeaderValidated (CsvHelper.HeaderValidatedArgs args) (at :0) CsvHelper.CsvReader.ValidateHeader (тип System.Type) (в :0) CsvHelper.CsvReader.ValidateHeader[T] () (в :0) CsvHelper.CsvReader.GetRecord[T] () (в :0) Из журнала ошибок вы можете видеть, что 'Avatar', '0', '0', 'FALSE', '0,Jack,Stand,False,True', '100ms=>256,128'< /code> — строка, которая ранее упоминалась как игнорируемая, на самом деле рассматривается как заголовок.

Есть ли способ решить эти проблемы, не удаляя заголовок? Если возможно, я бы все же хотел включить заголовок, чтобы сохранить код и CSV в чистоте.
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»