使用UTF-8的getBytes()不适用于大写德语变音符号

对于开发,我正在使用ResourceBundle直接从IDE中的resources-directory读取UTF-8编码的属性文件(我在Eclipse中的文件属性中设置该文件)(native2ascii用于生产的方式),例如:

 menu.file.open.label=&Öffnen... label.btn.add.name=&Hinzufügen label.btn.remove.name=&Löschen 

由于这会在使用非ASCII字符时导致字符编码问题,我以为我会满意:

 ResourceBundle resourceBundle = ResourceBundle.getBundle("messages", Locale.getDefault()); String value = resourceBundle.getString(key); value = new String(value.getBytes(), "UTF-8"); 

嗯,它确实适用于小写德语变音符号,但不适用于大写的变音符号, ß也不起作用。 这是使用getString(key)读取的值和使用new String(value.getBytes(), "UTF-8")转换后的值:

 &Löschen => &Löschen &Hinzufügen => &Hinzufügen &Ã?ber => &??ber &SchlieÃ?en => &Schlie??en &Ã?ffnen... => &??ffnen... 

最后三个应该是:

 &Ã?ber => &Über &SchlieÃ?en => &Schließen &Ã?ffnen... => &Öffnen... 

我想我离真相不太远,但我在这里错过了什么?

谷歌发现了类似的东西 ,但仍然没有答案。

编辑:更多代码

问题是你在没有指定编码的情况下调用String.getBytes() – 它将使用默认的平台编码。 然后,您将使用该操作的二进制结果, 就好像它是UTF-8一样。

如果你在两个方向都使用UTF-8,那就没关系了:

 // Should be a round-trip value = new String(value.getBytes("UTF-8"), "UTF-8"); 

…但是如果您尝试使用它来读取UTF-8编码的属性文件而不告诉正在执行初始读取的代码,那将无效。

您提供的代码基本上总是错误的方法。 你的“因为这会导致字符编码问题”表明你已经遇到过早期的问题 – 所以我会回到那个问题,而不是尝试应用破解的修复程序。 如果你在构建ResourceBundle时已经丢失了数据,那么以后再回来就太晚了……你需要确保正确加载ResourceBundle本身。

准确告诉我们您使用ResourceBundle遇到的问题,我们可以看看是否可以解决根本原因。

编辑:目前尚不清楚你是如何运行native2ascii。 修复可能就像更改使用一样简单:

 native2ascii -encoding UTF-8 input.properties output.properties 

一些说明:

  • 如果它是一个String它是UTF-16,如果它不是,它是一个损坏的字符串(并且修复太迟了。)
  • new String(value.getBytes(), "UTF-8"); – 此代码(最好)在使用UTF-8作为默认编码的系统上不执行任何操作; 否则会破坏字符串。
  • .properties文件必须是ISO 8859-1( Properties类型支持其他格式和编码,但我不知道如何告诉ResourceBundle 。)
  • System.out可以引入自己的转码错误( PrintStream将UTF-16字符串编码为默认编码;接收设备必须使用相同的编码对字节进行解码。)

我怀疑你正试图在错误的地方解决你的问题。

您正在使用与要解码的编码不同的编码对文本进行编码。

请尝试使用相同的字符集进行编码和解码。

 value = new String(value.getBytes("UTF-8"), "UTF-8"); 

 String s = "ßßßßß"; s += s.toUpperCase(); s = new String(s.getBytes("UTF-8"), "UTF-8"); System.out.println(s); 

版画

 ßßßßßSSSSSSSSSS 

今天我和一位同事交谈,他和其他答案提到的几乎一样。 所以我试图实现Jon Skeet所提到的,这意味着创建与生产中相同的文件。 由于每次更改资源后重建项目都是不可能的,我没有做任何解决这个问题的事情(我想这对某些人来说是新的)让我把它排除在外(即使它可能仅仅是为了个人参考;))。 简而言之,它使用Eclipse的项目构建器。

  1. 创建一个Ant样式的build.xml

              

    其目的是删除目标目录中的属性文件,并使用native2ascii重新创建它们。 删除是必要的,因为native2ascii不会覆盖现有文件。

  2. 在Eclipse中转到项目属性并选择“Builders”,单击“New …”,选择“Ant Builder”(这是运行配置的略微增强的编辑器)
  3. 在“Main”中,让“Buildfile”指向Ant脚本,将“Base Directory”设置为${project_loc}
  4. 在“刷新”中勾选“完成后刷新资源”并选择“包含所选资源的项目”
  5. 在“目标”中单击“自动构建”旁边的“设置目标”,然后在那里选择native-to-ascii (请注意,由于某种原因我不得不再次执行此操作)
  6. 对于每个人来说,这可能不是必需的,但在“JRE”中选择适当的执行环境
  7. 在“构建选项”中勾选“分配控制台”(但是,您可能希望保持此选项,直到您看到它全部正常工作)
  8. “申请”,“确定”
  9. 我被告知新创建的构建器应该位于Java Builder下面(使用向上/向下按钮)
  10. 在“Java Build Path”中选择包含资源的源文件夹(对我来说是src/main/resources )并为**/*.properties添加一个排除**/*.properties

应该是这样的。 如果编辑属性文件并保存,则应在输出文件夹中自动将其转换为ASCII。 您可以尝试输入ü ,最终应该是\u00fc

请注意,如果您有很多属性文件,这可能需要一些时间。 每次按键后都不要保存。 🙂