尝试编译Java代码时出现非法字符

33

我有一个程序,允许用户在富文本框中输入Java代码,并使用Java编译器进行编译。每当我尝试编译我写的代码时,就会出现一个错误,说我的代码开头有一个不存在的非法字符。这是编译器给我的错误信息:

C:\Users\Travis Michael>"\Program Files\Java\jdk1.6.0_17\bin\javac" Test.java
Test.java:1: illegal character: \187
public class Test
 ^
Test.java:1: illegal character: \191
public class Test
  ^
2 errors

2
你能发布这些字符的字符代码吗?也许是被搞乱了的Unicode BOM? - Mark Byers
你如何获取字符代码? - muckdog12
6
亲爱的微软,你们什么时候才会停止将假BOM丢入UTF-8文件的开头作为默认设置呢?这种行为已经不再好笑了。 - bobince
3
不,它不会。请参见规范,第30页。 - Mechanical snail
是的,这就是公司使用的退出条款,以确保他们软件生成的文件只能可靠地被自己的软件读取。Unicode是由软件供应商创建的。 - Hans Passant
显示剩余3条评论
10个回答

24

当你没有指定编码时,例如使用File.WriteAllText()或StreamWriter生成的BOM。默认情况下使用UTF8编码并生成BOM。您可以通过其-encoding命令行选项告诉Java编译器。

最简单的方法是避免生成BOM。只需指定System.Text.Encoding.Default即可,在操作系统的默认代码页中写入文件,并且不会写入BOM。使用File.WriteAllText(String, String, Encoding)重载或StreamWriter(String, Boolean, Encoding)构造函数。

请确保你创建的文件不会被其他地方的机器编译。否则,它将产生mojibake


非常感谢。我终于解决了!也许有一天微软会摆脱BOM和其他所有的错误! - muckdog12
1
小心扔那个虫子炸弹。像Java编译器这样的相对较新的软件不能自动检测UTF8,这是相当惊人的。这似乎也是越南的一个问题:http://vietunicode.sourceforge.net/howto/java/encoding.html - Hans Passant

19

正如大家所说的,那是一个字节顺序标记。

javac不理解BOM,即使你尝试类似这样的操作也不行:

javac -encoding UTF8 Test.java

您需要去掉BOM或将源文件转换为另一种编码。Notepad ++可以转换单个文件的编码,我不知道Windows平台上有批处理实用程序可以这样做。

Java编译器将假定文件采用平台默认编码,因此如果使用此选项,则无需指定编码。


7
  1. 如果使用IDE,请通过属性面板指定Java文件编码。
  2. 如果不使用IDE,请使用高级文本编辑器(我可以推荐Notepad++),并将编码设置为“UTF without BOM”或“ANSI”,如果这适合您的话。

5
在这种情况下,请按照以下步骤1-7进行操作。
在Android Studio中。
1. Menu -> Edit -> Select All
2. Menu -> Edit -> Cut
  1. 打开新的Notepad.exe

在Notepad中:

4. Menu -> Edit -> Paste
5. Menu -> Edit -> Select All
6. Menu -> Edit -> Copy 

回到Android Studio

7. Menu -> Edit -> Paste

3

http://en.wikipedia.org/wiki/Byte_order_mark

字节顺序标记 (BOM) 是 Unicode 字符,用于标识文本文件或流的字节顺序(字节序)。其代码点为 U+FEFF。BOM 使用是可选的,并且如果使用,则应出现在文本流的开头。除了作为一个字节顺序标记的特定用途之外,BOM 字符也可以指示文本所编码的多种Unicode 表示中的哪一种。

BOM 是一个看起来奇怪的字符,有时会出现在 unicode 流的开头,给出编码的提示。在 Java 中,它通常被字符串处理工具隐式处理,因此您必须某种方式混淆了它,但是如果没有看到您的代码,很难看出问题出在哪里。

您可能可以通过在将字符串提供给 javac 之前手动剥离 BOM 来轻松解决它。它可能被视为空格符,因此尝试在输入字符串上调用 trim(),然后将输出馈送到 javac


我试图对它进行裁剪,但没有成功。顺便说一下,我正在使用VB.NET。 - muckdog12
关于“提示编码”的问题,我想指出:尽管BOM可以提示编码,但它并不是为此目的而设计的。正如其名称所示,它只告诉您字节顺序。实际上,在UTF-16和UTF-32(小端)中存在一种歧义,这意味着BOM不能可靠地将它们区分开来。BOM不能替代正确处理字符编码问题。 - Mark Byers
@Mark:好观点,说得好 - 我匆忙中过于简化了。 @muckdog:抱歉,帮不了你,vb.net 不是我的专长。 - skaffman
muckdog12:它只是像其他字符一样的字符。您可以使用任何通常用于删除字符的字符串操作来删除它。 - Mark Byers
谢谢,它帮助我解决了同样的问题。 - Ayusman
显示剩余3条评论

2

这是与BOM(字节顺序标记)字符相关的问题。BOM是用于定义文本文件字节顺序的Unicode字符,位于文件开头。Eclipse不允许该字符出现在文件开头,因此您必须将其删除。为此,请使用像Notepad ++这样的富文本编辑器,并使用“UTF-8 without BOM”编码保存文件。这样就可以解决问题了。

I have copy pasted the some content from a website to a Notepad++ editor,
it shows the "LS" with black background. Have deleted the "LS" content and 
have copy the same content from notepad++ to java file, it works fine.

2

我通过在我的TextEdit程序文件上右键单击并选择[替换],然后取消勾选智能引号来解决这个问题。


1

不必使用Notepad++,您可以直接使用Wordpad打开文件,然后另存为纯文本文档。


0

我也遇到了这个问题,因为我使用的是notepad++编码。在notepad++中输入代码非常方便,但是编译后出现错误“error: illegal character: '\u00bb'”。 解决方法: 在旧版本的notepad中开始编写代码(默认情况下会有),并保存。稍后可以使用notepad++进行修改。 它有效!!!


0

我曾经遇到过同样的问题,使用Windows Powershell命令echo echo "" > Main.java生成文件时出现了问题。我搜索了一下,似乎与编码有关。我使用file -i Main.java检查了文件的编码,结果是text/plain; charset=utf-16le

后来我删除了文件,并使用git bash重新创建了它,使用touch Main.java,这次文件成功编译了。我再次使用file -i命令检查文件编码,这次结果是Main.java: text/x-c; charset=us-ascii

接下来我在互联网上搜索,发现可以使用Cmdlet New-Item在Powershell中创建空文件。我使用New-Item Main.java创建了文件,并检查了它的编码,这次结果是Main.java: text/x-c; charset=us-ascii,这次编译成功了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接