JCIFS 中某些非 ascii 字符的问题

2022-09-03 15:12:13

我正在使用JCIFS访问带有许多日语名称的文件共享,并且当其中的~字符时,我遇到了问题

例如:

the path 人事部/要員・コスト管理課/

第一部分是可以的,但第二部分会导致问题。这可能与“・”可以使用斜杠输入的事实有关,但我不确定。我尝试过逃避角色,但这似乎并不能解决问题。你有任何线索可能导致它吗?


答案 1

U + 30FB(片假名中间点)的更新:

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

建议-1:

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

建议-2:

不同的人面临着同一类型的问题。因此,他们以各种方式进行了尝试。

有人说,

  • 用 dot(.) 替换它解决了这个问题。
  • KATAKANA MIDDLE DOT (・)是 s 的双倍字符。如果要使用片假名(日语)中点,请考虑改用半角片假名中点。
  • 切换到常规子弹,它工作正常。

如果你看到,他们已经为.在 github 存储库中查看twitter-textKATAKANA MIDDLE DOT (・)

资源链接

片假名中点问题在Twitter文本中解决

但attom开发人员chrissimpkins在下面指出

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

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


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

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

SMB 网址将如下所示:

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

jCIFS还可以对服务器和工作组进行寻址。

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

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

如果 SMB URL (domain;user:pass) 的用户信息组件包含保留字符,则必须对其进行 URL 编码。根据 RFC 2396,这些字符是非 US-ASCII 字符,但是大多数元字符 jCIFS 可以正常工作,除了用于将 userinfo 组件与服务器分隔的 '@' 和 '%' (URL 转义字符本身)。


字符检查和设置

然后,您必须知道您正在使用哪个字符集。通过使用下面的代码,您可以得到:

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

或者你可以给命令

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

CIFS 使用其中之一或默认代码页。JCIFS 使用的缺省代码页是 Cp850 或 US_ASCII。UTF-16LE

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

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

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

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

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

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


使用日语设置客户端属性

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

下表显示了 J2SE 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                   |
----------------------------------------------------------------------------------------------

我分享了一些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 );
}

您还可以读/写,删除,创建目录,重命名,列出目录的内容,列出网络上的工作组/ ntdomain和服务器,列出服务器的共享,打开命名管道,验证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;
        }
    }

功劳归@man called haney

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


注意事项-1:

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

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

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

<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" />

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

资源链接:

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


对于非 ASCII 字符,您可以遍历

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

答案 2

看看 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));
    }
}

推荐