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

use*_*407 15 java samba jcifs

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

例如:

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

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

Sky*_*ker 8

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

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

建议1:

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

建议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(.)不是问题.字符编码服务器设置可能是问题.

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

SMB URL如下所示:

smb://[[[domain;]username[:password]@]server[:port]/[[share/[dir/]file]]][?param=value[param2=value2[...]]]
Run Code Online (Sandbox Code Playgroud)

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

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

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

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


字符检查和设置

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

System.out.println(Charset.defaultCharset());
Run Code Online (Sandbox Code Playgroud)

或者你可以发号施令

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

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

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

System.setProperty("jcifs.encoding", "UTF8");
Run Code Online (Sandbox Code Playgroud)

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

System.setProperty("jcifs.encoding", "Shift_JIS");
Run Code Online (Sandbox Code Playgroud)

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

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


使用日语设置客户端属性

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

下表显示了JapaneseJ2SE 5.0支持的编码集.新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                   |
----------------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

我已经为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 );
}
Run Code Online (Sandbox Code Playgroud)

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

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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

归功于 @ man叫哈尼

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


注意事项1:

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

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

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

<Connector port="8443" maxHttpHeaderSize="8192"
              maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
              enableLookups="false" disableUploadTimeout="true"
              acceptCount="100" scheme="https" secure="true"
              clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true" />
Run Code Online (Sandbox Code Playgroud)

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

资源链接:

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


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

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


vza*_*llo 4

看看heenenee评论,浏览一下你的服务器文件系统来检查真正的共享名是什么。我正在使用 Java 源代码 (UTF-8) 在 Samba 服务器 (UTF-8) 中测试对带有中间点和日语名称的网络共享的访问,没有出现任何问题。

\n\n
import java.io.File;\nimport java.io.IOException;\nimport java.nio.charset.Charset;\n\nimport org.apache.commons.io.FileUtils;\nimport org.apache.commons.io.IOUtils;\nimport org.junit.Test;\n\nimport jcifs.smb.SmbFile;\nimport junit.framework.TestCase;\n\npublic class JCifstest extends TestCase {\n\n    @Test\n    public void testJCifs() throws IOException {\n\n        System.out.println(Charset.defaultCharset());\n\n        SmbFile smbFile = new SmbFile("smb://myuser:mypass@myserver/basepath/\xe4\xba\xba\xe4\xba\x8b\xe9\x83\xa8\xe8\xa6\x81\xe5\x93\xa1\xe3\x83\xbb\xe3\x82\xb3\xe3\x82\xb9\xe3\x83\x88\xe7\xae\xa1\xe7\x90\x86\xe8\xaa\xb2/test.txt");\n        File destFile = new File("/tmp/" + smbFile.getName());\n        FileUtils.writeByteArrayToFile(destFile, IOUtils.toByteArray(smbFile.getInputStream()));\n        assertEquals("content", FileUtils.readFileToString(destFile));\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n