【问题标题】:Project running fine in IDE but not as Jar项目在 IDE 中运行良好,但不像 Jar
【发布时间】:2016-11-29 00:18:50
【问题描述】:

我正在编写一个使用翻译字符串(.properties 文件)的应用程序;这些字符串也是由非拉丁字符组成的(实际上,它们是像 lenny 微笑之类的复制意大利面)。我的问题是,当我在我的 IDE Netbeans 中启动它时,单击“清理并构建”然后“运行”,一切正常,所有字符串都正确显示......程序按预期运行;但是当我将我的项目导出为 fat jar 时(我使用 Maven shade 插件,它还包括我的属性文件)并且当我启动它时双击它的图标(仍然在 Windows 上)一切都搞砸了up 因为有些字符串没有显示出来:

在我的程序中,我使用类LocalisationService(代码如下)在不同的ArrayList 中加载字符串。使用 Netbeans 运行我的项目,字符串都正确加载(这是假定的行为)。在 Netbeans 之外运行我的 jar,只有 1/5 被正确加载。我的数组列表中有大量“找不到字符串”条目,这意味着在我的LocalisationService 类中,方法getString 捕获MissingResourceException 异常。但实际上这些资源并没有丢失,我的意思是,我将它们正确地包含在我的 Jar 中,Netbeans 直接运行我的项目,所以......

我完全不知道是什么导致了这个问题:我的 IDE 项目编码设置为 UTF-8,所以应该没有任何问题... Maven 使用以下方式运行我的项目:

cd C:\Users\utente\Documents\NetBeansProjects\mavenproject1; "JAVA_HOME=C:\\Program Files\\Java\\jdk1.8.0_40" cmd /c "\"\"C:\\Program Files\\NetBeans 8.0.2\\java\\maven\\bin\\mvn.bat\" -Dexec.args=\"-classpath %classpath bot.Main\" -Dexec.executable=\"C:\\Program Files\\Java\\jdk1.8.0_40\\bin\\java.exe\" -Dmaven.ext.class.path=\"C:\\Program Files\\NetBeans 8.0.2\\java\\maven-nblib\\netbeans-eventspy.jar\" -Dfile.encoding=UTF-8 org.codehaus.mojo:exec-maven-plugin:1.2.1:exec\""

我在 Ubuntu 上遇到了同样的问题,字符串被弄乱了从终端启动我的文件

/usr/bin/java -jar myproject.jar

这是我用来使用键检索正确本地化字符串的类 LocalisationService:

public class LocalisationService {
    private static LocalisationService instance = null;
    private final HashMap<String, String> supportedLanguages = new HashMap<>();

    private ResourceBundle english;
    private ResourceBundle italian;

private class CustomClassLoader extends ClassLoader {
    public CustomClassLoader(ClassLoader parent) {
        super(parent);

    }

    public InputStream getResourceAsStream(String name) {
        InputStream utf8in = getParent().getResourceAsStream(name);
        if (utf8in != null) {
            try {
                byte[] utf8Bytes = new byte[utf8in.available()];
                utf8in.read(utf8Bytes, 0, utf8Bytes.length);
                byte[] iso8859Bytes = new String(utf8Bytes, "UTF-8").getBytes("ISO-8859-1");
                return new ByteArrayInputStream(iso8859Bytes);
            } catch (IOException e) {
                e.printStackTrace();

            } finally {
                try {
                    utf8in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

/**
 * Singleton
 * @return Instance of localisation service
 */
public static LocalisationService getInstance() {
    if (instance == null) {
        synchronized (LocalisationService.class) {
            if (instance == null) {
                instance = new LocalisationService();
            }
        }
    }
    return instance;
}

/**
 * Private constructor due to singleton
 */
private LocalisationService() {
    CustomClassLoader loader = new CustomClassLoader(Thread.currentThread().getContextClassLoader());
    english = ResourceBundle.getBundle("localisation.strings", new Locale("en", "US"), loader);
    supportedLanguages.put("en", "English");
    italian = ResourceBundle.getBundle("localisation.strings", new Locale("it", "IT"), loader);
    supportedLanguages.put("it", "Italiano");
}

/**
 * Get a string in default language (en)
 * @param key key of the resource to fetch
 * @return fetched string or error message otherwise
 */
public String getString(String key) {
    String result;
    try {
        result = english.getString(key);
    } catch (MissingResourceException e) {
        System.out.println("not found key...  "+key);
        result = "String not found";
    }

    return result;
}

/**
 * Get a string in default language
 * @param key key of the resource to fetch from localisations
 * @param language code key for language (such as "EN" for english)
 * @return fetched string or error message otherwise
 */
public String getString(String key, String language) {
    String result;
    try {
        switch (language.toLowerCase()) {
            case "en":
                result = english.getString(key);
                break;
            case "it":
                result = italian.getString(key);
                break;
            default:
                result = english.getString(key);
                break;
        }
    } catch (MissingResourceException e) {
        result = english.getString(key);
    }

    return result;
}

public HashMap<String, String> getSupportedLanguages() {
    return supportedLanguages;
}

public String getLanguageCodeByName(String language) {
    return supportedLanguages.entrySet().stream().filter(x -> x.getValue().equals(language)).findFirst().get().getKey();
}
}

我的项目完全没有错误,也没有警告...... 我还尝试在 Ubuntu 上运行我的 jar 文件:

/usr/bin/java -Dfile.encoding=UTF-8 -jar myproject.jar

但仍然没有运气。

我真的希望你们能帮助我,我在这个问题上停留了两天,根本没有解决方案......

【问题讨论】:

  • “字符串混乱”是什么意思?从 Netbeans 和命令行运行程序时会发生什么?有什么区别?你希望它变成什么?
  • 我认为因为你不知道答案而责怪提出问题的人是不公平的。从代码中我似乎很清楚问题是什么,但我也有更多的经验。

标签: java


【解决方案1】:

不要期望 InputStream.available() 为您提供准确的信息。

在此处查看将 InputStream 转换为 ByteArrayInputStream 的正确方法 > Convert InputStream(Image) to ByteArrayInputStream

很明显,在 Netbeans 中加载父类加载器提供的 InputStream 与从命令行 JVM 实现运行时有所不同。您的代码没有显示执行此代码的完整上下文,但 Netbeans 的 InputStream 实现可能完全填充了 available() 方法,给您错误的印象是代码是正确的。

请参阅https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available() 的文档

InputStream 实现不需要使用准确的值填充此方法,因此您的代码结果将因 JVM 实现而异。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多