将文件名获取为UTF-8? ä,ü,ö…始终为\'?\'

问题描述

|| 我必须阅读某些文件名称,并将它们作为字符串放在列表中。这并不难,我只是遇到一些诸如ä,ö,ü之类的字符的问题……它们在我的字符串中始终是\'?\'。 有什么问题?好编码。好的,这应该很容易...多数民众赞成在我的想法。所以我尝试使用类似的功能
new String(insert.getBytes(\"UTF-8\")
要么
new String(insert.getBytes(\"ISO-8859-1\"),\"UTF-8\")
因为大多数文件是ISO-8859-1 它没有帮助。这是我的代码
...
File[] fileList = dir.listFiles();
String insert;
for(File f : fileList) {
...
insert=f.getName().substring(0,f.getName().length()-4);
                insert=insert.charat(0)+insert.substring(1,insert.length()).toLowerCase().replaceFirst(\"([0-9]*(_s?(i)?(_dat)?)*$)\",\"\").replaceFirst(\"_\",\" \");
...
System.out.println(\"test UTF8: \" + new String(insert.getBytes(\"UTF-8\"))); //not helping
System.out.println(\"test ISO,UTF8: \" + new String(insert.getBytes(\"ISO-8859-1\"),\"UTF-8\")); //not helping
...
names.add(insert);
}
最后,我的列表中有很多带有\'?\'字符的字符串。 如何解决问题?如果不仅有ISO-8859-1文件,最好的方法是什么? (可以说有很多未知的编码文件) 谢谢!     

解决方法

给定问题下来回的扩展注释,现在看来这要么是字体问题,要么(可能是)文件名编码问题。 我要求Lissy运行以下命令,让我们找出问题所在。如果她确定文件名中包含\“ä\”,但在文件名中加3时没有出现该字符,则此命令将告诉我们这是字体还是编码问题。
touch filenäme
ls filen*me
如果在
ls
的输出中显示\filenäme\,则表明问题出在将文件创建/复制到该系统上。如果创建文件的程序没有意识到文件系统编码是什么,或者太愚蠢而无法正确执行操作,则可能会发生这种情况。
convmv
程序可能是解决此问题的最佳方法。
convmv -f ENCODING -t utf8 -r .
问题是什么是正确的编码。可能包括UTF-16,cp850或iso8859-1。
convmv --list
将显示您(系统)当前已知的编码列表。由于上面列出的命令仅显示了它可能会执行的操作,因此可以安全地使用不同的编码运行几次,直到找到适用于所有文件的编码为止。 如果这是字体问题,我们将不得不进行调查     ,字符串中出现意外的问号,替换等,表示从一个字符集转换为另一个字符集时,某处某处无法识别该特定字符。 在您的情况下,问题可能发生在几个地方: 当您的Java程序正在从目录中读取文件名时(在
dir.listFiles()
调用中),可能会发生这种情况。 当您将字符打印到控制台流时,可能会发生这种情况。 在这两种情况下,根本原因很可能是Java认为语言环境设置应该与操作系统和/或命令外壳程序正在使用的设置之间的不匹配。 作为实验,尝试从命令行列出包含有问题的文件名的目录。您在那看到问号或其他图标吗? 要执行的第二个实验是修改Java程序,以将问题字符串之一转储为表示每个字符的字符代码的数字序列。您是否看到ASCII / Unicode
\'?\'
的字符代码。     ,文件名内容的编码与文件名本身的编码无关。 您应该从
System.out.println(insert)
获得正确的结果 如果不这样做,则意味着外壳具有与系统默认字符编码不同的字符编码(这种情况很少发生;通常是在外壳中切换编码的显式命令的结果)。 如果在外壳程序中列出目录时文件名正确显示,则我希望它们能正确显示,而无需在Java程序中指定编码。 如果shell无法显示字符(它将替换字符0xFFFD(...)替换为这些不可打印的字符),则您无法从Java应用程序中进行任何更改。您需要更改终端字符编码,安装正确的字体等;那是操作系统问题,而不是Java问题。 同时,即使您的终端无法显示正确的结果,Java程序也应该在没有您干预的情况下正确处理字符编码。
File
API背后的库正在为您的系统找出正确的字符编码,并进行必要的字符解码。同样,数据库驱动程序应与数据库协商以确定正确的编码,并代表您的应用程序对字节进行任何必要的编码。     ,您在评论中写道:   @mdrg:嗯,有一个问题。我必须阅读文件的名称,然后将它们放入数据库中。还有很多\'?\',不应该... – Lissy 27分钟前 我的猜测是,您要在其中插入文件名的列将US-ASCII指定为编码,并使用替换字符(在您的情况下是问号)替换该范围之外的字符。 因此,您必须在存储文件名的数据库表中找到该列的编码。各种产品具有检索该信息的各种语法。     ,在Java 1.6中,可以使用System.console()而不是System.out.println()来显示要突出显示的字符以进行控制台。
public class Test {
  public static void main(String args[]){
   String s = \"caractères français :  à é \\u00e9\"; // Unicode for \"é\"
   System.console().writer().println(s);
  }
}
输出是
C:\\temp>java Test
caractères français :  à é é