我有一个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标头写入文件,如此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并运行它之后,输出的文件的格式被破坏了(我发现了他们被'?'char)取代
我认为这不是代码的问题,将其部署到Jar文件是一个问题,我认为Eclipse正在将源文件编译为CP1252或其他东西,但是甚至用它们替换所有unicode字符代码常量没有帮助
答案 0 :(得分:6)
我已经遵循了一些关于如何使用UTF-8的提示(默认情况下在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中推断出编码并正确解码文件。
没有代码,就无法发现任何错误。
我是否遗漏了一些属性或命令行命令,因此Java知道我想默认创建UTF-8文件?
不 - 没有这样的设置。有些人可能会建议在命令行上设置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
中。请注意,您应该提供一些机制来检查基础错误并关闭流(或者您有泄漏文件句柄的风险)。