java 实现文件编码检测的几种方式汇总

 更新时间:2025年09月01日 14:55:00   作者:夜空下的星  
在实际开发中,我们常常涉及某些场景需要对文件的读取,但是因为不知道具体的编码格式,导致读取到的文件内容乱码,因此在读取文件内容之前,需要解析获取文件的编码,这样读取的内容就不会出现乱码了,下面是常见的几种获取文件编码的方式,感兴趣的朋友一起看看吧

一、前言

在实际开发中,我们常常涉及某些场景需要对文件的读取,但是因为不知道具体的编码格式,导致读取到的文件内容乱码,因此在读取文件内容之前,需要解析获取文件的编码,这样读取的内容就不会出现乱码了,下面是常见的几种获取文件编码的方式。

二、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文件编码检测内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java创建文件且写入内容的方法

    Java创建文件且写入内容的方法

    这篇文章主要介绍了Java创建文件且写入内容的方法的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • Sentinel热点规则示例详解分析

    Sentinel热点规则示例详解分析

    这篇文章主要介绍了何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制
    2021-09-09
  • Spring框架学习笔记之方法注解@Bean的使用

    Spring框架学习笔记之方法注解@Bean的使用

    这篇文章主要给大家介绍了关于Spring框架学习笔记之方法注解@Bean使用的相关资料,这是一个我们很常用的注解,作用是指示一个方法生成一个由Spring管理的Bean,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • java简单网页抓取的实现方法

    java简单网页抓取的实现方法

    这篇文章主要介绍了java简单网页抓取的实现方法,详细分析了与Java网页抓取相关的tcp及URL相关概念,以及对应的类文件原理,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • java批量采集豌豆荚网站Android应用图标和包名

    java批量采集豌豆荚网站Android应用图标和包名

    这篇文章主要介绍了java批量采集豌豆荚网站Android应用图标和包名,主要用在做主题时替换这些常见应用的图片,需要的朋友可以参考下
    2014-06-06
  • Mybatis复杂查询的实现

    Mybatis复杂查询的实现

    本文主要介绍了Mybatis复杂查询的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-09-09
  • Aspectj与Spring AOP的对比分析

    Aspectj与Spring AOP的对比分析

    这篇文章主要介绍了Aspectj与Spring AOP的对比分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java 8 的异步编程利器 CompletableFuture的实例详解

    Java 8 的异步编程利器 CompletableFuture的实例详解

    这篇文章主要介绍了Java 8 的异步编程利器 CompletableFuture 详解,本文通过一个例子给大家介绍下Java 8  CompletableFuture异步编程的相关知识,需要的朋友可以参考下
    2022-03-03
  • 新手入门Jvm--jvm概览

    新手入门Jvm--jvm概览

    JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的
    2021-06-06
  • Java多线程编程中的并发安全问题及解决方法

    Java多线程编程中的并发安全问题及解决方法

    保障多线程并发安全,解决线程同步与锁竞争问题,提高应用性能与可靠性。多线程编程需要考虑线程安全性,使用同步机制保证共享变量的一致性,避免线程竞争导致的数据不一致与死锁等问题。常用的同步机制包括synchronized、ReentrantLock、volatile等
    2023-04-04

最新评论