资讯专栏INFORMATION COLUMN

Equinox MANIFEST.MF 中文处理 Bug

RobinTang / 1243人阅读

摘要:之前一段时间排查一个应用在中文目录下无法启动的问题,查过一个的处理的坑。这里记录一下里面对中的中文处理的坑。只能说在用到的时候,尽量不要使用中文的吧。

之前一段时间排查一个应用在中文目录下无法启动的问题,查过一个 Equinox 的 Manifest 处理的坑。今天,一个同事在写 Equinox 插件的时候也遇到了类似的问题。这里记录一下 Equinox 里面对 Manifest 中的中文处理的坑。

问题描述

先来看一段代码:

package manifest;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.Manifest;

import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.BundleException;

public class Test {
    private static String chineseString = "你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界你好,世界";

    public static void main(String[] args) throws IOException, BundleException {
        File manifestFile = createManifest();

        // 使用 ManifestElement 读取
        Map header = new HashMap<>();
        ManifestElement.parseBundleManifest(new FileInputStream(manifestFile), header);
        System.out.println(header.get("Test-Headers"));
    }

    private static File createManifest() throws IOException {
        Manifest manifest = new Manifest();
        manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
        // 创建一个带有中文的 Header,MANIFEST.MF 的一行的最大长度是 72 字节,中文在这里会被阶段
        manifest.getMainAttributes().putValue("Test-Headers", chineseString);

        File file = new File("MANIFEST.MF");

        if (!file.exists()) {
            file.createNewFile();
        }

        OutputStream outputStream = new FileOutputStream(file);

        manifest.write(outputStream);
        outputStream.flush();
        outputStream.close();

        return file;
    }
}

这一段代码虽然比较长,但是实际上的内容其实不多,主要做了这几步:

创建一个内容带有中文的 MANIFEST.MF 文件。

写入 MANIFEST.MF 文件到磁盘上。

用 Equinox 的 ManifestElement 来读取 MANFIEST.MF。

输出刚才的带有中文的 Header

上面的这段代码在我本地的执行结果如下:

你好,世界你好,世界你好,世界你好,��界你好,世界你好,世界你好,世界你好,世界你��,世界你好,世界你好,世界你好,世界

大家可以看到,中间有几个地方出现了乱码,同样的代码,如果用标准的 JDK 的方式来读取,是不会出现这种情况,为什么呢?

原因

首先,我们知道 UTF-8 的中文是占据了三个字节,而 MANIFEST.MF 文件一行的最大长度是 72 个字节,也就是说,如果你的 MANIFEST.MF 中含有中文,那么这个中文的三个字节可能会被截断,出现一部分在上面一行,一部分在下面一行的情况。上面的 MANIFEST.MF 文件就出现了这种情况,可以 cat 这个文件来看一下:

[~/Desktop/test]$ cat MANIFEST.MF
Manifest-Version: 1.0
Test-Headers: 你好,世界你好,世界你好,世界你好,�
 �界你好,世界你好,世界你好,世界你好,世界你�
 �,世界你好,世界你好,世界你好,世界

不过,即使这样写入了,如果读取的时候完全按照字节来读取的话,那也应该没有问题。但是,Equinox 比较特立独行,看下 Equinox 读取 Manifest 的关键代码:

作死的 Equinox 将一行读取出来以后直接转成了一个 string,而 byte 在转 string 的时候,如果遇到无法转的字节的话,会用 来替代,于是就出现了上面的情况。(关于 ,可以看 http://en.wikipedia.org/wiki/Specials_(Unicode_block))

解决方法

这个问题除非 Equinox 修复了此 Bug,否则是无解的。只能说在用到 Equinox 的时候,尽量不要使用中文的 Header 吧。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/64266.html

相关文章

  • jar命令浅析

    摘要:命令浅析文件的全称是,意思是档案文件,通常文件是一种压缩文件,并且与常见的文件兼容,两者的区别便是拥有清单文件,这个文件是生成文件时自动创建的。首先输入命令,系统会自动提示命令的用法。 jar命令浅析  JAR文件的全称是Java Archive File,意思是java档案文件,通常JAR文件是一种压缩文件,并且与常见的Zip文件兼容,两者的区别便是JAR拥有清单文件 (META-I...

    wmui 评论0 收藏0
  • Java 使用JAR文件

    摘要:使用文件与以下好处安全。包作为内嵌在平台内部处理的标准,能够在各种平台上直接使用命令详解创建文件该命令没有显示压缩过程,执行结果是将当前路径下的路径下的全部内容生成一个文件。使用如下命令即可将清单文件中的对提取到文件中。 JAR,Java Archive File,Java档案文件。JAR文件是一种压缩文件,与ZIP压缩文件兼容,通常称为JAR包。JAR文件中默认包含了一个名为META...

    seal_de 评论0 收藏0
  • java agent 详细介绍

    摘要:简介是命令的一个参数。参数可以用于指定一个包,并且对该包有个要求这个包的文件必须指定项。重点就在方法,也就是我们今天的标题。和类加载器比较类加载器也可以实现运行时修改代码。使用能让修改字节码这个动作化于无形,对业务透明,减少侵入性。 简介 java agent是java命令的一个参数。参数 javaagent 可以用于指定一个 jar 包,并且对该 java 包有2个要求: 这个 j...

    zhiwei 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<