我有一个小的 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/