JCIFS中存在某些非ascii字符的问题

我正在使用JCIFS来访问一个包含很多日文名称的文件共享,当我在其中的字符时遇到问题

例如:

路径人事部/要员·コスト管理课程/

第一部分没问题,但第二部分引起了问题。 这可能与“·”可以使用斜线输入的事实有关,但我不确定。 我试过逃避角色,但似乎没有解决问题。 你有什么可能导致它的线索吗?

U + 30FB更新(KATAKANA MIDDLE DOT):

正如@ sergey-tachenov指出该问题与U+30FBU+30FB MIDDLE DOT)有关,那么它需要解决。 出于这个原因,我想分享一些以前的项目经验和建议。

建议1:

我的一个项目,我们正在为项目制作一些手册。 手册有各种语言版本。 我们遇到了同样的问题。 我们使用Lotus Notes 。 在这种情况下, 我们制作了一些filter,将这些字符或字形更改为点 。 之后莲花笔记创建文件夹和文件名,稍后将其用作路径。 所以这个问题就这样解决了。 如果您有这种类型的选项,那么您可以轻松修复。

建议2:

各种各样的人都面临着同样的问题。 所以他们以各种方式尝试过。

有人说,

  • 用点(。)替换它解决了这个问题。
  • KATAKANA MIDDLE DOT (・)是双倍宽度的角色。 如果您想使用片假名(日语)中点,请考虑使用HALFWIDTH KATAKANA MIDDLE DOT。
  • 切换到常规子弹,它工作正常。

如果您看到twitter-text ,他们已经为KATAKANA MIDDLE DOT (・)制作了解决方案。 请参阅github repo

资源链接

Katakana Middle Dot问题在Twitter-Text中得到解决

但是开发人员chrissimpkins表示如下

我可以确认我们在常规Hack字体中没有片假名中间点字形(U + 30FB)。 有一个中间点(U + 00B7),它具有你在这里的外观。 我可以确认U + 00B7字形与常规集的其余部分(以及所有其他变体集)具有相同的固定宽度间距。

资源链接: https //github.com/atom/atom/issues/9115


首先,我想与您分享点或句点(。)是ASCII字符 。 所以dot(。)不是问题。 字符编码服务器设置可能是个问题。

只能使用ASCII字符集通过Internet发送URL。 如果URL包含ASCII集之外的字符,则必须转换URL。

SMB URL如下所示:

 smb://[[[domain;]username[:password]@]server[:port]/[[share/[dir/]file]]][?param=value[param2=value2[...]]] 

jCIFS还可以处理服务器和工作组。

重要提示:表示工作组,服务器,共享或目录的所有SMB URL都需要使用尾部斜杠“/”。

当使用带有'smb://' URL的java.net.URL类时,首先需要调用static jcifs.Config.registerSmbURLHandler(); 方法。 这是注册SMB协议处理程序所必需的。

如果SMB URL(user; user:pass)的userinfo组件包含保留字符,则必须对其进行URL编码。 根据RFC 2396,这些字符是非US-ASCII字符和大多数元字符,但是jCIFS可以正常使用除了’@’之外的任何东西,用于从服务器界定userinfo组件,’%’是URL转义字符本身。


字符检查和设置

然后你必须知道你正在使用哪个charset。 通过使用以下代码,您可以获得:

 System.out.println(Charset.defaultCharset()); 

或者你可以发号施令

$ testparm -v | grep dos $ testparm -v | grep dos显示Samba的默认OEM编码

CIFS使用UTF-16LE或默认代码页。 JCIFS使用的默认代码页是Cp850或US_ASCII。

在jCIFS中,您可以将其设置为UTF-8并检查:

 System.setProperty("jcifs.encoding", "UTF8"); 

然后对于日本语区域,您可以尝试

 System.setProperty("jcifs.encoding", "Shift_JIS"); 

共享名称,密码,在某些情况下,包含非ASCII字符的文件和目录名称可能无法正确处理。 默认情况下,此属性为Cp860,即MS-DOS Latin1。

注意:Cp860字符集转换器位于jre / lib / charsets.jar中,AFAIK仅受Sun的JRE国际化版本支持。 如果Cp860不可用,则会发生exception。 要避免此exception,可以将jcifs.encoding设置为ASCII,但不能正确处理具有非ASCII字符的共享名称和密码。 要确定jCIFS是否正确处理这些字符,请创建包含非ASCII字符(例如Grüße)的共享,然后尝试使用ListFiles.java示例程序列出该共享。


使用日语设置客户端属性

对于日语 ,您可以尝试设置jcifs.encoding = Shift_JIS

下表显示了J2SE 5.0支持的Japanese编码集 。 新java.nio API使用的规范名称在很多情况下与java.io和java.lang API中使用的名称不同。

 ---------------------------------------------------------------------------------------------- |Canonical Name for | Canonical Name for java.io | Description | | java.nio API | and java.lang API | | ---------------------------------------------------------------------------------------------- | EUC-JP | EUC_JP | JISX 0201, 0208 and 0212, EUC encoding | | | | Japanese | ---------------------------------------------------------------------------------------------- | ISO-2022-JP | ISO2022JP | JIS X 0201, 0208, in ISO 2022 form, | | | | Japanese | ---------------------------------------------------------------------------------------------- | Shift_JIS | SJIS | Shift-JIS, Japanese | ---------------------------------------------------------------------------------------------- | windows-31j | MS932 | Windows Japanese | ---------------------------------------------------------------------------------------------- | x-euc-jp-linux | EUC_JP_LINUX | JISX 0201, 0208, EUC encoding Japanese | ---------------------------------------------------------------------------------------------- | x-eucJP-Open | EUC_JP_Solaris | JISX 0201, 0208, 0212, EUC encoding | | | | Japanese | ---------------------------------------------------------------------------------------------- | x-IBM33722 | Cp33722 | IBM-eucJP - Japanese (superset of 5050) | ---------------------------------------------------------------------------------------------- | x-IBM930 | Cp930 | Japanese Katakana-Kanji mixed with 4370 | | | | UDC, superset of 5026 | ---------------------------------------------------------------------------------------------- | x-IBM939 | Cp939 | Japanese Latin Kanji mixed with 4370 | | | | UDC, superset of 5035 | ---------------------------------------------------------------------------------------------- | x-IBM942 | Cp942 | IBM OS/2 Japanese, superset of Cp932 | ---------------------------------------------------------------------------------------------- | x-IBM943 | Cp943 | IBM OS/2 Japanese, superset of Cp932 | | | | and Shift-JIS | ---------------------------------------------------------------------------------------------- 

我已经为JCIFS分享了一些完整的代码示例。 你可以尝试一下

  1. 使用Java在网络共享文件夹上复制文件
  2. 使用Java将资源复制到Windows网络和从Windows网络复制资源
  3. Java教程 – 使用JCIFS使用用户名和密码将文件复制到共享网络驱动器

以下是检索文件的示例:

 import jcifs.smb.*; jcifs.Config.setProperty( "jcifs.netbios.wins", "192.168.1.220" ); NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain", "username", "password"); SmbFileInputStream in = new SmbFileInputStream("smb://host/c/My Documents/人事部/要員・コスト管理課/somefile.txt", auth); byte[] b = new byte[8192]; int n; while(( n = in.read( b )) > 0 ) { System.out.write( b, 0, n ); } 

您还可以读/写,删除,创建目录,重命名,列出目录内容,列出网络上的工作组/ ntdomains和服务器,列出服务器的共享,打开命名管道,validationWeb客户端等等。

SmbFile,SmbFileInputStream和SmbFileOutputStream类类似于File,FileInputStream和FileOutputStream类

通过使用FileInputStream和FileOutputStream,代码如下所示:

 SmbFile[] files = getSMBListOfFiles(sb, logger, domain, userName, password, sourcePath, sourcePattern); if (files == null) return false; output(sb, logger, " Source file count: " + files.length); String destFilename; FileOutputStream fileOutputStream; InputStream fileInputStream; byte[] buf; int len; for (SmbFile smbFile: files) { destFilename = destinationPath + smbFile.getName(); output(sb, logger, " copying " + smbFile.getName()); try { fileOutputStream = new FileOutputStream(destFilename); fileInputStream = smbFile.getInputStream(); buf = new byte[16 * 1024 * 1024]; while ((len = fileInputStream.read(buf)) > 0) { fileOutputStream.write(buf, 0, len); } fileInputStream.close(); fileOutputStream.close(); } catch (SmbException e) { OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, SMP issue: " + e.getMessage(), e); e.printStackTrace(); return false; } catch (FileNotFoundException e) { OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, file not found: " + e.getMessage(), e); e.printStackTrace(); return false; } catch (IOException e) { OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, IO problem: " + e.getMessage(), e); e.printStackTrace(); return false; } finally { OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, IO problem: " + e.getMessage(), e); e.printStackTrace(); return false; } } 

归功于 @ man叫哈尼

资源链接: 如何使用Java中的jcifs将文件从smb共享复制到本地驱动器?


注意事项1:

有关HTTPS和Tomcat用户的更多注意事项,

在大多数情况下,通过HTTP运行的URL工作正常,但在使用HTTPS(即通过SSL)时则不行 。 这通常会导致HTTPS URL中的Unicode(非ASCII)字符在URL中显示不正确,并且服务页面包含大量错误当conf/server.xml中的HTTPS连接器定义中未定义useBodyEncodingForURI="true"标志时会发生这种情况运行JIRA的Apache Tomcat应用程序服务器的conf/server.xml 。 默认情况下,此标志在JIRA的“推荐”分发安装中设置为此标志。

但是,在JIRA WAR设置中,情况可能并非如此。 因此,请确保useBodyEncodingForURI="true"标志包含在运行JIRA的Apache Tomcat安装的conf/server.xml文件的以下元素中:

  

在所有连接器定义(ie both the HTTP and the HTTPS connectors)指定useBodyEncodingForURI="true"之后,如在Tomcat 6.0或7.0文档上安装JIRA的“修改Tomcat server.xml”部分所述

资源链接:

如何使HTTPS URL中的Unicode“非ASCII”字符正确显示


对于非ASCII字符,您可以通过

  1. (请)停止在URL中使用不安全的字符
  2. 我可以在URL中使用非ASCII字符吗?
  3. 是否建议在URL中使用非ASCII字符?

看看heenenee的评论,通过服务器文件系统走一走,看看真正的共享名称是什么。 我正在测试使用Java源(UTF-8)的Samba服务器(UTF-8)中的中间点和日语名称访问网络共享没有问题。

 import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.Test; import jcifs.smb.SmbFile; import junit.framework.TestCase; public class JCifstest extends TestCase { @Test public void testJCifs() throws IOException { System.out.println(Charset.defaultCharset()); SmbFile smbFile = new SmbFile("smb://myuser:mypass@myserver/basepath/人事部要員・コスト管理課/test.txt"); File destFile = new File("/tmp/" + smbFile.getName()); FileUtils.writeByteArrayToFile(destFile, IOUtils.toByteArray(smbFile.getInputStream())); assertEquals("content", FileUtils.readFileToString(destFile)); } }