使用从zip文件中的文件名派生的特殊字符

时间:2012-06-29 10:37:21

标签: java mysql jdbc zip

这个问题涉及一个Tomcat 7 Web应用程序,该应用程序连接到MySQL(5.5.16)数据库。

当我打开zip文件时,其文件名在windows-1252字符集中编码,字符似乎由Java正确解释:

ZipFile zf = new ZipFile( zipFile, Charset.forName( "windows-1252" ) );
Enumeration entries = zf.entries();
while( entries.hasMoreElements() ) {
    ZipEntry ze = ( ZipEntry ) entries.nextElement();
    if( ! ze.isDirectory() ) {
        String name = ze.getName();
        System.out.println( name ); //prints correct filenames, e.g. café.pdf
    }
}

在ZipFile构造函数中省略Charset对象会导致异常。 zip文件中的文件名正确打印到标准输出,包括变音符号。 但是,当我随后尝试将文件名存储在数据库中时,e-acute被替换为问号(如mysql控制台客户端所示)。 我以前没有问题从Web应用程序插入特殊字符到MySQL。

当我在Java源代码中执行带é的INSERT时:

statement.executeUpdate( "insert into files (filename) values ('café.pdf')" );

é在MySQL中表现得很好。

此外,我的日志文件显示逗号而不是é: caf‚.pfd

有谁知道这里会发生什么?

3 个答案:

答案 0 :(得分:1)

正如您在评论部分中提到的,传入数据(压缩文件的名称)可以是不同的字符集。这对您来说是一个问题,因为您使用的是MySQL + JDBC链接,它会给您带来很多限制(例如MySQL中每列一个字符集,JDBC中每个连接只有一个字符集)。 p>

因此,我建议你将MySQL端的字符集(查找character_set_servercharacter_set_connection等变量)切换为UTF8,因为它可以让你传输和存储几乎任何字符你可能会收到。有关如何正确设置MySQL服务器的信息,请参阅here。请注意,MySQL服务器的设置可能具有挑战性,因此请不要犹豫,以获得额外的帮助。 JDBC将自动调整为服务器的character_set_connection变量,因此您不必更改Java应用程序中的任何内容。

您必须在应用程序中更改的一件事是您必须将所有传入数据转换为UTF8,以便将其发送并存储在MySQL服务器上。

祝你好运。

答案 1 :(得分:0)

在存储数据的表格中,请确保使用正确的排序规则以存储电子锐化字符

答案 2 :(得分:0)

问题已解决。 This post建议zip文件中的文件名编码可能不是windows-1252,而是IBM437。更改Charset

ZipFile zf = new ZipFile( zipFile, Charset.forName( "windows-1252" ) );

ZipFile zf = new ZipFile( zipFile, Charset.forName( "IBM437" ) );

给出了所需的结果:在MySQL中保存获取的文件名时,它与é。

一起正确存储

出了什么问题?

使用

将zip文件中包含的文件名打印到标准输出
System.out.println( name );

让我错误地认为zip文件中的文件名被解释得很好:当我使用windows-1252编码打开zip文件时,文件名用diacritic:café.pdf很好地打印到标准输出。使用其他字符编码,出现了不同的符号而不是é。

但是在this answer的帮助下打印é - Unicode的{​​{1}}值时,我能够看到用char编码打开zip文件时,实际的Unicode值不是windows-1252(带有急性的拉丁小写字母e),而是\u00e9(单个低9引号)。当我使用\u201a字符集打开ZipFile时,会显示正确的Unicode值DID。

当然,使用IBM437String打印到标准输出时,PrintStream也会与某个字符编码相关联。来自PrintStream Javadoc:

  

使用平台的默认字符编码将PrintStream打印的所有字符转换为字节。

我正在使用Windows XP。 当我创建新的PrintStream

PrintStream

一切都有意义:打开带有out = new PrintStream( System.out, true, "IBM437" ); 字符编码的zip文件,并使用新的PrintStream,é被正确打印。

There Ain't No Such Thing As Plain Text.