java中byte, iso-8859-1, UTF-8,乱码的根源

本文深入探讨Java中乱码问题,涉及字节、ISO-8859-1、UTF-8编码,解释乱码的根源,并分析Java中编码流程,包括字符到字节的转换,以及在I/O、内存、web环境中的编码处理。通过例子展示了中文字符在不同编码下如何变为乱码,强调了正确设置编码的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Post@https://ryan-miao.github.io

背景

还是多语言, 在项目中遇到本地环境和服务端环境不一致乱码的情形。因此需要搞清楚乱码产生的过程,来分析原因。

获取多语言代码如下:

private Map<String, String> getLocalizationContent(Locale locale) {
    ResourceBundle bundle = ResourceBundle.getBundle(this.resourceBundleName, Locale.US);
    ResourceBundle bundleLocale = ResourceBundle.getBundle(this.resourceBundleName, locale);
    Set<String> keys = bundle.keySet();
    Map<String, String> map = new HashMap();

    String key;
    String translation;
    for(Iterator var6 = keys.iterator(); var6.hasNext(); map.put(key, translation)) {
        key = (String)var6.next();

        try {
            translation = bundleLocale.getString(key);
            translation = new String(translation.getBytes("ISO-8859-1"), "UTF-8");
            translation = this.escapeStringForJavaScript(translation);
        } catch (UnsupportedEncodingException | MissingResourceException var10) {
            translation = bundle.getString(key);
        }
    }

    return map;
}

其中,因为ResourceBundle通过PropertyResourceBundle读取properties文件。 这就要看以哪种方式load Properties了。提供了两种构造函数:

public PropertyResourceBundle (InputStream stream) throws IOException {
    Properties properties = new Properties();
    properties.load(stream);
    lookup = new HashMap(properties);
}
public PropertyResourceBundle (Reader reader) throws IOException {
    Properties properties = new Properties();
    properties.load(reader);
    lookup = new HashMap(properties);
}

通过跟踪ResourceBundle.getBundle(this.resourceBundleName, locale);源码发现创建bundle的方法为:

public ResourceBundle newBundle(String baseName, Locale locale, String format,
                                        ClassLoader loader, boolean reload)
                    throws IllegalAccessException, InstantiationException, IOException {
    String bundleName = toBundleName(baseName, locale);
    ResourceBundle bundle = null;
    if (format.equals("java.class")) {
        try {
            @SuppressWarnings("unchecked")
            Class<? extends ResourceBundle> bundleClass
                = (Class<? extends ResourceBundle>)loader.loadClass(bundleName);

            // If the class isn't a ResourceBundle subclass, throw a
            // ClassCastException.
            if (ResourceBundle.class.isAssignableFrom(bundleClass)) {
                bundle = bundleClass.newInstance();
            } else {
                throw new ClassCastException(bundleClass.getName()
                             + " cannot be cast to ResourceBundle");
            }
        } catch (ClassNotFoundException e) {
        }
    } else if (format.equals("java.properties")) {
        final String resourceName = toResourceName0(bundleName, "properties");
        if (resourceName == null) {
            return bundle;
        }
        final ClassLoader classLoader = loader;
        final boolean reloadFlag = reload;
        InputStream stream = null;
        try {
            stream = AccessController.doPrivileged(
                new PrivilegedExceptionAction<InputStream>() {
                    public InputStream run() throws IOException {
                        InputStream is = null;
                        if (reloadFlag) {
                            URL url = classLoader.getResource(resourceName);
                            if (url != null) {
                                URLConnection connection = url.openConnection();
                                if (connection != null) {
                                    // Disable caches to get fresh data for
                                    // reloading.
                                    connection.setUseCaches(false);
                                    is = connection.getInputStream();
                                }
                            }
                        } else {
                            is = classLoader.getResourceAsStream(resourceName);
                        }
                        return is;
                    }
                });
        } catch (PrivilegedActionException e) {
            throw (IOException) e.getException();
        }
        if (stream != null) {
            try {
                bundle = new PropertyResourceBundle(stream);
            } finally {
                stream.close();
            }
        }
    } else {
        throw new IllegalArgumentException("unknown format: " + format);
    }
    return bundle;
}

也就是说,最终通过pr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值