转自:http://blog.csdn.net/jiangqin115/article/details/42684017

UTF-8编码的文本文档,有的带有BOM (Byte Order Mark, 字节序标志),即0xEF, 0xBB, 0xBF,有的没有。Windows下的txt文本编辑器在保存UTF-8格式的文本文档时会自动添加BOM到文件头。在判断这类文档时,可以根据文档的前3个字节来进行判断。然而BOM不是必需的,而且也不是推荐的。对不希望UTF-8文档带有BOM的程序会带来兼容性问题,例如Java编译器在编译带有BOM的UTF-8源文件时就会出错。而且BOM去掉了UTF-8一个期望的特性,即是在文本全部是ASCII字符时UTF-8是和ASCII一致的,即UTF-8向下兼容ASCII。

在具体判断时,如果文档不带有BOM,就无法根据BOM做出判断,而且IsTextUnicode API也无法对UTF-8编码的Unicode字符串做出判断。那在编程判断时就要根据UTF-8字符编码的规律进行判断了。

UTF-8是一种多字节编码的字符集,表示一个Unicode字符时,它可以是1个至多个字节,在表示上有规律:

1字节:0xxxxxxx
2字节:110xxxxx 10xxxxxx
3字节:1110xxxx 10xxxxxx 10xxxxxx
4字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

这样就可以根据上面的特征对字符串进行遍历来判断一个字符串是不是UTF-8编码了。应该指出的是UTF-8字符串的各个字节的取值有一定的范围,并不是所有的值都是有效的UTF-8字符,但是一般的应用的情况下这样的判断在对足够长的字符串及是比较精确了,而且实现也比较简单。具体的字节取值范围可以参见"Unicode Explained"一书中的6.4.3。另外BOM本身也符合3字节UTF-8字符编码规律,所以本方法对带BOM的UTF-8字符串也是有效的。

1. 判断文本是否UTF编码

在下面程序中对最大3字节长的UTF-8字符进行了判断,在实际情况下,几乎所有能用到的UTF-8字符最长就是3个字节

  1. bool IsUTF8(const void* pBuffer, long size)
  2. {
  3. bool IsUTF8 = true;
  4. unsigned char* start = (unsigned char*)pBuffer;
  5. unsigned char* end = (unsigned char*)pBuffer + size;
  6. while (start < end)
  7. {
  8. if (*start < 0x80) // (10000000): 值小于0x80的为ASCII字符
  9. {
  10. start++;
  11. }
  12. else if (*start < (0xC0)) // (11000000): 值介于0x80与0xC0之间的为无效UTF-8字符
  13. {
  14. IsUTF8 = false;
  15. break;
  16. }
  17. else if (*start < (0xE0)) // (11100000): 此范围内为2字节UTF-8字符
  18. {
  19. if (start >= end - )
  20. {
  21. break;
  22. }
  23.  
  24. if ((start[] & (0xC0)) != 0x80)
  25. {
  26. IsUTF8 = false;
  27. break;
  28. }
  29.  
  30. start += ;
  31. }
  32. else if (*start < (0xF0)) // (11110000): 此范围内为3字节UTF-8字符
  33. {
  34. if (start >= end - )
  35. {
  36. break;
  37. }
  38.  
  39. if ((start[] & (0xC0)) != 0x80 || (start[] & (0xC0)) != 0x80)
  40. {
  41. IsUTF8 = false;
  42. break;
  43. }
  44.  
  45. start += ;
  46. }
  47. else
  48. {
  49. IsUTF8 = false;
  50. break;
  51. }
  52. }
  53.  
  54. return IsUTF8;
  55. }

2. 判断文件是否UTF-8编码:

  1. bool CConvertCharset::IsUTF8File(const char* pFileName)
  2. {
  3. FILE *f = NULL;
  4. fopen_s(&f, pFileName, "rb");
  5. if (NULL == f)
  6. {
  7. return false;
  8. }
  9.  
  10. fseek(f, , SEEK_END);
  11. long lSize = ftell(f);
  12. fseek(f, , SEEK_SET); //或rewind(f);
  13.  
  14. char *pBuff = new char[lSize + ];
  15. memset(pBuff, , lSize + );
  16. fread(pBuff, lSize, , f);
  17. fclose(f);
  18.  
  19. bool bIsUTF8 = IsUTF8Text(pBuff, lSize);
  20. delete []pBuff;
  21. pBuff = NULL;
  22.  
  23. return bIsUTF8;
  24. }

如何判断一个文本文件内容的编码格式 UTF-8 ? ANSI(GBK)的更多相关文章

  1. C# 判断一个文本文件的编码格式(转载)

    文件的字符集在Windows下有两种,一种是ANSI,一种Unicode.对于Unicode,Windows支持了它的三种编码方式,一种是小尾编码(Unicode),一种是大尾编码(BigEndian ...

  2. 自动判断文本文件编码来读取文本文件内容(.net版本和java版本)

    .net版本 using System; using System.IO; using System.Text; namespace G2.Common { /// <summary> / ...

  3. [No000040]取得一个文本文件的编码方式

    using System; using System.IO; using System.Text; /// <summary> /// 用于取得一个文本文件的编码方式(Encoding). ...

  4. c c++怎么判断一个字符串中是否含有汉字

    c c++怎么判断一个字符串中是否含有汉字 (2013-02-05 10:44:23) 转载▼     #include  #include  int main() { char sztext[] = ...

  5. 如何用一个语句判断一个整数是不是二的整数次幂——从一道简单的面试题浅谈C语言的类型提升(type promotion)

    最近招聘季,看JULY大哥的面试100题时,碰到这么一个扩展问题: 如何用一个语句判断一个整数是不是二的整数次幂?(此题在编程之美也有) easy, 2的整数次幂的二进制形式只有一个1,只要用i和i- ...

  6. Java基础---Java---IO流-----File 类、递归、删除一个带内容的目录、列出指定目录下文件夹、FilenameFilte

    File 类 用来将文件或者文件夹封装成对象 方便对文件与文件夹进行操作. File对象可以作为参数传递给流的构造函数 流只用操作数据,而封装数据的文件只能用File类 File类常见方法: 1.创建 ...

  7. Java判断一个字符是否是数字的几种方法的代码

    在工作期间,将写内容过程经常用到的一些内容段做个记录,下面内容是关于Java判断一个字符是否是数字的几种方法的内容,希望能对码农们有好处. public class Test{ public stat ...

  8. VBA 判断一个TXT编码方式,再创建一个新的文件,复制数据进去

    如题,先读取一个文本文件判断编码(Unicode  ANSI),就这两种编码然后将txt导入到excel表中,最后处理完成,再创建一个相同编码,不同文件名的txt文件,把新数据放进去 Sub test ...

  9. linux下sort命令使用详解---linux将文本文件内容加以排序命令

    转载自:http://www.cnblogs.com/hitwtx/archive/2011/12/03/2274592.html linux下sort命令使用详解---linux将文本文件内容加以排 ...

随机推荐

  1. Python之路【第十一篇】: 进程与线程理论篇

    阅读目录 一 背景知识二 进程2.1 什么是进程2.2 进程与程序的区别2.3 并发与并行2.4 同步与异步2.5 进程的创建2.6 进程的终止2.7 进程的层次结构2.8 进程的状态2.9 进程并发 ...

  2. Windows 中打开 shell

    按住 Shift,单机鼠标右键"在当前目录打开命令窗口"

  3. MDP中值函数的求解

    MDP概述   马尔科夫决策过程(Markov Decision Process)是强化学习(reinforcement learning)最基本的模型框架.它对序列化的决策过程做了很多限制.比如状态 ...

  4. C# 操作 access 数据库

    随笔: (1)   命名空间 using System.Data.OleDb; (2)   连接字符串 private staticstring connStr = @"Provider= ...

  5. iOS 9应用开发教程之编辑界面与编写代码

    iOS 9应用开发教程之编辑界面与编写代码 编辑界面 在1.2.2小节中提到过编辑界面(Interface builder),编辑界面是用来设计用户界面的,单击打开Main.storyboard文件就 ...

  6. PreEssentials与MFC集成使用

    ProEssentials是Gigasoft公司开发的一个功能十分强大的分发免费的工控图表.它提供了几乎所有的曲线显示形式,支持多种开发工具,提供以下接口供开发者调用:.NET(WinForm).AS ...

  7. PHP获取目录和文件的方法

    PHP获取当前目录和相对目录的方法<?php //获取当前文件所在目录,如果 A.php include B.php 则无论写在哪个文件里,都是表示 A.php 文件所在的目录 echo rea ...

  8. python编程之socket编程基础

    python socket编程,首先需要import   socket模块 首先创建一个socket对象 expl = socket.socket(socket.AF_INET,socket.SOCK ...

  9. hihocoder #1301 : 筑地市场 二分+数位dp

    #1301 : 筑地市场 题目连接: http://hihocoder.com/problemset/problem/1301 Description 筑地市场是位于日本东京都中央区筑地的公营批发市场 ...

  10. Spring_Spring集成Quartz定时任务框架介绍和Cron表达式详解

    在JavaEE系统中,我们会经常用到定时任务,比如每天凌晨生成前天报表,每一小时生成汇总数据等等.我们可以使用java.util.Timer结合java.util.TimerTask来完成这项工作,但 ...