首页 > 解决方案 > c#编码问题与CsvHelper

问题描述

var orders = new List<Order>();
....
orders.Add(...)


string csvstring;
using (var ms = new MemoryStream())
using (var wr = new StreamWriter(stream, Encoding.UTF8))
using (var csvWriter = new CsvWriter(wr, CultureInfo.InvariantCulture, false))
{
    

csvWriter.WriteRecords(orders);
    csvstring = Encoding.UTF8.GetString(stream.ToArray());
}

接着

sftp.WriteAllText(fileNameAbsolutePath, csvstring, Encoding.UTF8);

在 sftp 中创建的文件的内容以“feff”开头。“orders.csv:文本/纯文本;charset=utf-8”。

这是问题的第一部分。我正在寻找的是将此 UTF8 转换为 IS0-8859-1,因为最终文件中预期的字符集是 IS0-8859-1。

可能我应该做这样的事情吗?

byte[] bytesSS = Encoding.Convert(Encoding.UTF8, Encoding.GetEncoding("ISO-8859-1"), Encoding.UTF8.GetBytes(csvstring));

string s1 = Encoding.GetEncoding("ISO-8859-1").GetString(bytesSS, 0, bytesSS.Length);

试图用谷歌搜索“ <feff>”,但我完全没有得到 BOM 的概念和解决这个问题的方法。

标签: c#encodingiso-8859-1csvhelperbyte-order-mark

解决方案


我不知道您使用哪个 SFTP 类作为 .NET 本身没有 SFTP 客户端。我假设您使用这个只是因为它在 Google 搜索中排在第一位sftp WriteAllText

如果要创建具有特定编码的文件,请在StreamWriter构造函数中指定它,而不是UTF8

using (var ms = new MemoryStream())
using (var wr = new StreamWriter(stream, Encoding.GetEncoding("ISO-8859-1")))
using (var csvWriter = new CsvWriter(wr, CultureInfo.InvariantCulture, false))
{    
    csvWriter.WriteRecords(orders);
}

另一方面,UTF8 和 Latin1(或任何代码页)对 0-127 范围内的字符使用完全相同的值。如果您只想发送英文文本,那么无论您使用哪种编码都不会有任何区别。如果实际要求是创建一个没有 BOM 的 UTF8 文件,您可以使用适当的UTF8Encoding 构造函数来指定它:

var utf8NoBom=new UTF8Encoding(false);
using (var ms = new MemoryStream())
using (var wr = new StreamWriter(stream, utf8NoBom)))
using (var csvWriter = new CsvWriter(wr, CultureInfo.InvariantCulture, false))
{    
    csvWriter.WriteRecords(orders);
}

所有 SFTP 客户端都有(或应该有)一种使用流上传数据的方法。这意味着您可以使用Stream.CopyTo将数据从内存流复制到上传流。假设OpenWrite可用,您可以将代码修改为:

using (var ms = new MemoryStream())
{
    using (var wr = new StreamWriter(stream, Encoding.GetEncoding("ISO-8859-1")))
    using (var csvWriter = new CsvWriter(wr, CultureInfo.InvariantCulture, false))
    {    
        csvWriter.WriteRecords(orders);
    }

    ms.Position=0;

    using(var stream=sftp.OpenWrite(somePath))
    {
        ms.CopyTo(stream);
    }
}

当 CsvHelper 完成时,MemoryStream 的位置位于流的末尾并且CopyTo不会复制任何内容。通过使用ms.Position,您可以将位置移动到流的开头。


推荐阅读