JCIFS 中某些非 ascii 字符的问题
我正在使用JCIFS访问带有许多日语名称的文件共享,并且当其中的~字符时,我遇到了问题
例如:
the path 人事部/要員・コスト管理課/
第一部分是可以的,但第二部分会导致问题。这可能与“・”可以使用斜杠输入的事实有关,但我不确定。我尝试过逃避角色,但这似乎并不能解决问题。你有任何线索可能导致它吗?
我正在使用JCIFS访问带有许多日语名称的文件共享,并且当其中的~字符时,我遇到了问题
例如:
the path 人事部/要員・コスト管理課/
第一部分是可以的,但第二部分会导致问题。这可能与“・”可以使用斜杠输入的事实有关,但我不确定。我尝试过逃避角色,但这似乎并不能解决问题。你有任何线索可能导致它吗?
正如@sergey-tachenov指出的那样,这个问题与(片假名中间点)有关,那么它需要解决。出于这个原因,我想分享一些以前的项目经验和建议。U+30FB
我的一个项目,我们正在为项目制作一些手册。该手册有各种语文。在那里,我们遇到了相同类型的问题。我们使用了 .在这种情况下,我们制作了一些过滤器,将这些字符或字形更改为点。之后,lotus笔记创建文件夹和文件名,这些名称稍后用作路径。所以这个问题就这样解决了。如果您有这种类型的选项,那么您可以轻松修复。Lotus Notes
不同的人面临着同一类型的问题。因此,他们以各种方式进行了尝试。
有人说,
KATAKANA MIDDLE DOT (・)
是 s 的双倍字符。如果要使用片假名(日语)中点,请考虑改用半角片假名中点。如果你看到,他们已经为.在 github 存储库中查看twitter-text
KATAKANA MIDDLE DOT (・)
但attom开发人员chrissimpkins在下面指出
我可以确认我们在常规的Hack字体中没有片假名中间点字形(U + 30FB)。有一个中间点(U + 00B7),它将具有您在这里追求的外观。我可以确认 U+00B7 字形与常规集的其余部分(以及所有其他变体集)具有相同的固定宽度间距。
资源链接:https://github.com/atom/atom/issues/9115
首先,我想与您分享点或句点(.)是ASCII字符。所以 dot(.) 不是问题所在。字符编码和服务器设置可能是问题所在。
URL 只能使用 ASCII 字符集通过互联网发送。如果 URL 包含 ASCII 集之外的字符,则必须转换该 URL。
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的完整代码示例。你可以试一试
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共享复制到本地驱动器?
在大多数情况下,通过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 中正确显示
看看 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));
}
}