java - 从可运行的 Jar 在 Java 中创建 UTF-8 文件

标签 java windows eclipse utf-8 jar

我有一个小的 Java 项目,我在其中将类文件的属性设置为 UTF-8(我使用了很多在默认 CP1252 上找不到的外来字符)。

目标是创建一个包含项目列表的文本文件(在 Windows 中)。 当从 Eclipse 本身运行类文件时(按 Ctrl+F11)它会完美地创建文件并在另一个编辑器中打开它(我使用的是 Notepad++)我可以看到我想要的字符。

┌──────────────────────────────────────────────────┐
│                          Universidade2010 (18/18)│
│                                         hidden: 0│
├──────────────────────────────────────────────────┤

但是,当我将项目(使用 Eclipse)导出为可运行的 Jar 并使用“javaw -jar project.jar”运行它时,创建的新文件是一堆问号

????????????????????????????????????????????????????
?                          Universidade2010 (19/19)?
?                                         hidden: 0?
????????????????????????????????????????????????????

我已经按照一些关于如何使用 UTF-8(在 Java 上默认情况下似乎被破坏)的提示来尝试纠正这个问题,所以现在我正在使用

Writer w = new OutputStreamWriter(fos, "UTF-8");

并将 BOM header 写入文件,如 question already answered但在导出到 Jar 时仍然没有运气

我是否缺少某些属性或命令行命令以便 Java 知道我要默认创建 UTF-8 文件?


问题不在于创建文件本身,因为在开发文件时正确输出(使用 unicode 字符)

创建文件的类现在(并遵循使用 Charset 类的建议)如下所示:

public class Printer {

    File f;
    FileOutputStream fos;
    Writer w;
    final byte[] utf8_bom = { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF };

    public Printer(String filename){
        f = new File(filename);
        try {
            fos = new FileOutputStream(f);
            w = new OutputStreamWriter(fos, Charset.forName("UTF-8"));
            fos.write(utf8_bom);
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void print(String s) {
        if(fos != null){
            try {
                fos.write(s.getBytes());
                fos.flush();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

所有被使用的字符都是这样定义的:

private final char pipe = '\u2502';         /* │ */
private final char line = '\u2500';         /* ─ */
private final char pipeleft = '\u251c';     /* ├ */
private final char piperight = '\u2524';    /* ┤ */
private final char cupleft = '\u250c';      /* ┌ */
private final char cupright = '\u2510';     /* ┐ */
private final char cdownleft = '\u2514';    /* └ */
private final char cdownright = '\u2518';   /* ┘ */

问题仍然存在,当简单地通过在 Eclipse 上运行项目输出到文件时,文件完美无缺,但是在将项目部署到 Jar 并运行它之后,输出文件的格式被破坏了(我发现它们被替换为“?”字符)

我开始认为这不是代码的问题,而是将它部署到 Jar 文件中的问题,我认为 Eclipse 正在将源文件编译为 CP1252 或其他东西,但甚至用它们替换所有 unicode 字符代码常量没有帮助

最佳答案

I've followed some tips on how to use UTF-8 (which seems to be broken by default on Java)

由于历史原因,Java 的编码默认为系统编码(在 Windows 95 上更有意义)。这种行为不太可能改变。据我所知,Java 的编码器实现没有任何问题。

  private static final String BOM = "\ufeff";

  public static void main(String[] args) throws IOException {
    String data = "\u250c\u2500\u2500\u2510\r\n\u251c\u2500\u2500\u2524";
    OutputStream out = new FileOutputStream("data.txt");
    Closeable resource = out;
    try {
      Writer writer = new OutputStreamWriter(out, Charset.forName("UTF-8"));
      resource = writer;
      writer.write(BOM);
      writer.write(data);
    } finally {
      resource.close();
    }
  }

上面的代码将发出以下以字节顺序标记为前缀的文本:

┌──┐
├──┤

Windows 应用程序(如记事本)可以从 BOM 推断编码并正确解码文件。

没有代码,就不可能发现任何错误。

Am I missing some property or command-line command so Java knows I want to create UTF-8 files by default?

否 - 没有这样的设置。有些人可能建议在命令行上设置 file.encoding,但这是 bad idea .


我写了一篇关于这个主题的更全面的博文 here .


这是对 your code 的改造:

public class Printer implements Closeable {
  private PrintWriter pw;
  private boolean error;

  public Printer(String name) {
    try {
      pw = new PrintWriter(name, "UTF-8");
      pw.print('\uFEFF'); // BOM
      error = false;
    } catch (IOException e) {
      error = true;
    }
  }

  public void print(String s) {
    if (pw == null) return;
    pw.print(s);
    pw.flush();
  }

  public boolean checkError() { return error || pw.checkError(); }

  @Override public void close() { if (pw != null) pw.close(); }
}

您想要的大部分功能已经存在于PrintWriter 中.请注意,您应该提供一些机制来检查潜在错误并关闭流(否则您可能会泄露文件句柄)。

关于java - 从可运行的 Jar 在 Java 中创建 UTF-8 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3033081/

相关文章:

java - TableMenuButton 不显示保存为 Label、JavaFx 的列名称

windows - 写入系统驱动器 C : without admin rights in Delphi 上的文件

java - 如何使 Eclipse 中 Java 8 lambda 参数的代码完成工作?

eclipse - 更新eclipse时出错

Java - 重写从外部类继承泛型的内部类时出现 'Name clash' 和 'constructor undefined' 错误

java - 安卓Java : Get Response Body from HttpUrlConnection

java - spring 配置在创建 bean 之前没有 Autowiring ?

java - 在 Java 7 中将 sun.locale.formatasdefault 设置为 true

java - Windows下JVM如何绘制按钮等控件?

windows - OpenSSL Windows x64 编译错误