【Java】你知道UTF-8 中 有BOM 和无 BOM 的区别吗?使用【豆包】学习的一天~

130 阅读4分钟

【Java】你知道UTF-8 中 有BOM 和无 BOM 的区别吗?使用【豆包】学习的一天~

前言

欢迎大家与小编一起拓展知识点~ 本文作者公众号 “新程快咖员” ,转载请注明出处~

作者简介:

IDEA插件Maven With Me(MPVP)开发者,让Maven开发管理版本更高效!无论是快速升级项目多模块版本、还是知晓当前项目各个模块的版本以及搜索中央仓库/私服依赖版本,都能轻松搞定。避免大家花费更多的精力和心力在这些繁琐的流程中~

UTF-8 中 BOM 和无 BOM 的区别

UTF-8 中的 BOM(Byte Order Mark,字节顺序标记)是一个特殊的字节序列 0xEF 0xBB 0xBF,主要作用是:

标识编码格式:告诉解析器该文件使用 UTF-8 编码。

历史兼容性:源自 UTF-16/32 中用于标记字节序(大端 / 小端)的标记,UTF-8 本身不需要字节序标记,但保留了 BOM 作为编码标识。

两者的核心区别:

带 BOM 的 UTF-8:文件开头会包含 0xEF 0xBB 0xBF 三个字节。

无 BOM 的 UTF-8:文件开头没有这三个字节,是更常见的形式。

BOM 可能带来的问题:

某些程序(如 shell 脚本、部分编程语言解析器)会将 BOM 视为文件内容的一部分,导致错误(例如脚本执行时的语法错误)。

多数现代软件(如编辑器、浏览器)能自动识别无 BOM 的 UTF-8,因此 BOM 通常不是必需的。

Java 写入的 UTF-8 是否带 BOM?

默认情况下,Java 写入的 UTF-8 是不带 BOM 的。

Java 中处理字符编码的 StandardCharsets.UTF_8 或 "UTF-8" 对应的编码方式不包含 BOM。例如:


// 默认写入无 BOM 的 UTF-8 (JAVA 11+)
try (FileWriter writer = new FileWriter("file-without-bom.txt", StandardCharsets.UTF_8)) {
    writer.write("内容");
}

// 默认写入无 BOM 的 UTF-8 (JAVA 8+)
try (Writer writer = new OutputStreamWriter(new FileOutputStream("file-without-bom.txt"), StandardCharsets.UTF_8)) {
    writer.write("内容");
}

如果需要生成带 BOM 的 UTF-8 文件,必须手动写入 0xEF 0xBB 0xBF 字节序列,例如:


try (OutputStream os = new FileOutputStream("file-with-bom.txt");
     OutputStreamWriter writer = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
    // 手动写入 BOM
    os.write(0xEF);
    os.write(0xBB);
    os.write(0xBF);
    // 写入内容
    writer.write("带 BOM 的内容");
}

总结:Java 不会自动为 UTF-8 编码添加 BOM,如需带 BOM 需手动处理。

Java如何通过字节流添加UTF-8 BOM?


import java.io.*;
import java.nio.charset.StandardCharsets;

public class ByteStreamWithBom {
    public static void main(String[] args) {
        String filePath = "byte-stream-with-bom.txt";
        String content = "通过字节流添加BOM的UTF-8内容";

        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            // 1. 先写入UTF-8 BOM的三个字节
            fos.write(0xEF);
            fos.write(0xBB);
            fos.write(0xBF);

            // 2. 再将内容转换为UTF-8字节并写入
            byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
            fos.write(contentBytes);

            System.out.println("已通过字节流生成带BOM的文件:" + filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

实现说明:

核心步骤:

第一步:通过FileOutputStream(字节流)先写入 BOM 标识的三个字节0xEF 0xBB 0xBF

第二步:将字符串内容通过String.getBytes(StandardCharsets.UTF_8)转换为 UTF-8 字节数组

第三步:写入转换后的字节数组

字节流的优势:

直接操作字节,过程更透明,能精确控制 BOM 的写入时机和位置

适合处理二进制数据或需要严格控制字节序列的场景

注意事项:

必须先写 BOM 再写内容,顺序不能颠倒

转换字符串为字节时,必须显式指定StandardCharsets.UTF_8,避免使用默认编码

使用 try-with-resources 确保流自动关闭,避免资源泄漏

这种纯字节流的方式最直接,能确保 BOM 被正确添加到文件头部,适用于所有需要带 BOM 的 UTF-8 文件场景。

如何在Java中检测一个文件是否包含UTF-8 BOM?



import java.io.FileInputStream;
import java.io.IOException;

public class Utf8BomDetector {

    /**
     * 检测文件是否包含UTF-8 BOM
     * @param filePath 文件路径
     * @return 包含BOM返回true,否则返回false
     * @throws IOException 可能的IO异常
     */
    public static boolean hasUtf8Bom(String filePath) throws IOException {
        // 定义UTF-8 BOM的字节序列
        byte[] bom = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF};

        try (FileInputStream fis = new FileInputStream(filePath)) {
            // 读取文件开头的3个字节
            byte[] buffer = new byte[3];
            int bytesRead = fis.read(buffer);

            // 如果读取到至少3个字节,且与BOM序列完全匹配
            if (bytesRead >= 3) {
                return buffer[0] == bom[0] && buffer[1] == bom[1] && buffer[2] == bom[2];
            }
        }
        return false;
    }

    // 测试方法
    public static void main(String[] args) {
        String testFile1 = "file-with-bom.txt";   // 假设包含BOM的文件
        String testFile2 = "file-without-bom.txt";// 假设不包含BOM的文件

        try {
            System.out.println(testFile1 + " 包含BOM: " + hasUtf8Bom(testFile1));
            System.out.println(testFile2 + " 包含BOM: " + hasUtf8Bom(testFile2));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

如何快速查看文件有无UTF8 BOM 或 添加 / 移除BOM

这里可以使用IDEA 打开文件,然后点击右下角的编码。如果显示Add Bom就是无Bom,显示Remove Bom就是有Bom。需要添加或移除Bom点击对应的选项即可。 在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

结尾

欢迎关注公众号 “新程快咖员” 解锁更多内容!

以上就是本篇文章的全部内容啦,感谢您的阅读和观看。欢迎点赞、转发(分享)和推荐~