介绍UTF-8编码规则

  1. UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长. Bigendian UCS-4 字节串的排列顺序是预定的.
  2. 字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到.
  3. 下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号.
  4. U-00000000 - U-0000007F: 0xxxxxxx
  5. U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
  6. U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
  7. U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  8. U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  9. U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  10. xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.
  11. 例如: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为:
  12. 11000010 10101001 = 0xC2 0xA9
  13. 而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为:
  14. 11100010 10001001 10100000 = 0xE2 0x89 0xA0
  15. 特殊规则: 文件头三个字节用16进制表示是EFBBBF, 此规则不通用, 由编辑工具定义.
  16. 这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 UCS Transformation Format. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身.

复制代码

源码实现:

  1. package com.yy.game.test;
  2. import java.io.BufferedInputStream;
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.nio.CharBuffer;
  8. import java.nio.MappedByteBuffer;
  9. import java.nio.channels.FileChannel;
  10. import java.nio.channels.FileChannel.MapMode;
  11. import java.nio.charset.Charset;
  12. import java.nio.charset.CharsetDecoder;
  13. import java.nio.charset.CoderResult;
  14. public class UTF8Checker {
  15. public static void main(String[] args) throws IOException {
  16. File dir = new File("F:\\test");
  17. for (File file : dir.listFiles()) {
  18. System.out.format("%s: %s, %s%n", file, check(file), check2(file));
  19. }
  20. }
  21. /**
  22. * JDK自带API实现
  23. */
  24. @SuppressWarnings("resource")
  25. public static boolean check2(File file) throws IOException {
  26. long start = System.nanoTime();
  27. FileChannel fc = null;
  28. try {
  29. fc = new FileInputStream(file).getChannel();
  30. MappedByteBuffer buf = fc.map(MapMode.READ_ONLY, 0, fc.size());
  31. Charset utf8 = Charset.forName("UTF-8");
  32. CharsetDecoder decoder = utf8.newDecoder();
  33. CharBuffer cbuf = CharBuffer.allocate((int) (buf.limit() * decoder.averageCharsPerByte()));
  34. CoderResult result = decoder.decode(buf, cbuf, true);
  35. return !result.isError();
  36. } finally {
  37. if (fc != null) {
  38. fc.close();
  39. }
  40. long end = System.nanoTime();
  41. System.out.println("used(ns):" + (end - start));
  42. }
  43. }
  44. /**
  45. * 自定义实现
  46. */
  47. public static boolean check(File file) throws IOException {
  48. long start = System.nanoTime();
  49. InputStream in = null;
  50. try {
  51. in = new BufferedInputStream(new FileInputStream(file));
  52. StreamBuffer sbuf = new StreamBuffer(in, 1024);
  53. if (sbuf.next() == 0xEF && sbuf.next() == 0xBB && sbuf.next() == 0xBF) {
  54. return true;
  55. }
  56. sbuf.redo();
  57. // 1. U-00000000 - U-0000007F: 0xxxxxxx
  58. // 2. U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
  59. // 3. U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
  60. // 4. U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  61. // 5. U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  62. // 6. U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  63. for (int ch = 0; (ch = sbuf.next()) != -1;) {
  64. int n = 0;
  65. if (ch <= 0x7F) {
  66. n = 1;
  67. } else if (ch <= 0xBF) {
  68. return false;
  69. } else if (ch <= 0xDF) {
  70. n = 2;
  71. } else if (ch <= 0xEF) {
  72. n = 3;
  73. } else if (ch <= 0xF7) {
  74. n = 4;
  75. } else if (ch <= 0xFB) {
  76. n = 5;
  77. } else if (ch <= 0xFD) {
  78. n = 6;
  79. } else {
  80. return false;
  81. }
  82. while (--n > 0) {
  83. if ((sbuf.next() & 0x80) != 0x80) {
  84. return false;
  85. }
  86. }
  87. }
  88. return true;
  89. } finally {
  90. if (in != null) {
  91. in.close();
  92. }
  93. long end = System.nanoTime();
  94. System.out.println("used(ns):" + (end - start));
  95. }
  96. }
  97. static class StreamBuffer {
  98. final InputStream in;
  99. final byte[] buf;
  100. int pos = -1;// 初始值为-1,表示指针尚未移动.
  101. int len;
  102. public StreamBuffer(InputStream in, int size) {
  103. this.in = in;
  104. if (size < 3) {
  105. size = 3;
  106. }
  107. this.buf = new byte[size];
  108. }
  109. public void redo() {
  110. this.pos = 0;
  111. }
  112. public int next() throws IOException {
  113. if (len > 0 || pos < 0) {
  114. if (++pos == len) {
  115. if ((len = in.read(buf)) == 0) {
  116. return -1;
  117. }
  118. pos = 0;
  119. }
  120. return this.buf[this.pos] & 0xFF;
  121. } else {
  122. return -1;
  123. }
  124. }
  125. }
  126. }

复制代码

在本机测试, JDK原生API需要创建CharBuffer,性能明显慢了25%以上.

  1. used(ns):472420
  2. used(ns):4490075
  3. F:\test\b334d5fd-b8a7-48f4-9099-f6011c7e5a48.sql: true, true
  4. used(ns):122515
  5. used(ns):343490
  6. F:\test\b334d5fd-b8a7-48f4-9099-f6011c7e5a482.sql: false, false
  7. used(ns):55164
  8. used(ns):82425
  9. F:\test\test.sql: false, false

复制代码

Java检测文件是否UTF8编码的更多相关文章

  1. Java实现将任何编码方式的txt文件以UTF-8编码方式转存

    本文利用JDK中的BufferedReader和BufferedWriter实现将任何编码方式的txt文件以UTF-8编码方式转存. UTF-8(8-bit Unicode Transformatio ...

  2. JAVA输出带BOM的UTF-8编码的文件

    当从http 的response输出CSV文件的时候,设置为utf8的时候默认是不带bom的,可是windows的Excel是使用bom来确认utf8编码的,全部须要把bom写到文件的开头. 微软在 ...

  3. java中文GBK和UTF-8编码转换乱码的分析

    原文:http://blog.csdn.net/54powerman/article/details/77575656 作者:54powerman 一直以为,java中任意unicode字符串,可以使 ...

  4. py2.7 批量转换文件为 utf8 编码

    source insight 不支持 utf8 ,但是在 linux 上查看的时候是 utf8 编码,就会显示不正常,所以写了个 python 小脚本,可以批量转换 py2.7 #coding:utf ...

  5. java 将GBK编码文件转为UTF-8编码

    需要commons-io-2.0.1.jar public class Test { public static void main(String args[]) throws IOException ...

  6. 2018-03-21 11:34:44 java脚本批量转换java utf-8 bom源码文件为utf-8编码文件

    package com.springbootdubbo; import java.io.*;import java.util.ArrayList;import java.util.List; /** ...

  7. 使用Dom4j生成xml文件(utf-8编码)

    xml文件内容: <?xml version="1.0" encoding="UTF-8"?> <result> <code> ...

  8. java检测文件内是否包含指定内容

    package com.test; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.File ...

  9. loadrunner将参数文件转换为UTF-8编码

    在使用loadrunner进行参数化的时候,对于有些信息,比如地址.人名等,很多时候需要传入中文,但是有的时候会碰到字符编码不对导致脚本出错. 下面介绍两种loadrunner中可以使用的编码转化为U ...

随机推荐

  1. 关于MPEG2中的图像序列和图像组头GOP

    图像序列 图像序列是由图像组构成的,是随机存取段落. sequence_header_code – The sequence_header_code is the bit string ‘000001 ...

  2. 华为OJ平台——整形数组合并

    题目描述: 将两个整型数组按照升序合并,并且过滤掉重复数组元素 输入: 输入说明,按下列顺序输入: 1 输入第一个数组的个数 2 输入第一个数组的数值 3 输入第二个数组的个数 4 输入第二个数组的数 ...

  3. prototype原型模式中的问题

    对于每个构造函数来说,都有一个prototype属性.对于每个对象实例来说,都有_proto_属性. 参看下面代码: function Person(){} Person.prototype={ na ...

  4. 前端开发中的SEO

    什么是SEO SEO由英文Search Engine Optimization缩写而来,中文意译为"搜索引擎优化".SEO是指从自然搜索结果获得网站流量的技术和过程,是在了解搜索引 ...

  5. 如何更新Linux源

    首先需要自己收藏几个可以得到Linux源的站点,比如:http://mirrors.163.com/ (163的镜像站):可以百度搜索[Linux镜像站]: 下面这些镜像站,转自:http://www ...

  6. “Sysprep 错误 + CAPI2 引起的蓝屏”的参考解决方法

    这些天我在给学校机房部署 Windows 7 系统时,遇到一些问题,在网上找了很长时间才找到,其中有一个还是英文的资料.特此分享出来,希望能给遇到同样问题的人一个参考.由于学校的机子型号不都一样,所以 ...

  7. ASP.NET内置对象一

    ASP.NET提供了大量的对象类库,在这些类库中包含了许多封装好的内置对象,我们只需要直接使用这些对象的方法和属性,就能简单快速地完成很多的功能.Request对象.Response对象和Serve对 ...

  8. 微信开发笔记(一)通过.net如何实现接入微信

    微信公众平台,给个人.企业和组织提供业务服务与用户管理能力的全新服务平台.现在基本上每个地方都可以看到微信存在,动不动就是让你扫一下加下微信. 经常遇到这样情况,“到一家餐馆吃饭,拿了个号,前台服务引 ...

  9. zend studio导入thinkphp的乱码问题

    刚刚导入thinkphp有乱码还有错误怎么办? windows -> preference -> Work space -> text file encodeing设置为 UTF-8 ...

  10. scala学习笔记2

    一.算术和操作符重载 a + b 是如下方法的简写: a.+(b) 在scala中你可以使用任何符号来为方法命名.比如BigInt类就定义了一个/%的方法,该方法返回一个对偶,对偶的内容是除法操作得到 ...