c# - 使用 C# 检测文本文件的编码

标签 c# encoding utf-8

我有一组 markdown 文件要传递给 jekyll 项目,需要使用程序或 API 找到它们的编码格式,即带 BOM 的 UTF-8 或不带 BOM 的 UTF-8 或 ANSI。

如果我传递文件的位置,则必须列出文件、读取文件并生成编码作为结果。

是否有任何代码或 API?

我已经尝试过使用 sr.CurrentEncoding for stream reader,如 Effective way to find any file's Encoding 中所述,但结果因 notepad++ 结果而异。

还尝试使用 https://github.com/errepi/ude (Mozilla 通用字符集检测器)如 https://social.msdn.microsoft.com/Forums/vstudio/en-US/862e3342-cc88-478f-bca2-e2de6f60d2fb/detect-encoding-of-the-file?forum=csharpgeneral 中所建议通过在c#项目中实现ude.dll,但结果不如notepad++有效,文件编码显示为utf-8,但从程序中,结果为utf-8 with BOM。

但是我应该从这两种方式得到相同的结果,所以问题发生在哪里?

最佳答案

检测编码总是一件棘手的事情,但检测 BOM 却非常简单。要将 BOM 作为字节数组获取,只需使用编码对象的 GetPreamble() 函数即可。这应该允许您通过前导码检测整个编码范围。

现在,至于检测没有前导码的 UTF-8,其实也不是很难。看,UTF8 has strict bitwise rules about what values are expected in a valid sequence , 你可以初始化一个 UTF8Encoding 对象 in a way that will fail by throwing an exception when these sequences are incorrect .

因此,如果您首先进行 BOM 检查,然后进行严格的解码检查,最后退回到 Win-1252 编码(您称之为“ANSI”),那么您的检测就完成了。

Byte[] bytes = File.ReadAllBytes(filename);
Encoding encoding = null;
String text = null;
// Test UTF8 with BOM. This check can easily be copied and adapted
// to detect many other encodings that use BOMs.
UTF8Encoding encUtf8Bom = new UTF8Encoding(true, true);
Boolean couldBeUtf8 = true;
Byte[] preamble = encUtf8Bom.GetPreamble();
Int32 prLen = preamble.Length;
if (bytes.Length >= prLen && preamble.SequenceEqual(bytes.Take(prLen)))
{
    // UTF8 BOM found; use encUtf8Bom to decode.
    try
    {
        // Seems that despite being an encoding with preamble,
        // it doesn't actually skip said preamble when decoding...
        text = encUtf8Bom.GetString(bytes, prLen, bytes.Length - prLen);
        encoding = encUtf8Bom;
    }
    catch (ArgumentException)
    {
        // Confirmed as not UTF-8!
        couldBeUtf8 = false;
    }
}
// use boolean to skip this if it's already confirmed as incorrect UTF-8 decoding.
if (couldBeUtf8 && encoding == null)
{
    // test UTF-8 on strict encoding rules. Note that on pure ASCII this will
    // succeed as well, since valid ASCII is automatically valid UTF-8.
    UTF8Encoding encUtf8NoBom = new UTF8Encoding(false, true);
    try
    {
        text = encUtf8NoBom.GetString(bytes);
        encoding = encUtf8NoBom;
    }
    catch (ArgumentException)
    {
        // Confirmed as not UTF-8!
    }
}
// fall back to default ANSI encoding.
if (encoding == null)
{
    encoding = Encoding.GetEncoding(1252);
    text = encoding.GetString(bytes);
}

请注意,Windows-1252(美国/西欧 ANSI)是一种每个字符一个字节的编码,这意味着其中的所有内容都会产生技术上有效的字符,因此 unless you go for heuristic methods , 无法对其进行进一步检测以将其与其他每字符一个字节的编码区分开来。

关于c# - 使用 C# 检测文本文件的编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48380031/

相关文章:

c# - 往返格式说明符 "R"的 64 位与 32 位双重解析问题

c# - 使用 C# 检查 IIS 中是否启用了表单例份验证

c# - 如何在 8*8 DataMatrix 中编码超过 3 个字符?

python - 如何将外来编码字符写入文本文件

c# - 如果 boolean 为 false,则在字符串中添加逗号和其他单词

c# - 如何播放视频文件?

java - Request.getParameter() 仅将 "+"替换为 ""

java - java中如何解决这个编码问题

python - python 中的 u' ' 前缀和 unicode() 有什么区别?

encoding - Rails 3 - (不兼容的字符编码 : UTF-8 and ASCII-8BIT):