java 实现文件编码检测的几种方式汇总
作者:夜空下的星
一、前言
在实际开发中,我们常常涉及某些场景需要对文件的读取,但是因为不知道具体的编码格式,导致读取到的文件内容乱码,因此在读取文件内容之前,需要解析获取文件的编码,这样读取的内容就不会出现乱码了,下面是常见的几种获取文件编码的方式。
二、java实现获取文件编码的几种方式。
1.引入第三方依赖库juniversalchardet实现编码获取。
(1)首先添加juniversalchardet Maven依赖。
<dependency> <groupId>com.github.albfernandez</groupId> <artifactId>juniversalchardet</artifactId> <version>2.4.0</version> </dependency>
(2)定义一个FileEncodeUtils类。
import org.mozilla.universalchardet.UniversalDetector; import java.io.*; import java.nio.charset.Charset; import java.util.Objects; public static Charset getCharset(File file) { try (InputStream in = new FileInputStream(file)) { String encoding = UniversalDetector.detectCharset(in); if (encoding != null) { return Charset.forName(encoding); } } catch (Exception e) { e.printStackTrace(); } return Charset.defaultCharset(); } public static void main(String[] args) { File file = new File("D:\\111.csv"); System.err.println(getCharset(file).name()); }
运行下main方法就可以获取对应的文件编码了。
2.使用hutool工具包获取文件编码。
(1).添加maven依赖
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </dependency>
(2)定义一个方法获取文件编码。
public static Charset getFileCharset(File file) { try (InputStream in = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { //最多循环3次,每次2kb,主要是防止一次不能获取到编码 int cycleNum = 0; Charset charset = null; byte[] buffer = new byte[4096]; int len; while (cycleNum < 3 && (len = in.read(buffer)) > -1) { baos.write(buffer, 0, len); baos.flush(); cycleNum++; charset = CharsetDetector.detect(1024 * cycleNum, new ByteArrayInputStream(baos.toByteArray()), null); if (Objects.nonNull(charset)) { break; } } if (charset != null) { } else { return Charset.defaultCharset(); } return charset; } catch (Exception e) { //使用默认编码utf-8 return Charset.defaultCharset(); } } public static void main(String[] args) { File file = new File("D:\\111.csv"); System.err.println(getFileCharset(file).name()); }
运行main方法即可获取编码。
3.基于 Java 原生 API获取编码
(1)通过 InputStreamReader 获取文件编码。
public static Charset getCharset(File file) { try (InputStream in = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(in)) { String encoding = isr.getEncoding(); // 返回当前流的编码(如 "UTF8") if (encoding != null) { return Charset.forName(encoding); } } catch (Exception e) { e.printStackTrace(); } return Charset.defaultCharset(); } public static void main(String[] args) { File file = new File("D:\\111.csv"); System.err.println(getCharset(file).name()); }
这个不需要依赖第三方包,但仅适用于流未被修改且编码已知的场景,对未知编码可能返回默认值(如系统编码)。
4.手动解析字节特征判断是否是utf8。
/** * 判断文件内容是否为 UTF-8 编码 * @author */ public static boolean checkUTF8(InputStream fis) { //请注意fis是流,是不能复用的! try { while (true) { int curr = fis.read(); if (curr == -1) { return true; } if (curr < 0x80) {// (10000000): 值小于0x80的为ASCII字符 return false; } else if (curr < (0xC0)) { // (11000000): 值介于0x80与0xC0之间的为无效UTF-8字符 return false; } else if (curr < (0xE0)) { // (11100000): 此范围内为2字节UTF-8字符 if ((fis.read() & (0xC0)) != 0x80) { return false; } return true; } else if (curr < (0xF0)) { // (11110000): 此范围内为3字节UTF-8字符 if ((fis.read() & (0xC0)) != 0x80 || (fis.read() & (0xC0)) != 0x80) { return false; } return true; } else { return false; } } } catch (IOException e) { return true; } }
这种方式可以简单判断是否为utf-8编码,但实现复杂,需编码知识,一般不推荐。
总结:
1.第三方库juniversalchardet 准确性高(需足够数据支撑统计分析),同时由于局限性:可能由于训练数据或算法原因,对某些GBK变体支持不足。
2.Hutool CharsetDetector实现较为基础,如通过 BOM 头或 ASCII 范围快速判断,缺乏复杂编码的统计分析能力。适用于简单场景(如明确已知 UTF-8 或 ASCII 编码)以及快速开发且对编码检测精度要求不高时。
到此这篇关于java 实现文件编码检测的几种方式汇总的文章就介绍到这了,更多相关java文件编码检测内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!