C#检测文本编码格式

最近有个csv文件带"±",文件是GB2312编码格式,所以使用Encoding.Default/UTF-8读取该文件±会变成乱码,又不好写死Encoding.GetEncoding("GB2312"),所以添加一步检测。尝试了Ude.NET库检测,不好使,检测不出来。所以用AI生成了一段,亲测可用。

复制代码
   public static Encoding DetectFileEncoding(string filePath)
   {
       byte[] bytes = File.ReadAllBytes(filePath);
       if (bytes.Length == 0) return Encoding.UTF8;

       // 1. 检查 BOM (最准确)
       if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
           return Encoding.UTF8;
       if (bytes.Length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE)
           return Encoding.Unicode; // UTF-16 LE
       if (bytes.Length >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF)
           return Encoding.BigEndianUnicode; // UTF-16 BE

       // 2. 注册所有编码支持 (确保 .NET Core/.NET 5+ 能识别 GBK)
       Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

       // 3. 启发式检测:对比 UTF-8, GB18030, ISO-8859-1

       // 尝试 UTF-8
       // 如果 UTF-8 解码后出现很多替换字符 (U+FFFD),说明大概率不是 UTF-8
       string utf8String = Encoding.UTF8.GetString(bytes);
       int utf8ReplacementCount = utf8String.Count(c => c == '\uFFFD');

       // 如果替换字符很少,可能是 UTF-8 (无 BOM)
       if (utf8ReplacementCount == 0 && IsLikelyText(utf8String))
       {
           return Encoding.UTF8;
       }

       // 尝试 GB18030 (完全兼容 GB2312 和 GBK)
       Encoding gbEncoding = Encoding.GetEncoding("GB18030");
       string gbString = gbEncoding.GetString(bytes);

       // 尝试 ISO-8859-1 (单字节,永远不会失败,但中文会变成乱码)
       Encoding isoEncoding = Encoding.GetEncoding("ISO-8859-1");
       string isoString = isoEncoding.GetString(bytes);

       // 4. 关键判断逻辑:
       // 如果 GBK 解码出的字符串中包含大量汉字,而 ISO 解码出的只是普通拉丁字符或乱码符号
       // 则认为它是 GBK/GB2312

       int chineseCharCount = gbString.Count(c => c >= 0x4E00 && c <= 0x9FFF); // 基本汉字范围
       int isoWeirdCount = isoString.Count(c => c > 0x7F && (c < 0xA0 || char.IsControl(c))); // ISO 中高位字节的奇怪字符

       // 阈值:如果检测到超过 5 个汉字,基本可以确定是 GB 编码
       if (chineseCharCount > 5)
       {
           return gbEncoding;
       }

       // 如果汉字很少,但 UTF-8 也不对,默认回退到系统默认编码 (中文 Windows 下通常是 GBK)
       // 或者根据业务需求,如果是英文为主,可能真的是 ISO-8859-1
       // 这里做一个简单的置信度判断:如果 GB 解码没有乱码替换,优先 GB
       int gbReplacementCount = gbString.Count(c => c == '\uFFFD');

       if (gbReplacementCount < utf8ReplacementCount)
       {
           return gbEncoding;
       }

       // 最后手段:返回系统默认
       return Encoding.Default;
   }

   // 辅助:判断字符串是否像正常文本(非二进制垃圾)
   private static bool IsLikelyText(string text)
   {
       // 简单检查:如果包含大量控制字符,则不是文本
       int controlChars = text.Count(c => char.IsControl(c) && c != '\r' && c != '\n' && c != '\t');
       return controlChars < text.Length * 0.05;
   }

另外,Net8不支持GB2312,需要先在.csproj添加:

<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />,

再在代码添加:

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

才可使用Encoding.GetEncoding("GB2312");

相关推荐
SomeOtherTime7 分钟前
Rust 面向对象介绍(AI回答)
开发语言·python·rust
zh_xuan26 分钟前
kotlin常见面试题
开发语言·kotlin·面试题
草莓熊Lotso2 小时前
【C++ 基于微服务的即时通讯系统】文件存储子服务实战:UUID生成、文件IO封装与全接口单元测试
开发语言·网络·数据库·c++·微服务·架构·单元测试
huaqianzkh3 小时前
WinForm C#:循环修改控件UI闪烁卡顿?SuspendLayout / ResumeLayout 与 BeginUpdate 优化
开发语言·ui·c#
沐晓时光13 小时前
C语言入门,内存函数知识讲解
c语言·开发语言
David猪大卫19 小时前
【C++修炼】map 和 set 的使用
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
用户37215742613520 小时前
C# 实现 Excel 单元格保护:锁定公式并允许编辑指定区域
c#·ai编程·编程语言
fengci.21 小时前
CTF2MISC中等部分
开发语言·前端·学习
xys_6781 天前
JavaEE通关手册:初识Java
java·开发语言
ShineWinsu1 天前
对于Qt:QTableWidget常见属性以及QTableWidgetItem类的解析
开发语言·c++·qt·gui·客户端·表格·qtablewidget