RSCG – Csvcsharp
| name | Csvcsharp |
| nuget | https://www.nuget.org/packages/Csvcsharp/ |
| link | https://github.com/nuskey8/Csv-CSharp |
| author | Yusuke Nakada |
Serializer for CSV files
This is how you can use Csvcsharp .
The code that you start with is
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net9.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <PropertyGroup> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="CsvCSharp" Version="1.0.0" /> </ItemGroup> </Project>
The code that you will use is
using Csv;
using SerializerDemo;
var p= new Person() { Name= "Andrei Ignat" , Age=55};
var utf8Csv = CsvSerializer.SerializeToString<Person>([p]);
Console.WriteLine(utf8Csv);
var p1 = CsvSerializer.Serialize<Person>([p]);
var p2 = CsvSerializer.Deserialize<Person>(p1);
Console.WriteLine(p2.First().Name);
Console.WriteLine(p2.First().Age);
using Csv.Annotations;
namespace SerializerDemo;
[CsvObject]
public partial class Person
{
[Column(0)]
public int Age { get; set; }
[Column(1)]
public string Name { get; set; } = string.Empty;
}
The code that is generated is
// <auto-generated />
#nullable enable
#pragma warning disable CS0162 // Unreachable code
#pragma warning disable CS0219 // Variable assigned but never used
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
#pragma warning disable CS8601 // Possible null reference assignment
#pragma warning disable CS8602 // Possible null return
#pragma warning disable CS8604 // Possible null reference argument for parameter
#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method
using System;
using Csv;
using Csv.Annotations;
using Csv.Internal;
namespace SerializerDemo
{
partial class Person : global::Csv.ICsvSerializerRegister
{
static void RegisterCsvSerializer()
{
global::Csv.CsvSerializer.Register(GeneratedCsvSerializer.Instance);
}
class GeneratedCsvSerializer : ICsvSerializer<global::SerializerDemo.Person>
{
public static readonly GeneratedCsvSerializer Instance = new();
static readonly byte[] AgeUtf8Key = { 65, 103, 101 }; // Age
static readonly byte[] NameUtf8Key = { 78, 97, 109, 101 }; // Name
<pre><code> public void Serialize(ref global::Csv.CsvWriter writer, global::System.ReadOnlySpan<global::SerializerDemo.Person> values)
{
if (writer.Options.HasHeader)
{
var quoteHeader = writer.Options.QuoteMode is (global::Csv.QuoteMode.All or global::Csv.QuoteMode.NonNumeric);
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteRaw(AgeUtf8Key.AsSpan());
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteSeparator();
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteRaw(NameUtf8Key.AsSpan());
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteEndOfLine();
}
for (int i = 0; i < values.Length; i++)
{
var item = values[i];
writer.WriteInt32(item.Age);
writer.WriteSeparator();
writer.WriteString(item.Name);
if (i != values.Length - 1) writer.WriteEndOfLine();
}
}
public void Serialize(ref global::Csv.CsvWriter writer, global::System.Collections.Generic.IEnumerable<global::SerializerDemo.Person> values)
{
if (writer.Options.HasHeader)
{
var quoteHeader = writer.Options.QuoteMode is (global::Csv.QuoteMode.All or global::Csv.QuoteMode.NonNumeric);
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteRaw(AgeUtf8Key.AsSpan());
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteSeparator();
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteRaw(NameUtf8Key.AsSpan());
if (quoteHeader) writer.WriteRaw((byte)'"');
writer.WriteEndOfLine();
}
var e = values.GetEnumerator();
try
{
if (!e.MoveNext()) return;
while (true)
{
var item = e.Current;
writer.WriteInt32(item.Age);
writer.WriteSeparator();
writer.WriteString(item.Name);
if (!e.MoveNext())
{
writer.WriteEndOfLine();
break;
}
}
}
finally
{
e.Dispose();
}
}
public global::SerializerDemo.Person[] Deserialize(ref global::Csv.CsvReader reader)
{
var allowComments = reader.Options.AllowComments;
while (reader.TryReadEndOfLine(true) || (allowComments && reader.TrySkipComment(false))) { }
if (reader.Options.HasHeader) reader.SkipLine();
using var list = new TempList<global::SerializerDemo.Person>();
while (reader.Remaining > 0)
{
if (reader.TryReadEndOfLine()) continue;
if (allowComments && reader.TrySkipComment(false)) continue;
var __Age = default(int);
var __Name = default(string);
var ___endOfLine = false;
for (int __i = 0; __i <= 1; __i++)
{
switch (__i)
{
case 0:
__Age = reader.ReadInt32();
break;
case 1:
__Name = reader.ReadString();
break;
default:
reader.SkipField();
break;
}
if (reader.TryReadEndOfLine(true))
{
___endOfLine = true;
goto ADD_ITEM;
}
if (!reader.TryReadSeparator(false)) goto ADD_ITEM;
}
ADD_ITEM:
list.Add( new()
{
Age = __Age,
Name = __Name,
}
);
if (!___endOfLine) reader.SkipLine();
}
return list.AsSpan().ToArray();
}
public int Deserialize(ref global::Csv.CsvReader reader, global::System.Span<global::SerializerDemo.Person> destination)
{
var allowComments = reader.Options.AllowComments;
while (reader.TryReadEndOfLine(true) || (allowComments && reader.TrySkipComment(false))) { }
if (reader.Options.HasHeader) reader.SkipLine();
var n = 0;
while (reader.Remaining > 0)
{
if (reader.TryReadEndOfLine()) continue;
if (allowComments && reader.TrySkipComment(false)) continue;
var __Age = default(int);
var __Name = default(string);
var ___endOfLine = false;
for (int __i = 0; __i <= 1; __i++)
{
switch (__i)
{
case 0:
__Age = reader.ReadInt32();
break;
case 1:
__Name = reader.ReadString();
break;
default:
reader.SkipField();
break;
}
if (reader.TryReadEndOfLine(true))
{
___endOfLine = true;
goto ADD_ITEM;
}
if (!reader.TryReadSeparator(false)) goto ADD_ITEM;
}
ADD_ITEM:
destination[n++] = new()
{
Age = __Age,
Name = __Name,
}
;
if (!___endOfLine) reader.SkipLine();
}
return n;
}
}
}
#pragma warning restore CS0162 // Unreachable code
#pragma warning restore CS0219 // Variable assigned but never used
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
#pragma warning restore CS8601 // Possible null reference assignment
#pragma warning restore CS8602 // Possible null return
#pragma warning restore CS8604 // Possible null reference argument for parameter
#pragma warning restore CS8631 // The type cannot be used as type parameter in the generic type or method</code></pre>
}
// <auto-generated />
#nullable enable
#pragma warning disable CS0162 // Unreachable code
#pragma warning disable CS0219 // Variable assigned but never used
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
#pragma warning disable CS8601 // Possible null reference assignment
#pragma warning disable CS8602 // Possible null return
#pragma warning disable CS8604 // Possible null reference argument for parameter
#pragma warning disable CS8619 // Possible null reference assignment fix
#pragma warning disable CS8631 // The type cannot be used as type parameter in the generic type or method
using System;
using VYaml.Annotations;
using VYaml.Parser;
using VYaml.Emitter;
using VYaml.Serialization;
namespace SerializerDemo
{
partial class Person
{
[VYaml.Annotations.Preserve]
public static void __RegisterVYamlFormatter()
{
global::VYaml.Serialization.GeneratedResolver.Register(new PersonGeneratedFormatter());
}
[VYaml.Annotations.Preserve]
public class PersonGeneratedFormatter : IYamlFormatter<global::SerializerDemo.Person?>
{
static readonly byte[] AgeKeyUtf8Bytes = { 97, 103, 101 }; // age
<pre><code> static readonly byte[] NameKeyUtf8Bytes = { 110, 97, 109, 101 }; // name
[VYaml.Annotations.Preserve]
public void Serialize(ref Utf8YamlEmitter emitter, global::SerializerDemo.Person? value, YamlSerializationContext context)
{
if (value is null)
{
emitter.WriteNull();
return;
}
emitter.BeginMapping();
if (context.Options.NamingConvention == global::VYaml.Annotations.NamingConvention.LowerCamelCase)
{
emitter.WriteScalar(AgeKeyUtf8Bytes);
}
else
{
global::VYaml.Serialization.NamingConventionMutator.MutateToThreadStaticBufferUtf8(AgeKeyUtf8Bytes, context.Options.NamingConvention, out var mutated, out var written);
emitter.WriteScalar(mutated.AsSpan(0, written));
}
context.Serialize(ref emitter, value.Age);
if (context.Options.NamingConvention == global::VYaml.Annotations.NamingConvention.LowerCamelCase)
{
emitter.WriteScalar(NameKeyUtf8Bytes);
}
else
{
global::VYaml.Serialization.NamingConventionMutator.MutateToThreadStaticBufferUtf8(NameKeyUtf8Bytes, context.Options.NamingConvention, out var mutated, out var written);
emitter.WriteScalar(mutated.AsSpan(0, written));
}
context.Serialize(ref emitter, value.Name);
emitter.EndMapping();
}
[VYaml.Annotations.Preserve]
public global::SerializerDemo.Person? Deserialize(ref YamlParser parser, YamlDeserializationContext context)
{
if (parser.IsNullScalar())
{
parser.Read();
return default;
}
parser.ReadWithVerify(ParseEventType.MappingStart);
var __Age__ = default(int);
var __Name__ = default(string);
while (!parser.End && parser.CurrentEventType != ParseEventType.MappingEnd)
{
if (parser.CurrentEventType != ParseEventType.Scalar)
{
throw new YamlSerializerException(parser.CurrentMark, "Custom type deserialization supports only string key");
}
if (!parser.TryGetScalarAsSpan(out var key))
{
throw new YamlSerializerException(parser.CurrentMark, "Custom type deserialization supports only string key");
}
if (context.Options.NamingConvention != global::VYaml.Annotations.NamingConvention.LowerCamelCase)
{
global::VYaml.Serialization.NamingConventionMutator.MutateToThreadStaticBufferUtf8(key, global::VYaml.Annotations.NamingConvention.LowerCamelCase, out var mutated, out var written);
key = mutated.AsSpan(0, written);
}
switch (key.Length)
{
case 3:
if (key.SequenceEqual(AgeKeyUtf8Bytes))
{
parser.Read(); // skip key
__Age__ = context.DeserializeWithAlias<int>(ref parser);
continue;
}
goto default;
case 4:
if (key.SequenceEqual(NameKeyUtf8Bytes))
{
parser.Read(); // skip key
__Name__ = context.DeserializeWithAlias<string>(ref parser);
continue;
}
goto default;
default:
parser.Read(); // skip key
parser.SkipCurrentNode(); // skip value
continue;
}
}
parser.ReadWithVerify(ParseEventType.MappingEnd);
return new Person
{
Age = __Age__,
Name = __Name__,
}
;
}
}
}</code></pre>
}
#pragma warning restore CS0162 // Unreachable code
#pragma warning restore CS0219 // Variable assigned but never used
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
#pragma warning restore CS8601 // Possible null reference assignment
#pragma warning restore CS8602 // Possible null return
#pragma warning restore CS8604 // Possible null reference argument for parameter
#pragma warning restore CS8631 // The type cannot be used as type parameter in the generic type or method
Code and pdf at
https://ignatandrei.github.io/RSCG_Examples/v2/docs/Csvcsharp