基于 C# 的文本文件的编码识别

news2024/9/28 2:19:28

基于 C# 的文本文件的编码识别

  • 前言
    • 一、有 BOM 文件头
    • 二、无 BOM 文件头
    • 三、简体中文汉字编码
    • 四、C# 程序对编码的识别
      • 1、文件选择按钮代码:
      • 2、获取文件编码,有 BOM 的文件识别
      • 3、获取文件编码,UTF8 无 BOM 文件的识别
      • 4、获取文件编码,UTF16 无 BOM 文件的识别
      • 5、获取非 UTF8、UTF16、UTF32 文件的 ASCII 和中文编码
  • 五、程序通过验证
  • 六、源代码下载

前言

在 Windows 系统下,文本编码存在有无 BOM 的编码。BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode 编码标准中用于标识文件是采用哪种格式的编码。有文件 BOM 头的 Unicode 编码容易识别,无 BOM 文件头的要在文件中查找字节顺序来判断 Unicode 编码。

一、有 BOM 文件头

文件编码文件头 0-3 字节顺序 BOM 标记汉字字节组成以“中文”为例的编码(后回车)
Unicode0xFF,0xFE,非0,非0一个汉字 2 字节,“中文”二字共 4 字节2D 4E 87 65 0D 00 0A 00
BigEndianUnicode0xFE,0xFF,非0,非0一个汉字 2 字节,“中文”二字共 4 字节4E 2D 65 87 00 0D 00 0A
UTF320xFF,0xFE,0,0一个汉字 4 字节,“中文”二字共 8 字节2D 4E 00 00 87 65 00 00 0D 00 0A 00
UTF32BE0xFE,0xFF,0,0一个汉字 4 字节,“中文”二字共 8 字节4E 2D 00 00 65 87 00 00 00 0D 00 0A
UTF80xEF,0xBB,0xBF一个汉字3字节,“中文”二字共6字节E4 B8 AD E6 96 87 0D 0A

二、无 BOM 文件头

文件编码文件头 0-4 字节顺序 BOM 标记汉字字节组成以“中文”为例的编码
Unicode一个汉字 2 字节,“中文”二字共 4 字节2D 4E 87 65 0D 00 0A 00
BigEndianUnicode一个汉字 2 字节,“中文”二字共 4 字节4E 2D 65 87 00 0D 00 0A
UTF32一个汉字 4 字节,“中文”二字共 8 字节2D 4E 00 00 87 65 00 00 00 0D 00 0A 00
UTF32BE一个汉字 4 字节,“中文”二字共 8 字节4E 2D 00 00 65 87 00 00 00 0D 00 0A
UTF8一个汉字3字节,“中文”二字共6字节E4 B8 AD E6 96 87 0D 0A
ANSI一个汉字 2 字节,“中文”二字共 4 字节D6 D0 CE C4 0D 0A

三、简体中文汉字编码

中文编码(按新旧顺序)代码页以“中文”为例
GB18030CP54936D6 D0 CE C4
GBKCP936D6 D0 CE C4
GB2312CP20936D6 D0 CE C4
HZ-GB2312CP52936D6 D0 CE C4
BIG5CP950A4 A4 A4 E5

四、C# 程序对编码的识别

1、文件选择按钮代码:

    private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog Openfiledialog = new OpenFileDialog();
            Openfiledialog.InitialDirectory = Application.StartupPath;
            Openfiledialog.Filter = "文本文件(*.TXT)|*.TXT|所有文件(*.*)|*.*";
            Openfiledialog.Title = "打开文件";
            Openfiledialog.Multiselect = true;
            Openfiledialog.FilterIndex = 0;

            dataGridView1.Columns.Clear();
            DataGridViewColumn col;
            DataGridViewRow row;
            DataGridViewCell cell = new DataGridViewTextBoxCell();
            string[] HeaderText = { "文件", "编码" };
            for (int i = 0; i < 2; i++)
            {
                col = new DataGridViewColumn();
                col.HeaderText = HeaderText[i];
                col.CellTemplate = cell;
                col.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;

                dataGridView1.Columns.Add(col);
                dataGridView1.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
            }

            if (Openfiledialog.ShowDialog() == DialogResult.OK)
            {
                string[] FilePath = Openfiledialog.FileNames;

                foreach (string file in FilePath)
                {
                    row = new DataGridViewRow();
                    cell = new DataGridViewTextBoxCell();
                    cell.Value = file;
                    row.Cells.Add(cell);

                    cell = new DataGridViewTextBoxCell();
                    cell.Value = GetEncoding(file).WebName;
                    row.Cells.Add(cell);
                    dataGridView1.Rows.Add(row);
                }
            }
            dataGridView1.AutoResizeColumns();
        }

2、获取文件编码,有 BOM 的文件识别

       /// <summary>获取文件的编码格式</summary>
        /// <param name="file_name">文件</param>
        /// <returns>文件的编码类型</returns>
        private static Encoding GetEncoding(string file_name)
        {
            //文件的字符集在Windows下有两种,一种是ANSI,一种Unicode。
            //对于Unicode,Windows支持了它的三种编码方式,
            //一种是小尾编码(Unicode),一种是大尾编码(BigEndianUnicode),一种是UTF - 8编码。
            if (file_name == null)
            {
                throw new ArgumentNullException(nameof(file_name));
            }

            FileStream fs = new FileStream(file_name, FileMode.Open, FileAccess.Read);
            long FsLeng = fs.Length;

            if (FsLeng < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(FsLeng));
            }

            byte[] bytes = new byte[FsLeng];

            if (fs.Length < 3)//小于BOM文件头3字节
            {
                fs.Close();
                return Encoding.ASCII;
            }

            fs.Read(bytes, 0, bytes.Length);
            fs.Close();

            if (bytes[0] == 0xFF && bytes[1] == 0xFE && (bytes[2] != 0 || bytes[3] != 0))//Unicode BOM标记
            {
                return Encoding.Unicode;
            }
            else if (bytes[0] == 0xFE && bytes[1] == 0xFF && (bytes[2] != 0 || bytes[3] != 0))//BigEndianUnicode BOM标记
            {
                return Encoding.BigEndianUnicode;
            }
            else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0 && bytes[3] == 0)//UTF32 BOM标记
            {
                return Encoding.UTF32;
            }
            else if (bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0xFE && bytes[3] == 0xFF)//UTF32BE BOM标记
            {
                return Encoding.GetEncoding("utf-32BE");
            }
            else if (bytes[0] == 0xEF && bytes[1] == 0xBB && (bytes[2] == 0xBF))//UTF8 BOM标记
            {
                return Encoding.UTF8;
            }
            else//无BOM标记
            {
                Encoding encoding = CheckUtf16Ascii(bytes, bytes.Length);//识别无BOM标记的UTF16
                if (IsUTF8Bytes(bytes))
                {
                    if (encoding == null)
                    {
                        if (IsOnlyAscii(bytes))//只有ASCII字符
                        {
                            return Encoding.ASCII;//ASCII或UTF8下的ASCII
                        }
                        else
                        {
                            return Encoding.UTF8; //无BOM标记的UTF8
                        }
                    }
                    else
                    {
                        return encoding;//无BOM标记的UTF16
                    }
                }
                else
                {
                    if (encoding == null)
                    {
                        string STR = Encoding.Default.GetString(bytes);

                        if (IsOnlyAscii(bytes))
                        {
                            return Encoding.ASCII;
                        }
                        else if (IsGBK(STR))
                        {
                            return Encoding.GetEncoding("GBK");
                        }
                        else if (IsGB2312(STR))
                        {
                            return Encoding.GetEncoding("GB2312");
                        }
                        else if (IsGB18030(STR))
                        {
                            return Encoding.GetEncoding("GB18030");
                        }
                        else
                        {
                            return Encoding.Default;//无法识别,默认为GB2312
                        }

                    }
                    else
                    {
                        return encoding;//无BOM标记的UTF16
                    }

                }
            }
        }
      

3、获取文件编码,UTF8 无 BOM 文件的识别

 private static bool IsUTF8Bytes(byte[] data)
        {
            int charByteCounter = 1;  //计算当前正分析的字符应还有的字节数
            byte curByte; //当前分析的字节.

            for (int i = 0; i < data.Length; i++)
            {
                curByte = data[i];
                if (charByteCounter == 1)
                {
                    if (curByte >= 0x80)
                    {
                        //判断当前
                        while (((curByte <<= 1) & 0x80) != 0)
                        {

                            charByteCounter++;
                        }
                        //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 
                        if (charByteCounter == 1 || charByteCounter > 6)
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    //若是UTF-8 此时第一位必须为1
                    if ((curByte & 0xC0) != 0x80)
                    {
                        return false;
                    }
                    charByteCounter--;
                }
            }

            if (charByteCounter > 1)
            {
                throw new Exception("非预期的byte格式");
            }
            return true;
        }

4、获取文件编码,UTF16 无 BOM 文件的识别

 private static Encoding CheckUtf16Ascii(byte[] buffer, int size)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (size < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(size));
            }

            if (size < 2)
            {
                return null;
            }

            // 将大小减小1,这样我们就不必担心字节对的边界检查
            size--;

            const double threshold = 0.5; // 允许一些非英语ISO-8859-1子集的UTF-16字符,同时仍检测编码。
            const double limit = 0.1;

            var leAsciiChars = 0;
            var beAsciiChars = 0;

            var pos = 0;
            while (pos < size)
            {
                byte ch1 = buffer[pos++];
                byte ch2 = buffer[pos++];

                // 偶数计数为空
                if (ch1 == 0 && ch2 != 0)
                {
                    beAsciiChars++;
                }

                // 奇数计数空值
                if (ch1 != 0 && ch2 == 0)
                {
                    leAsciiChars++;
                }
            }

            // 恢复大小
            size++;

            double leAsciiCharsPct = leAsciiChars * 2.0 / size;
            double beAsciiCharsPct = beAsciiChars * 2.0 / size;

            if (leAsciiCharsPct > threshold && beAsciiCharsPct < limit)
            {
                return Encoding.Unicode;
            }

            if (beAsciiCharsPct > threshold && leAsciiCharsPct < limit)
            {
                return Encoding.BigEndianUnicode;
            }

            // 无法识别的编码
            return null;
        }

5、获取非 UTF8、UTF16、UTF32 文件的 ASCII 和中文编码

        private static bool IsOnlyAscii(byte[] bytes)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }
            for (int i = 0; i < bytes.Length; i++)
            {
                if (bytes[i] > 127) return false;//小于127的只有ASCII字符
            }
            return true;
        }

        private static bool IsGBK(string input)
        {
            // 正则表达式匹配所有汉字字符
            var regex = new Regex(@"[\u4E00-\u9FA5]"); // 检查输入字符串中的所有字符是否都匹配GBK编码区间
            return regex.IsMatch(input);
        }

        private static bool IsGB2312(string input)
        {
            var regex = new Regex(@"[\uB0A1-\uF7FE\u8140-\uA4D0]"); // 检查输入字符串中的所有字符是否都匹配GB2312编码区间
            return regex.IsMatch(input);
        }

        private static bool IsGB18030(string input)
        {
            var regex = new Regex(@"[\u4E00-\u9FA5\uE7C7-\uE7F3]");// 检查输入字符串中的所有字符是否都匹配GB18030编码区间
            return regex.IsMatch(input);
        }

五、程序通过验证

在这里插入图片描述

六、源代码下载

https://download.csdn.net/download/zyyujq/89805828

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2171947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何有效应对商标撤三挑战?

商标撤三作为商标法中的一项重要制度&#xff0c;时刻考验着企业的商标维护与保护能力。面对这一挑战&#xff0c;企业如何构建一套有效的商标撤三管理体系&#xff0c;以确保自身品牌权益不受侵害&#xff0c;成为了一个亟待解决的问题。 理解商标撤三制度的核心要义 商标撤三…

【MyBatis 源码拆解系列】执行 Mapper 接口的方法时,MyBatis 怎么知道执行的哪个 SQL?

欢迎关注公众号 【11来了】 &#xff0c;持续 MyBatis 源码系列内容&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址&#xff1a;点击查看文章导读&#xff01; 感谢你的关注&#xff…

web前端-CSS字体属性

CSS Fonts(字体)属性用于定义字体系列、大小、粗细、和文字样式(如斜体)。 一、字体 1.字体系列 CSS使用font-family属性定义文本的字体系列 例如&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

vmware-toolbox安装,VMware虚拟机访问win10共享目录

问题&#xff1a;VMware界面无法安装vmware-toolbox&#xff0c;共享目录设置失败 解决方法&#xff1a; VMware设置 共享文件夹 ubuntu24 vm中运行vmware-toolbox-cmd -v 检查版本 vm运行sudo apt install open-vm-tools // vm可能需要重启 vm的 /mnt 目录下如果没有 hgfs…

UE5 C++: 插件编写04 | 增加和删改前缀

准备工作 UObject* Asset UObject* Asset 通常指的是一个指向UObject的指针。UObject是Unreal Engine中的基类&#xff0c;几乎所有的引擎对象都继承自UObject。这个指针可以引用任何派生自UObject的对象&#xff0c;比如蓝图、材质、贴图、音频资源等资产。 如果你看到UObj…

开箱即用的大模型应用跟踪与批量测试方案

背景介绍 最近抽空参加了一个讯飞的 RAG 比赛&#xff0c;耗时两周终于在最后一天冲上了榜首。 整体的框架是基于 RAG 能力有点弱弱的 Dify 实现。在比赛调优的过程中&#xff0c;经常需要批量提交几百个问题至 Dify 获取回答&#xff0c;并需要跟踪多轮调优的效果差异。借助…

Paxos 协议详解:分布式系统一致性的基石

文章目录 1. 分布式系统与一致性问题1.1 分布式系统的定义1.2 一致性问题的起源1.3 CAP 定理及其影响1.4 分布式系统中的失败假设 2. Paxos 协议的背景与介绍2.1 Paxos 协议是什么2.3 Paxos 解决什么问题 3. Paxos 的基本原理3.1 Paxos 角色3.2 Paxos 的多数原则3.3 Paxos 协议…

Python画笔案例-068 绘制漂亮米

1、绘制漂亮米 通过 python 的turtle 库绘制 漂亮米,如下图: 2、实现代码 绘制 漂亮米,以下为实现代码: """漂亮米.py注意亮度为0.5的时候最鲜艳本程序需要coloradd模块支持,安装方法:pip install coloradd程序运行需要很长时间,请耐心等待。可以把窗口最小…

找不到MFC100U.dll,无法继续执行代码,重新安装此程序可解决此问题

概要 最近在研究中移物联的模组ML307R&#xff0c;通过二次开发 的方式对之前开发的物联网--如意控项目进行升级&#xff0c;研究了ML307R模组的开发资料&#xff0c;中移物联的模组二次开发难度确实很高&#xff0c;中移物联ML307R的openCPU开发采用的事C语言开发的&#xff0…

局域网中实现一对一视频聊天(附源码)

一、什么是webRTC WebRTC&#xff08;Web Real-Time Communication&#xff09;是一项支持网页浏览器进行实时语音对话或视频对话的API技术。它允许直接在浏览器中实现点对点&#xff08;Peer-to-Peer&#xff0c;P2P&#xff09;的通信&#xff0c;而无需任何插件或第三方软件…

不可思议的转折,这部韩剧在口碑上实现逆袭

今天&#xff0c;推荐一下韩国版的《纸钞屋》&#xff0c;第一季豆瓣从9.4分滑到6.9分。第二季的回归却让这部剧迎来了“翻身仗”&#xff0c;目前豆瓣已飙升至8.4。 对比第一季&#xff0c;第二季不仅在剧情反转和人物刻画上有了明显的提升&#xff0c;还引入了《黑暗荣耀》中…

浅谈Agent智能体

Agent智能体无疑是24年最为火爆的话题之一&#xff0c;那么什么是Agent智能体&#xff1f;有什么作用&#xff1f;为什么需要Agent智能体&#xff1f; 用下边一张图简单说明一下 每日进步一点点

Python制作进度条,18种方式全网最全!(不全去你家扫厕所!)

想象一下&#xff0c;你的程序在执行复杂任务时&#xff0c;不再是冷冰冰的等待光标&#xff0c;而是伴随着色彩斑斓、动态变化的进度条&#xff0c;不仅让等待变得有趣&#xff0c;更让用户对你的作品刮目相看。从基础的文本进度条到高级的图形界面进度条&#xff0c;从简单的…

小程序兼容问题

【微信小程序】安卓兼容问题&#xff0c;scroll-view上拉导致input输入框上移 引用&#xff1a;https://blog.csdn.net/krico233/article/details/127491690 当一个scroll-view占据全屏高度(100vh)并包含input表单时&#xff0c;输入框聚焦会导致光标上移但输入框本身位置不变…

【C语言】数组(上)

【C语言】数组 1、数组的概念2、一维数组的创建和初始化2.1数组创建2.2数组的初始化2.3数组的类型 3、一维数组的使用3.1数组下标3.2 数组元素打印3.3数组的输入 4、一维数组在内存中的存储5、sizeof计算数组元素个数 1、数组的概念 数组是一组相同类型元素的组合&#xff0c;…

【RabbitMQ】面试题

在本篇文章中&#xff0c;主要是介绍RabbitMQ一些常见的面试题。对于前几篇文章的代码&#xff0c;都已经在码云中给出&#xff0c;链接是mq-test: 学习RabbitMQ的一些简单案例 (gitee.com)&#xff0c;如果存在问题的话欢迎各位提出&#xff0c;望共同进步。 MQ的作用以及应用…

快速上手Make Sense:在线标注数据集的强大工具

链接&#xff1a; Makesense汉化版本 Makesense英文版 随着深度学习在计算机视觉领域的广泛应用&#xff0c;数据集标注成为了一项重要的任务。Make Sense正是一个为图像数据集提供标注功能的在线工具。其易用性和强大的功能使得它在众多标注工具中脱颖而出。本文将为你详细介绍…

找不到msvcr100.dll怎么解决?总结6个有效的解决方法

在使用计算机的过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcr100.dll丢失”。这个问题可能会让我们感到困惑和无助&#xff0c;但是不用担心&#xff0c;本文将为大家介绍六种实用的解决方法&#xff0c;帮助你轻松解决这个问题。 一&#xff…

raylib实现生产者消费者模型增加缓冲提高帧率

原来增加了四叉树导致帧率下降 后来学了生产者消费者模型&#xff0c;尝试追加缓冲池&#xff0c;剥离主函数查找需要更新的数据 帧率上升稳定到60帧 多了10 帧 中间工程主要是探索数据结构体怎么安排 // 参考自 https://zhuanlan.zhihu.com/p/693482704 #include <stdio.…

C语言-进程

一,进程的基本认识 1,进程的简介 进程描述是一个程序执行过程。当程序执行后&#xff0c;执行过程开始&#xff0c;则进程产生&#xff1b;执行过程结束&#xff0c;则进程也就结束了.进程和我们普通电费程序最大的区别就是,进程是动态的,他是一个过程,而程序是静态的. 2,进程…