如何读取上传的 CSV UTF-8 以使用 CsvHelper 进行处理?
How to read uploaded CSV UTF-8 for processing with CsvHelper?
我的 WebAPI 允许用户上传 CSV 文件,然后解析该文件。我使用 CsvHelper 来完成读取 CSV 并将其映射到域 objects.
的繁重工作
但是,我有一位客户的文件是 CSV UTF-8 格式。适用于 "vanilla" (ASCII) CSV 文件的代码在尝试处理 CSV UTF-8 时会抛出异常。
有没有办法导入 CSV UTF-8 数据并将其转换为 ASCII CSV 以便我的代码继续工作?
我当前的代码如下所示:
//In my WebAPI Controller
//fileToProcess is IFormFile
byte[] fileBytes = new byte[fileToProcess.Length];
using(var stream = fileToProcess.OpenReadStream())
{
await stream.ReadAsync(fileBytes);
stream.Close();
}
var result = await ProcessFileAsync(fileBytes);
return OK(result);
...
//In a Parsing Class
public async Task<List<Client>> ProcessFileAsync(byte[] fileBytes)
{
List<Client> result = null;
var fileText = Encoding.Default.GetString(fileBytes);
using(var reader = new StringReader(fileText))
{
using(var csv = new CsvReader(reader))
{
csv.RegisterClassMap<ClientMap>();
result = csv.GetRecords<T>().ToList();
await PostProcess(result);
}
}
return result;
}
问题在于 CSV UTF-8 具有 BOM,因此当 CsvHelper 尝试处理引用第一列的映射时 header
Map(c => c.ClientId).Name("CLIENT ID");
它失败了,因为列名包含 BOM。
所以,我的问题是:
- 如何判断传入的文件是 UTF-8 还是 ASCII。
- 如何将UTF-8转为ASCII才能正常处理?
注意
我确实尝试了以下方法:
fileBytes = Encoding.Convert(Encoding.UTF8, Encoding.ASCII, fileBytes);
但是,这用 ?
替换了 BOM,这仍然导致 CsvHelper 失败。
通过这样做:
var fileText = Encoding.Default.GetString(fileBytes);
using(var reader = new StringReader(fileText))
...在将其转换为字符串时,您将自己锁定在特定的编码中。 Encoding.Default
可能因平台和 CLR 实现而异。
StreamReader
class 旨在从流中读取文本(您可以使用 MemoryStream
环绕原始字节)并且能够为您检测编码如果你愿意的话。试试这个:
using (var stream = new MemoryStream(fileBytes))
using (var reader = new StreamReader(stream))
在您的情况下,您可以通过更改 ProcessFileAsync
以接受流来直接使用传入流。
using (var stream = fileToProcess.OpenReadStream())
{
var result = await ProcessFileAsync(stream);
return OK(result);
}
public async Task<List<Client>> ProcessFileAsync(Stream stream)
{
using (var reader = new StreamReader(stream))
{
using (var csv = new CsvReader(reader))
{
csv.RegisterClassMap<ClientMap>();
List<Client> result = csv.GetRecords<Client>().ToList();
await PostProcess(result);
return result;
}
}
}
只要 BOM 存在,这也将支持 UTF16 编码和 UTF32 编码的文件(以及几乎任何其他可以检测到的文件),因为它会在中看到 U+FEFF
代码点无论它使用哪种编码。
我的 WebAPI 允许用户上传 CSV 文件,然后解析该文件。我使用 CsvHelper 来完成读取 CSV 并将其映射到域 objects.
的繁重工作但是,我有一位客户的文件是 CSV UTF-8 格式。适用于 "vanilla" (ASCII) CSV 文件的代码在尝试处理 CSV UTF-8 时会抛出异常。
有没有办法导入 CSV UTF-8 数据并将其转换为 ASCII CSV 以便我的代码继续工作?
我当前的代码如下所示:
//In my WebAPI Controller
//fileToProcess is IFormFile
byte[] fileBytes = new byte[fileToProcess.Length];
using(var stream = fileToProcess.OpenReadStream())
{
await stream.ReadAsync(fileBytes);
stream.Close();
}
var result = await ProcessFileAsync(fileBytes);
return OK(result);
...
//In a Parsing Class
public async Task<List<Client>> ProcessFileAsync(byte[] fileBytes)
{
List<Client> result = null;
var fileText = Encoding.Default.GetString(fileBytes);
using(var reader = new StringReader(fileText))
{
using(var csv = new CsvReader(reader))
{
csv.RegisterClassMap<ClientMap>();
result = csv.GetRecords<T>().ToList();
await PostProcess(result);
}
}
return result;
}
问题在于 CSV UTF-8 具有 BOM,因此当 CsvHelper 尝试处理引用第一列的映射时 header
Map(c => c.ClientId).Name("CLIENT ID");
它失败了,因为列名包含 BOM。
所以,我的问题是:
- 如何判断传入的文件是 UTF-8 还是 ASCII。
- 如何将UTF-8转为ASCII才能正常处理?
注意
我确实尝试了以下方法:
fileBytes = Encoding.Convert(Encoding.UTF8, Encoding.ASCII, fileBytes);
但是,这用 ?
替换了 BOM,这仍然导致 CsvHelper 失败。
通过这样做:
var fileText = Encoding.Default.GetString(fileBytes);
using(var reader = new StringReader(fileText))
...在将其转换为字符串时,您将自己锁定在特定的编码中。 Encoding.Default
可能因平台和 CLR 实现而异。
StreamReader
class 旨在从流中读取文本(您可以使用 MemoryStream
环绕原始字节)并且能够为您检测编码如果你愿意的话。试试这个:
using (var stream = new MemoryStream(fileBytes))
using (var reader = new StreamReader(stream))
在您的情况下,您可以通过更改 ProcessFileAsync
以接受流来直接使用传入流。
using (var stream = fileToProcess.OpenReadStream())
{
var result = await ProcessFileAsync(stream);
return OK(result);
}
public async Task<List<Client>> ProcessFileAsync(Stream stream)
{
using (var reader = new StreamReader(stream))
{
using (var csv = new CsvReader(reader))
{
csv.RegisterClassMap<ClientMap>();
List<Client> result = csv.GetRecords<Client>().ToList();
await PostProcess(result);
return result;
}
}
}
只要 BOM 存在,这也将支持 UTF16 编码和 UTF32 编码的文件(以及几乎任何其他可以检测到的文件),因为它会在中看到 U+FEFF
代码点无论它使用哪种编码。