当前位置: 首页 > news >正文

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

基于 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标记的UTF16if (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 此时第一位必须为1if ((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.mrgr.cn/news/37887.html

相关文章:

  • ARM点灯---看手册
  • LLM Agent系列 | 端侧Agent路由器,合纵连横AI江湖,破局端侧大模型之困!
  • LeetCode[中等] 78.子集
  • Vue 3 技术体系
  • 基于Hive和Hadoop的电商消费分析系统
  • Meta震撼发布Llama3.2大规模模型
  • BufferQueue低延迟优化,以及SurfaceView帧率上限问题解决
  • 线性代数~行列式计算
  • 一款开源的通用PDF处理神器,功能强悍!
  • SpringBoot整合JPA实现CRUD详解
  • 【HTML|第1期】HTML5视频(Video)元素详解:从起源到应用
  • 鸿蒙开发(NEXT/API 12)【硬件(接入手写套件)】手写功能开发
  • 算法——冒泡排序
  • 【洛谷】AT_abc178_d [ABC178D] Redistribution 的题解
  • 手搓一个Agent#Datawhale 组队学习Task3
  • 1013. 将数组分成和相等的三个部分 数组切分
  • 物理学基础精解【30】
  • 用十万字解析《微积分(第三版)》
  • 如何注册和使用Disney+?Disney+会员账号可以合租?Disney+会员账号订阅购买使用教程
  • 并发编程---线程与进程