CSVHelper C# 生成错误字符

问题描述 投票:0回答:1

我正在使用 CsvHelper 库写入 CSV 文件。但是,我的一些 CSV 文件具有不同的编码,导致写入数据中出现随机字符。下面是一个代码示例,说明了我目前在项目中如何处理这个问题。我该如何解决?

 public async Task WriteAsync<T>(string path, T record)
        {

            bool containsNewLines = ContainsNewLines(path);
            using (var stream = File.Open(path, FileMode.Append))
            using (var writer = new StreamWriter(stream, Encoding.UTF8))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                if (!containsNewLines)
                {
                    await csv.NextRecordAsync();
                }
                csv.WriteRecord(record);
                await csv.NextRecordAsync();
            }
        }

        private bool ContainsNewLines(string filePath)
        {
            using (var reader = new StreamReader(filePath))
            {
                string content = reader.ReadToEnd();
                return content.EndsWith(Environment.NewLine);
            }
        }
c# csvhelper
1个回答
0
投票

问题是,没有万无一失的方法来确定文件的编码。正如 Panagiotis Kanavos 所说,最好的答案是要么要求所有文件都采用单一编码,比如

UTF8
,要么让文件的创建者以某种方式为您提供文件的编码。

也就是说,可以猜测编码。这是对 Berthier Lemieux 的答案 的修改,用于检测文件编码。该方法读取整个文件并假设它是

UTF8
编码。如果阅读器在读取
UTF8
时抛出异常,则默认为您首选的
ANSI
编码。这种方法最适合我确定
UTF8
ANSI
编码之间的差异。它不会检测所有类型的编码。

public Encoding DetectFileEncoding(string fileName, Encoding defaultEncoding)
{
    var Utf8EncodingVerifier = Encoding.GetEncoding("utf-8", 
            new EncoderExceptionFallback(), new DecoderExceptionFallback());
    using (var reader = new StreamReader(fileName, Utf8EncodingVerifier, 
            detectEncodingFromByteOrderMarks: true, bufferSize: 1024))
    {
        try
        {
            while (!reader.EndOfStream)
            {
                _ = reader.ReadLine();
            }
            return reader.CurrentEncoding;
        }
        catch (Exception)
        {
            // Failed to decode the file using the BOM/UT8. 
            // return default encoding
            return defaultEncoding;
        }
    }
}

然后您可以使用

DetectFileEncoding
设置
StreamWriter
的编码。如果您的文件不太可能采用
Latin1 (ISO-8859-1)
编码,那么您可以使用最适合您的默认编码。

public async Task WriteAsync<T>(string path, T record)
{
    bool containsNewLines = ContainsNewLines(path);
    Encoding fileEncoding = DetectFileEncoding(path, Encoding.Latin1);

    using (var stream = File.Open(path, FileMode.Append))
    using (var writer = new StreamWriter(stream, fileEncoding))
    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
    {
        if (!containsNewLines)
        {
            await csv.NextRecordAsync();
        }
        csv.WriteRecord(record);
        await csv.NextRecordAsync();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.