.net版本

using System;
using System.IO;
using System.Text; namespace G2.Common
{
/// <summary>
/// 用于取得一个文本文件的编码方式(Encoding)。
/// </summary>
public static class TextEncodingHelper
{
/// <summary>
/// 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符,Encoding.Default将被返回。
/// 文件的字符集在Windows下有两种,一种是ANSI,一种Unicode。
/// 对于Unicode,Windows支持了它的三种编码方式,一种是小尾编码(Unicode),一种是大尾编码(BigEndianUnicode),一种是UTF-8编码。
/// 我们可以从文件的头部来区分一个文件是属于哪种编码。当头部开始的两个字节为 FF FE时,是Unicode的小尾编码;当头部的两个字节为FE FF时,是Unicode的大尾编码;当头部两个字节为EF BB时,是Unicode的UTF-8编码;当它不为这些时,则是ANSI编码。
/// 按照如上所说,我们可以通过读取文件头的两个字节来判断文件的编码格式
/// </summary>
/// <param name="filename">文件名。</param>
/// <returns></returns>
public static System.Text.Encoding GetFileEncoding(this string filename)
{
if (!File.Exists(filename))
{
throw new Exception("文件"" + filename + ""不存在!");
} using (var fs = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (var br = new System.IO.BinaryReader(fs))
{
var buffer = br.ReadBytes();
if (buffer[] >= 0xEF)
{
if (buffer[] == 0xEF && buffer[] == 0xBB)
{
return System.Text.Encoding.UTF8;
} if (buffer[] == 0xFE && buffer[] == 0xFF)
{
return System.Text.Encoding.BigEndianUnicode;
} if (buffer[] == 0xFF && buffer[] == 0xFE)
{
return System.Text.Encoding.Unicode;
}
} return GetEncodingWithBomUtf8(fs, System.Text.Encoding.Default);
}
} /// <summary>
/// 通过给定的文件流,判断文件的编码类型 (解决了不带BOM的 UTF8 编码问题 )
/// </summary>
/// <param name="fs">文件流</param>
/// <param name="defaultEncoding">默认编码</param>
/// <returns>文件的编码类型</returns>
private static System.Text.Encoding GetEncodingWithBomUtf8(Stream fs, Encoding defaultEncoding)
{
byte[] unicode = new byte[] { 0xFF, 0xFE, 0x41 };
byte[] unicodeBig = new byte[] { 0xFE, 0xFF, 0x00 }; //带BOM
byte[] utf8 = new byte[] { 0xEF, 0xBB, 0xBF };
var reVal = defaultEncoding; using (var r = new System.IO.BinaryReader(fs))
{
byte[] ss = r.ReadBytes();
if (ss[] == 0xFE && ss[] == 0xFF && ss[] == 0x00)
{
reVal = Encoding.BigEndianUnicode;
}
else if (ss[] == 0xFF && ss[] == 0xFE && ss[] == 0x41)
{
reVal = Encoding.Unicode;
}
else
{
if (ss[] == 0xEF && ss[] == 0xBB && ss[] == 0xBF)
{
reVal = Encoding.UTF8;
}
else
{
int i;
int.TryParse(fs.Length.ToString(), out i);
ss = r.ReadBytes(i); if (IsUtf8Bytes(ss))
{
reVal = Encoding.UTF8;
}
}
} return reVal;
}
} /// <summary>
/// 判断是否是不带 BOM 的 UTF8 格式
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private static bool IsUtf8Bytes(byte[] data)
{
int charByteCounter = ;  //计算当前正分析的字符应还有的字节数
for (int i = ; i < data.Length; i++)
{
var curByte = data[i]; //当前分析的字节.
if (charByteCounter == )
{
if (curByte >= 0x80)
{
//判断当前
while (((curByte <<= ) & 0x80) != )
{
charByteCounter++;
}
//标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X 
if (charByteCounter == || charByteCounter > )
{
return false;
}
}
}
else
{
//若是UTF-8 此时第一位必须为1
if ((curByte & 0xC0) != 0x80)
{
return false;
}
charByteCounter--;
}
}
if (charByteCounter > )
{
throw new Exception("非预期的byte格式!");
}
return true;
}
}
}

java版本

import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.BitSet; public class EncodeUtils {
private static final Logger logger = LoggerFactory.getLogger(EncodeUtils.class);
private static final int BYTE_SIZE = 8;
private static final String CODE_UTF8 = "UTF-8";
private static final String CODE_UTF16 = "UTF-16";//Unicode
private static final String CODE_UTF16LE = "UTF-16LE";//Unicode big endian
private static final String CODE_GBK = "GBK"; //ABSU /**
* 通过文件全名称获取编码集名称
*/
public static String getEncode(String fullFileName) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fullFileName));
return getEncode(bis, CODE_GBK);
} /**
* 通过文件全名称获取编码集名称
*/
public static String getEncode(String fullFileName, String defaultEncoding) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fullFileName));
return getEncode(bis, defaultEncoding);
} /**
* 通过文件缓存流获取编码集名称,文件流必须为未曾
*
* @param bis 文件流
*/
public static String getEncode(BufferedInputStream bis, String defaultEncoding) throws Exception {
bis.mark(0);
String encodeType;
byte[] head = new byte[3];
bis.read(head);
if (head[0] == -1 && head[1] == -2 && head[2] == (byte) 0x41) {
encodeType = CODE_UTF16;
} else if (head[0] == -2 && head[1] == -1 && head[2] == 0) {
//encodeType = "Unicode";
encodeType = CODE_UTF16LE;
} else if (head[0] == -17 && head[1] == -69 && head[2] == -65) {
//带BOM的UTF8 (CODE_UTF8_BOM)
encodeType = CODE_UTF8;
} else {
if (isUTF8(bis)) {
encodeType = CODE_UTF8;
} else {
encodeType = defaultEncoding;
}
} return encodeType;
} /**
* 是否是无BOM的UTF8格式,不判断常规场景,只区分无BOM UTF8和GBK
*/
private static boolean isUTF8(BufferedInputStream bis) throws Exception {
bis.reset(); //读取第一个字节
int code = bis.read();
do {
BitSet bitSet = convert2BitSet(code);
//判断是否为单字节
if (bitSet.get(0)) {//多字节时,再读取N个字节
if (!checkMultiByte(bis, bitSet)) {//未检测通过,直接返回
return false;
}
}
code = bis.read();
} while (code != -1);
return true;
} /**
* 检测多字节,判断是否为utf8,已经读取了一个字节
*/
private static boolean checkMultiByte(BufferedInputStream bis, BitSet bitSet) throws Exception {
int count = getCountOfSequential(bitSet);
byte[] bytes = new byte[count - 1];//已经读取了一个字节,不能再读取
bis.read(bytes);
for (byte b : bytes) {
if (!checkUtf8Byte(b)) {
return false;
}
}
return true;
} /**
* 检测bitSet中从开始有多少个连续的1
*/
private static int getCountOfSequential(BitSet bitSet) {
int count = 0;
for (int i = 0; i < BYTE_SIZE; i++) {
if (bitSet.get(i)) {
count++;
} else {
break;
}
}
return count;
} /**
* 检测单字节,判断是否为utf8
*/
private static boolean checkUtf8Byte(byte b) throws Exception {
BitSet bitSet = convert2BitSet(b);
return bitSet.get(0) && !bitSet.get(1);
} /**
* 将整形转为BitSet
*/
private static BitSet convert2BitSet(int code) {
BitSet bitSet = new BitSet(BYTE_SIZE); for (int i = 0; i < BYTE_SIZE; i++) {
int tmp3 = code >> (BYTE_SIZE - i - 1);
int tmp2 = 0x1 & tmp3;
if (tmp2 == 1) {
bitSet.set(i);
}
}
return bitSet;
} public static void main(String[] args) {
String filePath = "C:\\110025.txt";
try {
String encoding = getEncode(filePath);
System.out.println(encoding);
} catch (Exception ex) {
logger.warn("文件检测编码出错!", ex);
}
}
}

自动判断文本文件编码来读取文本文件内容(.net版本和java版本)的更多相关文章

  1. [转发]读取txt防止读到乱码--自动根据文件编码进行读取

    以下是摘抄 /// <summary> /// 获取文件的编码格式 /// </summary> public class EncodingType { /// <sum ...

  2. web前端读取文本文件内容

    html5+js实现,参照xxyy888的CSDN博客文章<使用HTML+javascrpt读取txt文本文件>失败,将作者文章中的代码重新整理了下依然不行,文章代码存在的问题是括号错误, ...

  3. java读取文本文件内容2

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/183 很久之前写了一篇Java读取文本文件内容,链接地址是 ...

  4. java读取文本文件内容

    版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/128 java读取文本文件内容 今天写代码写着要调试一个很 ...

  5. php -- 读取文本文件内容

    php读取文件内容的三种方法:    //**************第一种读取方式*****************************  代码如下: header("content- ...

  6. MATLAB对于文本文件(txt)数据读取的技巧总结(经典中的经典)

    振动论坛原版主eight的经典贴http://www.chinavib.com/thread-45622-1-1.html MATLAB对于文本文件(txt)进行数据读取的技巧总结(经典中的经典)由于 ...

  7. python读取文本文件

    1. 读取文本文件 代码: f = open('test.txt', 'r') print f.read() f.seek(0) print f.read(14) f.seek(0) print f. ...

  8. 获取文本文件的第N行内容

    在PowerShell中,可以通过Get-Content这个cmdlet来获取文本文件的内容.Get-Content将一个文本文件读取到一个数组中,每一个数组元素就是文件的一行内容.比如一个文本文件内 ...

  9. (转) Java读取文本文件中文乱码问题

    http://blog.csdn.net/greenqingqingws/article/details/7395213 最近遇到一个问题,Java读取文本文件(例如csv文件.txt文件等),遇到中 ...

随机推荐

  1. 【转载】Python BeautifulSoup匹配字符串

    作者:鸡仔说链接:https://www.jianshu.com/p/ceb99aed4b2e來源:简书 BeautifulSoup中可以通过name和attrs去定位名称和属性,以找到特定的html ...

  2. 编写高质量代码改善C#程序的157个建议——建议41:实现标准的事件模型

    建议41:实现标准的事件模型 上一建议中,我们实现了一个带事件通知的文件传输类FileUploader.虽然已经满足需求,但却不符合C#的编码规范,查看EventHandler的原型声明: publi ...

  3. web开发四个作用域

    web开发一共有四个作用域,范围从高到低分为appliaction作用域(全局作用域),session作用域,request作用域和page作用域.${base}是el表达式语法,它会自动先从page ...

  4. 团队项目第六周-Alpha阶段项目复审(深海划水队)

    经小组讨论后得出以下排名: 队名 优点 缺点 排名 大猪蹄子队 界面优美,功能简洁易懂,单词解释较为完善 互动方式.操作简易性有待优化,有部分功能尚未完成 1 Running Duck队 基本功能已经 ...

  5. EBS取Web字段SQL操作文档

    1)  安全性—>责任-à定义 在这个路径下,输入责任名称,可以查询这个责任的请求组的名称 2)  organization_id 和 org_id的功能 3)  查找网页上的字段 Naviga ...

  6. Boost 安装详解

    一 Linux(redhat)篇 1.1 获取boost库 解压tar -zxvf boost_1.48.0.tar.gz 进入解压目录cd boost_1_48_0 1.2 编译安装 使用下面的命令 ...

  7. 标准库函数begin和end------c++primer

    尽管能计算得到尾后指针,但这种用法极易出错.为了让指针的使用更简单.更安全,c++新标准引入了两个名为begin和end的函数.这两个函数与容器中的两个同名成员功能类似,不过数组毕竟不是类类型,因此这 ...

  8. 《C#多线程编程实战》2.6 ManualResetEventSlim

    这个比较好理解的. 正如书上所言,如同一直在打开的大门的屋子,谁要进去,谁就自己的关门,出来的时候在开开. 常用的方法 有三个: Set()  //设置为有信号,也就是让等待的线程不用继续等待,唤醒等 ...

  9. C#委托笔记

    参考: 第一篇:http://www.tracefact.net/tech/009.html 第二篇:http://www.tracefact.net/tech/029.html 1.委托相当于一种参 ...

  10. luoguP3648 [APIO2014]序列分割

    https://www.luogu.org/problemnew/show/P3648 同bzoj3675 这题斜率优化+滚动数组就可以了qwq 因为我是在飞机上瞎bb的式子,所以可能会和别的题解的式 ...