“Unmappable character for encoding UTF-8”错误。

79

我在下面的方法中遇到了编译错误。

public static boolean isValidPasswd(String passwd) {
    String reg = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~#;:?/@&!\"'%*=¬.,-])(?=[^\\s]+$).{8,24}$";
    return Pattern.matches(reg, passwd);
}
在 Utility.java 文件中,[76,74] 处存在一个无法映射的字符,该字符为双引号 (" )。
如何解决这个问题?谢谢。

在我的Eclipse中编译完全没问题,但是中间的那个'¬'看起来有点奇怪,你确定问题不是出在'¬'而不是双引号'"'上吗?你试过用其他编辑器保存文件并确保编码为UTF-8了吗? - esaj
我所做的是打开有问题的文件(希望您能推断出它抱怨的是哪个文件)。然后我只是再次保存了该文件(在写入一些随机字符以注册更改后,然后将它们删除)。然后重新保存后,我就可以编译了。我想重新保存会按照您的操作系统的本地方式保存文件。 - user798719
12个回答

49
你的源代码文件存在编码问题。它可能是使用ISO-8859-1编码的,但编译器设置为使用UTF-8。这将导致在使用字符时出现错误,因为在UTF-8和ISO-8859-1中,这些字符的字节表示不同。对于所有非ASCII字符都会发生这种情况,例如¬ NOT SIGN
你可以使用下面的程序模拟此问题。它只使用你的源代码行生成一个ISO-8859-1字节数组,并使用UTF-8编码进行“错误”的解码。您可以看到哪个位置出现了代码损坏。我在您的源代码中添加了2个空格,以使其位置74与¬ NOT SIGN匹配,这是唯一一个在ISO-8859-1编码和UTF-8编码中生成不同字节的字符。我猜这将与实际源文件的缩进匹配。
 String reg = "      String reg = \"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~#;:?/@&!\"'%*=¬.,-])(?=[^\\s]+$).{8,24}$\";";
 String corrupt=new String(reg.getBytes("ISO-8859-1"),"UTF-8");
 System.out.println(corrupt+": "+corrupt.charAt(74));
 System.out.println(reg+": "+reg.charAt(74));     

以下是输出结果(因标记混乱而出现问题):

String reg = "^(?=.[0-9])(?=.[a-z])(?=.[A-Z])(?=.[~#;:?/@&!"'%*=�.,-])(?=[^\s]+$).{8,24}$";: �

String reg = "^(?=.[0-9])(?=.[a-z])(?=.[A-Z])(?=.[~#;:?/@&!"'%*=¬.,-])(?=[^\s]+$).{8,24}$";: ¬

可在https://ideone.com/ShZnB上查看“实时”情况。

要解决此问题,请使用UTF-8编码保存源文件。


2
谢谢Michael!我在一个从旧的cvs服务器签出的Java项目中遇到了类似的问题。所以,为了解决它,我做了以下操作 - 确定并更改文件字符编码:find -name '*.java' -exec recode Latin-1..UTF-8 {} ; - Gilberto
7
请提供如何使用UTF-8编码保存源文件的示例,谢谢! - kellyfj
1
@kellyfj 这当然取决于用户使用的编辑器。我猜每个编辑器都有一些菜单提供这种选项。 - Michael Konietzka
帮了我一大忙!!谢谢。我的代码注释中有一个“-”字符,导致了问题。 - Kanad

16

我正在为一个始于2000年的遗留系统在Linux服务器上设置CI构建服务器。有一部分生成的PDF文件包含非UTF8字符。由于我们即将发布,所以我无法替换这些让我困扰的字符,但出于某些原因,我不能等到发布后一周再解决这个问题。幸运的是,Ant中的“javac”命令有一个“encoding”参数。

 <javac destdir="${classes.dir}" classpathref="production-classpath" debug="on"
     includeantruntime="false" source="${java.level}" target="${java.level}"

     encoding="iso-8859-1">

     <src path="${production.dir}" />
 </javac>

7
Java编译器假定您的输入采用UTF-8编码,可能是因为您已经指定或其为平台默认编码。然而,您的.java文件中的数据实际上不是以UTF-8编码的。问题可能是“¬”字符。请确保您选择的编辑器(或IDE)实际上将其文件保存为UTF-8编码格式。

5
对于IntelliJ用户来说,一旦您找到原始编码,这就非常容易了。您可以从窗口右下角选择编码,然后会弹出一个对话框,上面写着:
“您选择的编码('[编码类型]')可能会更改 '[您的文件]' 的内容。您想重新加载磁盘上的文件还是将文本转换并保存为新编码?”
因此,如果您的一些字符保存在某种奇怪的编码中,您应该先选择'Reload',以使用坏字符的编码加载文件。对我来说,这将把问号字符转换为它们的正确值。
IntelliJ可以判断您是否选择了正确的编码,并会发出警告。请返回并重试。
一旦您看不到错误字符,请将底部右侧的编码选择框更改回您最初打算使用的格式(如果您正在搜索此错误消息,则可能是UTF-8)。这次,在对话框上选择“Convert”按钮。
对我来说,我需要以“windows-1252”重新加载,然后转换回“UTF-8”。有问题的字符是单引号(‘和’),可能是从Word文档(或电子邮件)中复制并粘贴时使用了错误的编码,上述操作将把它们转换为UTF-8。

5
在Eclipse中尝试进入文件属性(Alt+Enter),并将 Resource→ 'Text File encoding' → Other 更改为UTF-8。重新打开文件并检查,在字符串/文件中会出现乱码字符,请删除它,然后保存文件。
把编码 Resource→ 'Text File encoding' 改回默认值。
编译和部署代码。

3
编译器正在使用UTF-8字符编码读取您的源文件。但该文件必须是由使用不同编码的编辑器编写的。请在设置为UTF-8编码的编辑器中打开文件,修复引号,并再次保存。
或者,您可以找到字符的Unicode代码点,并在源代码中使用Unicode转义。例如,字符A可以替换为Unicode转义\u0041。
顺便说一下,在使用matches()方法时,您不需要使用起始和结束行锚^和$。当使用matches()方法时,正则表达式必须与整个序列匹配。锚只有在使用find()方法时才有用。

3

感谢Michael Konietzka(https://dev59.com/7W445IYBdhLWcg3wLXSh#4996583)的回答。

我是在Eclipse / STS中完成的:

Preferences > General > Content Types > Selected "Text" 
    (which contains all types such as CSS, Java Source Files, ...)
Added "UTF-8" to the default encoding box down the bottom and hit 'Add'

1

以下代码在我的电脑上编译通过:

class E{
   String s = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~#;:?/@&!\"'%*=¼.,-])(?=[^\\s]+$).{8,24}$";
}

请参见:

enter image description here


1
你已经用 ¼ 替换了 ¬ - Luke Woodward
@Luke 嗯,那很奇怪,这就是复制/粘贴对我所做的.. 我已经添加了我的gvim窗口的截图。无论如何,我并没有真正回答这个问题,所以我会把它变成CW。 - OscarRyz

1
"error: unmappable character for encoding UTF-8"的意思是,Java发现了一个在UTF-8中没有表示的字符。因此,请在编辑器中打开文件并将字符编码设置为UTF-8。您应该能够找到一个在UTF-8中没有表示的字符。删除此字符并重新编译即可。

1
只需搜索 字符并将其更改为 "

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