Java检测文件是否UTF8编码
介绍UTF-8编码规则
- UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长. Bigendian UCS-4 字节串的排列顺序是预定的.
- 字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到.
- 下列字节串用来表示一个字符. 用到哪个串取决于该字符在 Unicode 中的序号.
- U-00000000 - U-0000007F: 0xxxxxxx
- U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
- U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
- U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- xxx 的位置由字符编码数的二进制表示的位填入. 越靠右的 x 具有越少的特殊意义. 只用最短的那个足够表达一个字符编码数的多字节串. 注意在多字节串中, 第一个字节的开头"1"的数目就是整个串中字节的数目.
- 例如: Unicode 字符 U+00A9 = 1010 1001 (版权符号) 在 UTF-8 里的编码为:
- 11000010 10101001 = 0xC2 0xA9
- 而字符 U+2260 = 0010 0010 0110 0000 (不等于) 编码为:
- 11100010 10001001 10100000 = 0xE2 0x89 0xA0
- 特殊规则: 文件头三个字节用16进制表示是EFBBBF, 此规则不通用, 由编辑工具定义.
- 这种编码的官方名字拼写为 UTF-8, 其中 UTF 代表 UCS Transformation Format. 请勿在任何文档中用其他名字 (比如 utf8 或 UTF_8) 来表示 UTF-8, 当然除非你指的是一个变量名而不是这种编码本身.
复制代码
源码实现:
- package com.yy.game.test;
- import java.io.BufferedInputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.nio.CharBuffer;
- import java.nio.MappedByteBuffer;
- import java.nio.channels.FileChannel;
- import java.nio.channels.FileChannel.MapMode;
- import java.nio.charset.Charset;
- import java.nio.charset.CharsetDecoder;
- import java.nio.charset.CoderResult;
- public class UTF8Checker {
- public static void main(String[] args) throws IOException {
- File dir = new File("F:\\test");
- for (File file : dir.listFiles()) {
- System.out.format("%s: %s, %s%n", file, check(file), check2(file));
- }
- }
- /**
- * JDK自带API实现
- */
- @SuppressWarnings("resource")
- public static boolean check2(File file) throws IOException {
- long start = System.nanoTime();
- FileChannel fc = null;
- try {
- fc = new FileInputStream(file).getChannel();
- MappedByteBuffer buf = fc.map(MapMode.READ_ONLY, 0, fc.size());
- Charset utf8 = Charset.forName("UTF-8");
- CharsetDecoder decoder = utf8.newDecoder();
- CharBuffer cbuf = CharBuffer.allocate((int) (buf.limit() * decoder.averageCharsPerByte()));
- CoderResult result = decoder.decode(buf, cbuf, true);
- return !result.isError();
- } finally {
- if (fc != null) {
- fc.close();
- }
- long end = System.nanoTime();
- System.out.println("used(ns):" + (end - start));
- }
- }
- /**
- * 自定义实现
- */
- public static boolean check(File file) throws IOException {
- long start = System.nanoTime();
- InputStream in = null;
- try {
- in = new BufferedInputStream(new FileInputStream(file));
- StreamBuffer sbuf = new StreamBuffer(in, 1024);
- if (sbuf.next() == 0xEF && sbuf.next() == 0xBB && sbuf.next() == 0xBF) {
- return true;
- }
- sbuf.redo();
- // 1. U-00000000 - U-0000007F: 0xxxxxxx
- // 2. U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
- // 3. U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
- // 4. U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- // 5. U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- // 6. U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
- for (int ch = 0; (ch = sbuf.next()) != -1;) {
- int n = 0;
- if (ch <= 0x7F) {
- n = 1;
- } else if (ch <= 0xBF) {
- return false;
- } else if (ch <= 0xDF) {
- n = 2;
- } else if (ch <= 0xEF) {
- n = 3;
- } else if (ch <= 0xF7) {
- n = 4;
- } else if (ch <= 0xFB) {
- n = 5;
- } else if (ch <= 0xFD) {
- n = 6;
- } else {
- return false;
- }
- while (--n > 0) {
- if ((sbuf.next() & 0x80) != 0x80) {
- return false;
- }
- }
- }
- return true;
- } finally {
- if (in != null) {
- in.close();
- }
- long end = System.nanoTime();
- System.out.println("used(ns):" + (end - start));
- }
- }
- static class StreamBuffer {
- final InputStream in;
- final byte[] buf;
- int pos = -1;// 初始值为-1,表示指针尚未移动.
- int len;
- public StreamBuffer(InputStream in, int size) {
- this.in = in;
- if (size < 3) {
- size = 3;
- }
- this.buf = new byte[size];
- }
- public void redo() {
- this.pos = 0;
- }
- public int next() throws IOException {
- if (len > 0 || pos < 0) {
- if (++pos == len) {
- if ((len = in.read(buf)) == 0) {
- return -1;
- }
- pos = 0;
- }
- return this.buf[this.pos] & 0xFF;
- } else {
- return -1;
- }
- }
- }
- }
复制代码
在本机测试, JDK原生API需要创建CharBuffer,性能明显慢了25%以上.
- used(ns):472420
- used(ns):4490075
- F:\test\b334d5fd-b8a7-48f4-9099-f6011c7e5a48.sql: true, true
- used(ns):122515
- used(ns):343490
- F:\test\b334d5fd-b8a7-48f4-9099-f6011c7e5a482.sql: false, false
- used(ns):55164
- used(ns):82425
- F:\test\test.sql: false, false
复制代码
Java检测文件是否UTF8编码的更多相关文章
- Java实现将任何编码方式的txt文件以UTF-8编码方式转存
本文利用JDK中的BufferedReader和BufferedWriter实现将任何编码方式的txt文件以UTF-8编码方式转存. UTF-8(8-bit Unicode Transformatio ...
- JAVA输出带BOM的UTF-8编码的文件
当从http 的response输出CSV文件的时候,设置为utf8的时候默认是不带bom的,可是windows的Excel是使用bom来确认utf8编码的,全部须要把bom写到文件的开头. 微软在 ...
- java中文GBK和UTF-8编码转换乱码的分析
原文:http://blog.csdn.net/54powerman/article/details/77575656 作者:54powerman 一直以为,java中任意unicode字符串,可以使 ...
- py2.7 批量转换文件为 utf8 编码
source insight 不支持 utf8 ,但是在 linux 上查看的时候是 utf8 编码,就会显示不正常,所以写了个 python 小脚本,可以批量转换 py2.7 #coding:utf ...
- java 将GBK编码文件转为UTF-8编码
需要commons-io-2.0.1.jar public class Test { public static void main(String args[]) throws IOException ...
- 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; /** ...
- 使用Dom4j生成xml文件(utf-8编码)
xml文件内容: <?xml version="1.0" encoding="UTF-8"?> <result> <code> ...
- java检测文件内是否包含指定内容
package com.test; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.File ...
- loadrunner将参数文件转换为UTF-8编码
在使用loadrunner进行参数化的时候,对于有些信息,比如地址.人名等,很多时候需要传入中文,但是有的时候会碰到字符编码不对导致脚本出错. 下面介绍两种loadrunner中可以使用的编码转化为U ...
随机推荐
- socket学习笔记——select与epoll函数的使用(linux)
select.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <u ...
- oracle删除用户及其名下对象
drop user XXXX cascade; drop tablespace XXXX INCLUDING CONTENTS;
- 华为OJ平台——杨辉三角的变形
import java.util.Scanner; /** * 杨辉三角的变形 *第一行为1,后面每一行的一个数是其左上角到右上角的数的和,没有的记为0 * 1 * 1 1 1 * 1 2 3 2 1 ...
- 【MySQL】MySQL无基础学习和入门之二:MySQL的安装
安装MySQL安装一般分为源码包编译安装.分发包.rpm包安装和yum安装,四种安装方式有一些区别,对应的适用场景也不一样. 源码包:源码包就是程序源代码包,其中包含程序代码文件,这些代码文件是文本型 ...
- 【Linux】基于Linux的buffer和cache学习
缓存(cached)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据)就不要去读硬盘了,若没有命中就读硬盘.其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最容易找到的位置,把不再读 ...
- Widows2003开机取消按CTRL+ALT+DEL
一, Widows2003开机取消按CTRL+ALT+DEL 1. 单击windows开始键→管理工具→本地安全策略(如下图) 2. 本地安全设置→本地策略→安全选项 3. 安全选项→右侧→找到这个文 ...
- JavaScript高级 引用类型(二)《JavaScript高级程序设计(第三版)》
五.Function类型 是JS中最重要的一种引用类型 构造方式:(三种) 函数声明: 函数表达式定义: 函数构造器: 没有重载: 如果有两个相同函数名的函数,执行时,执行最近被定义的一次. 函数声明 ...
- 搭建高性能计算环境(七)、应用软件的安装之MS
1,上传软件包MaterialsStudio70.tgz.msi_7.lic到服务器上. 2,安装ms一般会创建一个普通用户msi,软件安装在msi账号下. 创建用户msi: useradd msi ...
- Apache开启Proxy代理,实现域名端口转发
今天帮客户迁移网站,客户一个是ASPX的一个是PHP的网站,这时候有2个域名,可是php网站是Apache下的伪静态,必须要用到Apache,但是ASPX网站还必要到IIS+Mssql 然后到了这个时 ...
- EasyUI datagrid checkbox数据设定与取值(转自http://blog.csdn.net/baronyang/article/dnetails/9323463,感谢分享,谢谢)
这一篇将会说明两种使用 jQuery EasyUI DataGrid 的 Checkbox 设定方式,以及在既有数据下将 checked 为 true 的该笔数据列的 Checkbox 设定为 Che ...