11示例教你用C# .NET CsvHelper读写CSV文件(1)
作者:admin 时间:2023-5-19 15:52:38 浏览:C# .NET 使用 CsvHelper 读写CSV文件,是一个简单易用的值得推荐的方法,在前文中,我详细介绍了 CsvHelper 的特征、用法等知识,在本文中,将通过11个示例详细介绍如何使用 CsvHelper 读写CSV文件。
- 先决条件
- 读CSV文件[示例]
- 写CSV文件[示例]
文章内容目录
先决条件
以下是使用 CsvHelper 所需的一些先决条件,这些是使用 CsvHelper 时隐含的 .NET 基础知识。
使用和处置
每当你有一个对象实现IDisposable
时,你需要在用完资源时释放它。大多数使用非托管资源的类都将实现IDisposable
,这意味着System.IO
命名空间中的许多类都需要被销毁。
处理完对象的最佳做法是将代码包装在一个using
块中,当using
块退出时,资源将尽快自动处理。
using (var stream = new MemoryStream())
{
// Use the stream.
}
// The stream will be disposed of as soon as possible.
如果你需要保留它一段时间并在以后处理它,using
为你做一些错误处理,所以使用它而不是Dispose
直接调用仍然是个好主意。
var stream = new MemoryStream();
// Later in a different part of your code.
using (stream) { }
读写文件
要打开文件进行读取或写入,我们可以使用System.IO.File
。
using (var stream = File.OpenRead("path\\to\\file.csv"))
{
}
using (var stream = File.OpenWrite("path\\to\\file.csv"))
{
}
这些都返回一个FileStream
用于处理我们的文件。由于我们的数据是文本,因此我们需要使用 StreamReader
和 StreamWriter
来读写文本。
using (var stream = File.OpenRead("path\\to\\file.csv"))
using (var reader = new StreamReader(stream))
{
}
using (var stream = File.OpenWrite("path\\to\\file.csv"))
using (var writer = new StreamWriter(stream))
{
}
StreamReader
和StreamWriter
有执行此操作的快捷方式。
using (var reader = new StreamReader("path\\to\\file.csv"))
{
}
using (var writer = new StreamWriter("path\\to\\file.csv"))
{
}
CsvHelper 对你的编码一无所知,因此如果你有特定的编码,则需要在流中指定它。
using (var reader = new StreamReader("path\\to\\file.csv", Encoding.UTF8))
{
}
using (var writer = new StreamWriter("path\\to\\file.csv", Encoding.UTF8))
{
}
CsvReader
和 CsvWriter
在他们的构造函数中使用 TextReader
和 TextWriter
。TextReader
和 TextWriter
是阅读和写作文本的abstract
类。StreamReader
继承 TextReader
, StreamWriter
继承TextWriter
,所以我们可以使用CsvReader
和CsvWriter
。
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader))
{
}
using (var writer = new StreamWriter("path\\to\\file.csv"))
using (var csv = new CsvWriter(writer))
{
}
Streams
从流中读取时,如果需要回到流的开头,可以使用 Stream.Position
属性。
using (var stream = new File.OpenRead("path\\to\\file"))
using (var reader = new StreamReader(stream))
{
// Read file content.
var content = reader.ReadToEnd();
// Go back to beginning of the stream.
stream.Position = 0;
// Read file content again.
content = reader.ReadToEnd();
}
写入文件时,需要刷新写入器才能将数据写入流。StreamWriter
包含一个内部缓冲区,数据仅在缓冲区已满或被调用Flush
时写入流。当using
块退出时自动调用Flush
。
using (var stream = new File.OpenWrite("path\\to\\file"))
using (var writer = new StreamWriter(stream))
{
writer.WriteLine("Foo");
writer.Flush(); // Data is written from the writer buffer to the stream.
} // Flush is also called here.
读CSV文件[示例]
获得类记录
将 CSV 行转换为类对象。
数据
Id,Name
1,one
例子
void Main()
{
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<Foo>();
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
获取动态记录
将 CSV 行转换为动态对象。由于无法确定属性应该是什么类型,因此动态对象上的所有属性都是字符串。
数据
Id,Name
1,one
例子
void Main()
{
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = csv.GetRecords<dynamic>();
}
}
获取匿名类型记录
将 CSV 行转换为匿名类型对象。你只需要提供匿名类型定义。
数据
Id,Name
1,one
例子
void Main()
{
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var anonymousTypeDefinition = new
{
Id = default(int),
Name = string.Empty
};
var records = csv.GetRecords(anonymousTypeDefinition);
}
}
枚举类记录
将 CSV 行转换为在可枚举的每次迭代中重复使用的类对象。每个枚举都会混合给定的记录,但仅限于映射的成员。如果你提供了一个映射但没有映射其中一个成员,则该成员将不会与当前行的数据混合。当心在强制IEnumerable
评估的投影上调用的任何方法,例如ToList()
,你将获得一个列表,其中所有记录都是你提供的与 CSV 文件中的最后一条记录混合的相同实例。
数据
Id,Name
1,one
例子
void Main()
{
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var record = new Foo();
var records = csv.EnumerateRecords(record);
foreach (var r in records)
{
// r is the same instance as record.
}
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
手动读取
有时出于各种原因,不尝试配置映射以匹配你的类定义会更容易。通常只需要多几行代码就可以手动读取行。
数据
Id,Name
1,one
例子
void Main()
{
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var records = new List<Foo>();
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
var record = new Foo
{
Id = csv.GetField<int>("Id"),
Name = csv.GetField("Name")
};
records.Add(record);
}
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
读取多个数据集
出于某种原因,存在包含多组 CSV 数据的 CSV 文件。你应该能够毫无问题地读取这样的文件。你将需要检测何时更改要检索的类类型。
数据
FooId,Name
1,foo
BarId,Name
07a0fca2-1b1c-4e44-b1be-c2b05da5afc7,bar
例子
void Main()
{
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
IgnoreBlankLines = false,
};
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, config))
{
csv.Context.RegisterClassMap<FooMap>();
csv.Context.RegisterClassMap<BarMap>();
var fooRecords = new List<Foo>();
var barRecords = new List<Bar>();
var isHeader = true;
while (csv.Read())
{
if (isHeader)
{
csv.ReadHeader();
isHeader = false;
continue;
}
if (string.IsNullOrEmpty(csv.GetField(0)))
{
isHeader = true;
continue;
}
switch (csv.HeaderRecord[0])
{
case "FooId":
fooRecords.Add(csv.GetRecord<Foo>());
break;
case "BarId":
barRecords.Add(csv.GetRecord<Bar>());
break;
default:
throw new InvalidOperationException("Unknown record type.");
}
}
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Bar
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public sealed class FooMap : ClassMap<Foo>
{
public FooMap()
{
Map(m => m.Id).Name("FooId");
Map(m => m.Name);
}
}
public sealed class BarMap : ClassMap<Bar>
{
public BarMap()
{
Map(m => m.Id).Name("BarId");
Map(m => m.Name);
}
}
读取多种记录类型
如果你有 CSV 数据,其中每一行可能是不同的记录类型,你应该能够根据行类型或类似的东西读取。
数据
A,1,foo
B,07a0fca2-1b1c-4e44-b1be-c2b05da5afc7,bar
例子
void Main()
{
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
HasHeaderRecord = false,
};
using (var reader = new StreamReader("path\\to\\file.csv"))
using (var csv = new CsvReader(reader, config))
{
csv.Context.RegisterClassMap<FooMap>();
csv.Context.RegisterClassMap<BarMap>();
var fooRecords = new List<Foo>();
var barRecords = new List<Bar>();
while (csv.Read())
{
switch (csv.GetField(0))
{
case "A":
fooRecords.Add(csv.GetRecord<Foo>());
break;
case "B":
barRecords.Add(csv.GetRecord<Bar>());
break;
default:
throw new InvalidOperationException("Unknown record type.");
}
}
}
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Bar
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public sealed class FooMap : ClassMap<Foo>
{
public FooMap()
{
Map(m => m.Id).Index(1);
Map(m => m.Name).Index(2);
}
}
public sealed class BarMap : ClassMap<Bar>
{
public BarMap()
{
Map(m => m.Id).Index(1);
Map(m => m.Name).Index(2);
}
}
写CSV文件[示例]
由于篇幅有限,CsvHelper 写CSV文件[示例]请参阅下一篇文章:
相关文章
- 站长推荐