You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中UTF-8字符串的打印、去重排序及文件保存问题

问题解决与实现方案

一、Eclipse控制台正确打印特殊字符的方法

Windows下Eclipse默认控制台编码为GBK,会导致UTF-8特殊字符输出时乱码成问号,按以下步骤调整:

  • 打开Run Configurations,找到你的Java程序,切换到Common标签页,在Encoding区域选择UTF-8(不要用默认选项)。
  • 若仍有问题,在VM参数中添加:-Dfile.encoding=UTF-8,强制JVM输出采用UTF-8编码。
  • 确认控制台字体支持目标字符:检查字体设置(Window > Preferences > General > Appearance > Colors and Fonts > Debug > Console Font),确保GNU FreeMono或其他选中字体包含所需Unicode字符集。

二、charAt() + HashSet去重的安全性问题

不安全,会出现多代码单元字符被拆分的情况。
Java中的char是UTF-16编码的16位代码单元,而Unicode中部分字符(如增补平面的字符)需要两个char组成代理对(高代理+低代理)。charAt()会将这两个代码单元拆分为独立的char,存入HashSet时会被当成两个单独的"字符",导致原字符被破坏,去重逻辑出错。

三、安全的字符比较与处理方式

必须基于**Unicode代码点(code point)**处理,每个代码点对应一个完整的Unicode字符:

  • 获取字符串所有代码点:调用str.codePoints(),返回IntStream,每个int代表一个代码点。
  • 比较字符时,直接比较代码点的整数值,或使用Character.compare(codePoint1, codePoint2)。
  • 将代码点转换回字符串:使用String.valueOf(Character.toChars(codePoint)),或通过IntStream.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString()批量转换。

四、多语言场景下安全保存字符串到文本文件

绝对不能使用默认编码的输出流(如FileWriter,Windows下默认编码为GBK),必须明确指定UTF-8编码:

方法1:使用OutputStreamWriter

try (OutputStreamWriter writer = new OutputStreamWriter(
        new FileOutputStream("output.txt"), StandardCharsets.UTF_8)) {
    writer.write(resultStr);
} catch (IOException e) {
    e.printStackTrace();
}

方法2:使用Files类(Java 7+)

try {
    // Java 11+ 可使用更简洁的写法
    Files.writeString(Paths.get("output.txt"), resultStr, StandardCharsets.UTF_8);
    // Java 7-10 写法
    // Files.write(Paths.get("output.txt"), resultStr.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
    e.printStackTrace();
}

保存后用支持UTF-8的文本编辑器(如Notepad++、VS Code)打开,确保编辑器编码设置为UTF-8。

五、完整实现:去重+按Unicode排序+打印+保存

以下是满足需求的完整代码,基于代码点处理避免代理对问题:

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.TreeSet;

public class UnicodeStringProcessor {
    public static void main(String[] args) {
        String originalStr = "áçñéüöëéóíóíóíóíííããéíáéíáççãÓłńńāņšøøøøééèèÜüÜüééíéáéáříříççááññïïššäääééèèááéáéáéáéáéáéáèèèèííéèéèáééÇÇééééííüüüüííøøáááá¿¿ííóé̌Íá̌íáææööíÁíÁíííłççññá璇üşİüşİöğöğşşııããßßôèôèêééççáÁáÁééééééÇóóéíêööééííððññáñáñÓúÓúíłńłńååéééëëááéí¿¿ééÖÖáéáéöğÖüöğÖüçŞçŞııçııçııİİşİşíáíáéüüÉÉéééøññïíéé";

        // 去重+按Unicode代码点排序:TreeSet自动按代码点数值排序
        TreeSet<Integer> uniqueCodePoints = new TreeSet<>();
        originalStr.codePoints().forEach(uniqueCodePoints::add);

        // 将代码点转换为字符串
        StringBuilder resultBuilder = new StringBuilder();
        uniqueCodePoints.forEach(resultBuilder::appendCodePoint);
        String resultStr = resultBuilder.toString();

        // 打印结果(需确保控制台编码已设为UTF-8)
        System.out.println("处理后的字符串:");
        System.out.println(resultStr);

        // 保存为UTF-8编码的文本文件
        try {
            Files.writeString(Paths.get("unicode_result.txt"), resultStr, StandardCharsets.UTF_8);
            System.out.println("\n文件已成功保存为unicode_result.txt(UTF-8编码)");
        } catch (IOException e) {
            System.err.println("保存文件失败:" + e.getMessage());
        }
    }
}

说明:

  • TreeSet会自动按代码点的整数值排序,即遵循Unicode编码顺序。
  • 用codePoints()遍历所有完整字符,避免代理对拆分问题。
  • 保存时明确指定StandardCharsets.UTF_8,确保多语言字符正确存储。

内容的提问来源于stack exchange,提问作者user2526586

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:39:28