基于 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 标记 | 汉字字节组成 | 以“中文”为例的编码(后回车) |
---|
Unicode | 0xFF,0xFE,非0,非0 | 一个汉字 2 字节,“中文”二字共 4 字节 | 2D 4E 87 65 0D 00 0A 00 |
BigEndianUnicode | 0xFE,0xFF,非0,非0 | 一个汉字 2 字节,“中文”二字共 4 字节 | 4E 2D 65 87 00 0D 00 0A |
UTF32 | 0xFF,0xFE,0,0 | 一个汉字 4 字节,“中文”二字共 8 字节 | 2D 4E 00 00 87 65 00 00 0D 00 0A 00 |
UTF32BE | 0xFE,0xFF,0,0 | 一个汉字 4 字节,“中文”二字共 8 字节 | 4E 2D 00 00 65 87 00 00 00 0D 00 0A |
UTF8 | 0xEF,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 |
三、简体中文汉字编码
中文编码(按新旧顺序) | 代码页 | 以“中文”为例 |
---|
GB18030 | CP54936 | D6 D0 CE C4 |
GBK | CP936 | D6 D0 CE C4 |
GB2312 | CP20936 | D6 D0 CE C4 |
HZ-GB2312 | CP52936 | D6 D0 CE C4 |
BIG5 | CP950 | A4 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 的文件识别
private static Encoding GetEncoding(string file_name){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){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)){return Encoding.Unicode;}else if (bytes[0] == 0xFE && bytes[1] == 0xFF && (bytes[2] != 0 || bytes[3] != 0)){return Encoding.BigEndianUnicode;}else if (bytes[0] == 0xFF && bytes[1] == 0xFE && bytes[2] == 0 && bytes[3] == 0){return Encoding.UTF32;}else if (bytes[0] == 0x00 && bytes[1] == 0x00 && bytes[2] == 0xFE && bytes[3] == 0xFF){return Encoding.GetEncoding("utf-32BE");}else if (bytes[0] == 0xEF && bytes[1] == 0xBB && (bytes[2] == 0xBF)){return Encoding.UTF8;}else{Encoding encoding = CheckUtf16Ascii(bytes, bytes.Length);if (IsUTF8Bytes(bytes)){if (encoding == null){if (IsOnlyAscii(bytes)){return Encoding.ASCII;}else{return Encoding.UTF8; }}else{return encoding;}}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;}}else{return encoding;}}}}
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++;}if (charByteCounter == 1 || charByteCounter > 6){return false;}}}else{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;}size--;const double threshold = 0.5; 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;}return true;}private static bool IsGBK(string input){var regex = new Regex(@"[\u4E00-\u9FA5]"); return regex.IsMatch(input);}private static bool IsGB2312(string input){var regex = new Regex(@"[\uB0A1-\uF7FE\u8140-\uA4D0]"); return regex.IsMatch(input);}private static bool IsGB18030(string input){var regex = new Regex(@"[\u4E00-\u9FA5\uE7C7-\uE7F3]");return regex.IsMatch(input);}
五、程序通过验证

六、源代码下载
https://download.csdn.net/download/zyyujq/89805828