C#猜测识别文件编码
项目 gitee地址:https://gitee.com/dhclly/IceDog.SmallProject/tree/master/src/IceDog.SmallProject.CodeConvert
C#猜测识别文件编码
测试句子: This is a good time. 这是个好时光。
除了 ascii 只有英文,其他都是中英文都有
主要判断的编码有
- ascii
- gb18030
- gb2312
- gbk
- utf8
- utf8WithBOM
- Unicode utf16 LE
- Unicode Big Endian utf16 BE
其中ANSI是默认的编码方式,对于英文文件是ASCII编码,
对于简体中文文件默认是GB2312编码(只针对Windows简体中文版,如果是繁体中文版默认会采用Big5码)
Unicode其实是UTF-16 endian big编码方式,这个把带有BOM的小端序UTF-16
称作Unicode而又不详细说明,也是微软的习惯;
而Unicode big endian则是带有BOM的大端序编码方式
EF BB BF 239 187 191 UTF-8
FE FF 254 255 UTF-16 BE (big-endian)
FF FE 255 254 UTF-16 LE (little-endian)
00 00 FE FF 00 00 254 255 UTF-32 BE (big-endian)
FF FE 00 00 255 254 00 00 UTF-32 LE (little-endian)
需要引入 NuGet :System.Text.Encoding.CodePages
UTF-8是一种变长字节编码方式。对于某一个字符的UTF-8编码,
如果只有一个字节则其最高二进制位为0;如果是多字节,
其第一个字节从最高位开始,连续的二进制位值为1的
个数决定了其编码的位数,其余各字节均以10开头。
UTF-8最多可用到6个字节。
- 1字节:0xxxxxxx
- 2字节:110xxxxx 10xxxxxx
- 3字节:1110xxxx 10xxxxxx 10xxxxxx
- 4字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- 0000 0000 0x00
- 1000 0000 0x80
- 1100 0000 0xC0
- 1110 0000 0xE0
- 1111 0000 0xF0
- 1111 1000 0xF8
- 1111 1100 0xFC
- 1111 1101 0xFD
参考文章
- 如何判断一个文本文件内容的编码格式 UTF-8 ? ANSI(GBK) https://www.cnblogs.com/fnlingnzb-learner/p/5832486.html
- 如何判断一个文本文件内容的编码格式 UTF-8 ? ANSI(GBK)https://blog.csdn.net/jiangqin115/article/details/42684017
- 如何判断一个文本文件的编码 https://www.cnblogs.com/lkpp/p/encoding_detection.html
- RFC 2279 https://www.ietf.org/rfc/rfc2279.txt?number=2279
- A composite approach to language/encoding detection https://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html
- 判断中文文本编码格式是gbk还是utf-8的一种简单方式 https://blog.csdn.net/capricio/article/details/83023828
- 编码转换查询:http://www.mytju.com/classcode/tools/encode_utf8.asp
- UTF-8编码规则(转) https://www.cnblogs.com/ziolo/p/3822454.html
- https://segmentfault.com/a/1190000000498924#articleHeader8
源码
也可以直接去gitee去看代码
TextCodeGuessHelper.cs
/*
* 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符,Encoding.Default将被返回。
* 文件的字符集在Windows下有两种,一种是ANSI,一种Unicode。
* 对于Unicode,Windows支持了它的三种编码方式,小尾编码(Unicode),大尾编码(BigEndianUnicode),UTF-8编码。
* 我们可以从文件的头部来区分一个文件是属于哪种编码。
* 当头部开始的两个字节为 FF FE时,是Unicode的小尾编码;
* 当头部的两个字节为FE FF时,是Unicode的大尾编码;
* 当头部两个字节为EF BB BF时,是Unicode的UTF-8编码;
* 当它不为这些时,则是ANSI(中文是GBK系列)编码。
*/
using System;
using System.IO;
using System.Text;
namespace IceDog.SmallProject.CodeConvert
{
/// <summary>
/// 文本编码猜测帮助器
/// <para>在调用其他方法前,先调用TextCodeGuessHelper.RegisterMoreEncoding()</para>
/// </summary>
public static class TextCodeGuessHelper
{
static TextCodeGuessHelper()
{
}
/// <summary>
/// 注册更多的编码类型类型
/// </summary>
/// <remarks>
/// <para>需要引入 NuGet包:System.Text.Encoding.CodePages</para>
/// <para>调用下面的编码类型需要先调用此方法</para>
/// <para>详情链接:https://docs.microsoft.com/zh-cn/dotnet/api/system.text.encoding.registerprovider?redirectedfrom=MSDN&view=netframework-4.8#System_Text_Encoding_RegisterProvider_System_Text_EncodingProvider_</para>
/// </remarks>
public static void RegisterMoreEncoding()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
public static Encoding UTF8 => Encoding.UTF8;
public static Encoding Unicode => Encoding.Unicode;
public static Encoding BigEndianUnicode => Encoding.BigEndianUnicode;
public static Encoding ASCII => Encoding.ASCII;
public static Encoding UTF16BE => Encoding.BigEndianUnicode;
public static Encoding UTF16LE => Encoding.Unicode;
public static Encoding GB2312 => Encoding.GetEncoding("GB2312");
public static Encoding GBK => Encoding.GetEncoding("GBK");
public static Encoding GB18030 => Encoding.GetEncoding("GB18030");
/// <summary>
/// 获取编码
/// </summary>
/// <param name="name">编码名称,如(UTF-8)</param>
/// <returns></returns>
public static Encoding GetEncoding(string name) => Encoding.GetEncoding(name);
public static Encoding GuessFileEncoding(string filename)
{
if (!File.Exists(filename))
{
throw new Exception("文件 " + filename + " 不存在!");
}
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
return GuessStreamEncoding(fs);
}
}
public static Encoding GuessStreamEncoding(Stream stream)
{
if (!stream.CanRead)
{
return null;
}
using (var br = new BinaryReader(stream))
{
var buffer = br.ReadBytes(3);
if (buffer[0] == 0xFE && buffer[1] == 0xFF)//FE FF 254 255 UTF-16 BE (big-endian)
{
return Encoding.BigEndianUnicode;
}
if (buffer[0] == 0xFF && buffer[1] == 0xFE)//FF FE 255 254 UTF-16 LE (little-endian)
{
return Encoding.Unicode;
}
if (buffer[0] == 0xEF && buffer[1] == 0xBB & buffer[2] == 0xBF)//EF BB BF 239 187 191 UTF-8
{
return Encoding.UTF8;//with BOM
}
if (IsUtf8WithoutBom(stream))
{
return Encoding.UTF8;//without BOM
}
if (IsPlainASCII(stream))
{
return Encoding.ASCII; //默认返回ascii编码
}
return GBK;
}
}
public static bool IsPlainASCII(string path)
{
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
return IsPlainASCII(fs);
}
}
private static bool IsPlainASCII(Stream stream)
{
bool isAllASCII = true;
long totalLength = stream.Length;
stream.Seek(0, SeekOrigin.Begin);//重置 position 位置
using (var br = new BinaryReader(stream, Encoding.Default, true))
{
for (long i = 0; i < totalLength; i++)
{
byte b = br.ReadByte();
/*
* 原理是
* 0x80 1000 0000
* &
* 0x75 (p) 0111 0101
* ASCII字符都比128小,与运算自然都是0
*/
if ((b & 0x80) != 0)// (1000 0000): 值小于0x80的为ASCII字符
{
isAllASCII = false;
break;
}
}
}
return isAllASCII;
}
/// <summary>
/// 通过给定的文件流,判断文件的编码类型
/// </summary>
/// <param name="fs">文件流</param>
/// <param name="defaultEncoding">默认编码</param>
/// <returns>文件的编码类型</returns>
private static bool IsUtf8WithoutBom(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);//重置 position 位置
bool isAllASCII = true;
long totalLength = stream.Length;
long nBytes = 0;
using (var br = new BinaryReader(stream, Encoding.Default, true))
{
for (long i = 0; i < totalLength; i++)
{
byte b = br.ReadByte();
// (1000 0000): 值小于0x80的为ASCII字符
// 等同于 if(b < 0x80 )
if ((b & 0x80) != 0) //0x80 128
{
isAllASCII = false;
}
if (nBytes == 0)
{
if (b >= 0x80)
{
if (b >= 0xFC && b <= 0xFD) { nBytes = 6; }//此范围内为6字节UTF-8字符
else if (b >= 0xF8) { nBytes = 5; }// 此范围内为5字节UTF-8字符
else if (b >= 0xF0) { nBytes = 4; }// 此范围内为4字节UTF-8字符
else if (b >= 0xE0) { nBytes = 3; }// 此范围内为3字节UTF-8字符
else if (b >= 0xC0) { nBytes = 2; }// 此范围内为2字节UTF-8字符
else { return false; }
nBytes--;
}
}
else
{
if ((b & 0xC0) != 0x80) { return false; }//0xc0 192 (11000000): 值介于0x80与0xC0之间的为无效UTF-8字符
nBytes--;
}
}
}
if (nBytes > 0)
{
return false;
}
if (isAllASCII)
{
return false;
}
return true;
}
public static string ReadFile(string path, Encoding encoding)
{
using (StreamReader sr = new StreamReader(path, encoding, true))
{
return sr.ReadToEnd();
}
}
public static string ReadStream(Stream stream, Encoding encoding)
{
if (!stream.CanRead)
{
return null;
}
using (StreamReader sr = new StreamReader(stream, encoding, true))
{
return sr.ReadToEnd();
}
}
/// <summary>
/// 很巧妙的判断方式
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
/// <remarks>参考:https://blog.csdn.net/capricio/article/details/83023828</remarks>
public static Encoding IsGBKOrUTF8(string fileName)
{
var utf8Str = ReadFile(fileName, UTF8);
var gbkStr = ReadFile(fileName, GBK);
return utf8Str.Length <= gbkStr.Length ? UTF8 : GBK;
}
}
}
C#猜测识别文件编码的更多相关文章
- [转] linux下查看文件编码及修改编码
如果无法识别文件编码,可能是文件中已有乱码,此时需要去掉乱码 查看文件编码 在Linux中查看文件编码可以通过以下几种方式: 1.在Vim中可以直接查看文件编码 :set fileencoding 即 ...
- [译]如何定义python源文件的文件编码
简介 这篇文章是为了介绍定义python源文件文件编码的方法.python解释器可以根据所指定的编码信息对当前文件进行解析.通常来说,这种方法可以提高解析器对Unicode编码的源文件的识别,并且支持 ...
- Java与网页JSP文件编码的小总结
感谢大佬: https://www.cnblogs.com/yangguoe/p/8467672.html(编码发展史) https://blog.csdn.net/seabiscuityj/arti ...
- 转 :Vim文件编码识别与乱码处理
Vim文件编码识别与乱码处理 在 Vim 中,有四个与编码有关的选项,它们是:fileencodings.fileencoding.encoding 和 termencoding.在实际使用中,任 ...
- 修改VISUAL STUDIO EXPRESS 2012新建C++文件编码
本站文章除注明转载外,均为本站原创或者翻译. 本站文章欢迎各种形式的转载,但请18岁以上的转载者注明文章出处,尊重我的劳动,也尊重你的智商: 本站部分原创和翻译文章提供markdown格式源码,欢迎使 ...
- Linux查看文件编码格式及文件编码转换
Linux查看文件编码格式及文件编码转换 如果你需要在Linux 中操作windows下的文件,那么你可能会经常遇到文件编码转换的问题.Windows中默认的文件格式是GBK(gb2312),而L ...
- 【转】关于Python脚本开头两行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用 – 指定文件编码类型
原文网址:http://www.crifan.com/python_head_meaning_for_usr_bin_python_coding_utf-8/ #!/usr/bin/python 是用 ...
- linux下查看文件编码及修改编码
http://blog.csdn.net/jnbbwyth/article/details/6991425 查看文件编码在Linux中查看文件编码可以通过以下几种方式:1.在Vim中可以直接查看文件编 ...
- 【转载】关于Python脚本开头两行的:#!/usr/bin/python和# -*- coding: utf-8 -*-的作用 – 指定文件编码类型
1.#!/usr/bin/python 是用来说明脚本语言是 python 的 是要用 /usr/bin下面的程序(工具)python,这个解释器,来解释 python 脚本,来运行 python 脚 ...
随机推荐
- github上星星1万多的python教程推荐收藏
简单的说,Python是一个“优雅”.“明确”.“简单”的编程语言. 学习曲线低,非专业人士也能上手 开源系统,拥有强大的生态圈 解释型语言,完美的平台可移植性 支持面向对象和函数式编程 能够通过调用 ...
- rxJava2.x源码解析
一. Rxjava是什么 Rxjava在GitHub的介绍是 "A library for composing asynchronous and event-based programs u ...
- 前端之javascript1
js介绍和js引入页面 学习前端脚本语言javascript的基本概念.页面引入方式.获取页面元素及操作元素属性的技巧,学习函数的基本定义方法和使用方法. JavaScript介绍 JavaScrip ...
- c# Winform 加载窗体
先来一个加载窗体代码 public partial class FrmLoading : Form { public BackgroundWorker updateDBWorker=new Backg ...
- 为什么要学 Python? python该怎么学
很多童鞋对为什么学习Python感到迷茫,小编来跟大家说说学习Python的10个理由,希望可以帮助到大家!!! 摘要: 看完这十个理由,我决定买本python从入门到精通! 如果你定期关注现今的科技 ...
- C# vs2017创建Com组件,并注册
1.创建一个普通类库dll项目,如:MyCom. 2.导出接口,添加Guid,Guid为全局唯一标识,可以用VS2017自带工具获取.获取Guid的方法,如图: (1)打开自带Guid工具. (2)首 ...
- mysql-python 安装错误 fatal error C1083: Cannot open include file: 'config-win.h': No such file or directory
安装mysql-python之前, 请先安装setuptools. https://pypi.python.org/pypi/setuptools/7.0 下载mysql-python. 下载源码包. ...
- Python—序列化和反序列化模块(json、pickle和shelve)
什么是序列化 我们把对象(或者变量)从内存中变为可存储或者可传输的过程称为序列化.在python中为pickling,在其他语言中也被称之为serialization,marshalling,flat ...
- Shell脚本(1)
在创建Shell脚本时,必须在文件的第一行指定要使用的shell.格式为:#!/bin/bash 除了第一行外,在shell脚本中井号(#)用作注释行 若出现错误:command not found ...
- 【cf1111】C. Creative Snap (dfs+dp)
传送门 简单的dfs+dp即可解决.根本不用动态开点 /* * Author: heyuhhh * Created Time: 2019/11/13 10:12:42 */ #include < ...