No Description

ababin 080472818c Добавить 'README.md' 6 months ago
.idea 8975d9515f secont 7 months ago
ConsoleApp17 8975d9515f secont 7 months ago
ConsoleApp17.sln 8975d9515f secont 7 months ago
README.md 080472818c Добавить 'README.md' 6 months ago

README.md

Форматы файлов

CSV (от англ. Comma-Separated Values — значения, разделённые запятыми) — текстовый формат, предназначенный для представления табличных данных. Строка таблицы соответствует строке текста, которая содержит одно или несколько полей, разделенных запятыми.

Спецификация

Каждая строка файла — это одна строка таблицы. Разделителем (англ. delimiter) значений колонок является символ запятой (,). Однако на практике часто используются другие разделители, то есть формат путают с DSVruen и TSV (см. ниже). Значения, содержащие зарезервированные символы (двойная кавычка, запятая, точка с запятой, новая строка) обрамляются двойными кавычками ("). Если в значении встречаются кавычки — они представляются в файле в виде двух кавычек подряд.

Создание csv файла и запуск кода

using System.Globalization;
using CsvHelper;
using CsvHelper.Configuration;

using (var reader = new StreamReader("./test.csv")) {
    using (var csv = new CsvReader(
        reader, CultureInfo.InvariantCulture))
    {
        var records = csv.GetRecords<Foo>();
        foreach (var record in records) {
            Console.WriteLine("{0}, {1}", record.description, record.value);
        }
    }
}

public class Foo
{
    public string description { get; set; }
    public double value { get; set; }
}
description,value
"строка с пробелами",123.15
"строка
с переносом 
строки",456

Запись в CSV

// использую не стандартный формат
var config = new CsvConfiguration(
    CultureInfo.InvariantCulture) { 
        Delimiter = ";", 
        HasHeaderRecord = false };

// создаю тестовые данные
var records = new List<Foo>
{
    new Foo { 
        description ="тест записи\nмногострочного текста",
        value = 12.34 },
    new Foo { 
        description = "просто, текст, с запятыми", 
        value = 0 }
};

using (var writer = new StreamWriter("./test3.csv"))
using (var csv = new CsvWriter(writer, config))
{
    csv.WriteRecords(records);
}

Вывод:

"тест записи
многострочного текста";12.34
просто, текст, с запятыми;0

Различия в культурной среде

В русской культурной среде в качестве разделителя разрядов в числах с плавающей запятой используется запятая. Поэтому вполне может попасться csv файл, в котором в числах разделитель запятая.

"строка с пробелами";123,15
"строка
с переносом 
строки";456

Разделитель полей мы менять умеем, но как быть с форматом чисел?

Нужно задать нужную культурную среду:


var config = new CsvConfiguration(
    new CultureInfo("ru-RU")) { 
        Delimiter = ";", 
        HasHeaderRecord = false };

JSON

JSON (JavaScript Object Notation). Можно перевести как способ записи объектов в JavaScript. Формат оказался настолько удобен, что его стали поддерживать практически все популярные языки программирования.

Как устроен этот формат

Допустим, у нас есть магазин с системой бонусов, которые начисляются по скидочной карте. Когда продавец считывает карту, он должен получить от сервера такие данные:

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

{
  "firstname": "Михаил",
  "lastname": "Максимов",
  "phone": "+79201234567",
  "city": "Москва",
  "age": 37,
  "bonus": 2000,
  "prev": [
    "Кроссовки",
    "Турник",
    "Зимняя куртка"
  ]
}

Newtonsoft.Json

Эта библиотека является стандартом де-факто для работы с JSON в C#.

var person = new Person
{
    name = "Имя",
    age = 18,
    date = "2024-03-07"
};

string json = JsonConvert.SerializeObject(
    person, Formatting.Indented);

Console.WriteLine(json);
{
    "name": "Имя",
    "age":18,
    "date":"2024-03-07"
}

JSON. DataContractJsonSerializer.

[DataContract]
internal class Person
{
    [DataMember]
    public string name;

    [DataMember]
    public int age;

    [DataMember]
    public DateTime date;
}

Сериализация

var PersonList = new List<Person>() {
    new Person {name="Иванов", age=25, date=new DateTime(2021,1,1)},
    new Person {name="Петров", age=35, date=new DateTime(2021,1,2)}
};

// создаем объект сериализатора, указав, что на входе 
// будет МАССИВ объектов Person
var Serializer = new DataContractJsonSerializer(typeof(Person[]));

using (var streamWriter = new StreamWriter("test1.json"))
{
    Serializer.WriteObject(
        streamWriter.BaseStream,
        // Преобразуем список (List) объектов в МАССИВ
        PersonList.ToArray()
    );
}

На выходе получим следующее: [{"age":25,"date":"\/Date(1609448400000+0300)\/","name":"Иванов"},{"age":35,"date":"\/Date(1609534800000+0300)\/","name":"Петров"}]

Десериализация (Преобразование JSON-строки в объект)

[DataContract]
internal class Person
{
    // создаем приватную переменную для хранения даты
    private DateTime privateDate;

    [DataMember]
    public string name { get; set; }

    [DataMember]
    public string age { get; set; }

    // создаем ПРИВАТНОЕ СТРОКОВОЕ свойство и с помощью атрибутов меняем ему имя для сериализатора
    [DataMember(Name = "date")]
    private string StringDate {
        get {
            return privateDate.ToString("yyyy-MM-dd");
        }
        set {
            // 2021-03-21
            // 0123456789
            privateDate = new DateTime(
                Convert.ToInt32(value.Substring(0, 4)),
                Convert.ToInt32(value.Substring(5, 2)),
                Convert.ToInt32(value.Substring(8, 2))
            );
        } 
    }

    // публичное свойство "дата" скрываем от сериализатора
    [IgnoreDataMember]
    public DateTime date { 
        get { return privateDate; }
        set { privateDate = value;  } 
    }
}

Вариант попроще

Можно использовать не только "голый" .NET Framework, но и библиотеки из других компонентов Visual Studio. В пространстве имён System.Web.Script.Serialization есть класс JavaScriptSerializer, который выглядит попроще чем классическая реализация:

// целевые классы нам по прежнему нужны, но уже без всяких аннотаций
internal class MaterialTC
{
    public string Title { get; set; }
    public int Count { get; set; }
}

internal class Notice
{
    public Material[] data;
}

internal class Answer
{
    public Notice notice;
}


// в месте, где нам нужно распарсить JSON создаем сериализатор и разбираем строку
var serializer = new JavaScriptSerializer();
var answer = serializer.Deserialize<Answer>("тут ваша JSON-строка");

// и ВСЁ