我正在尝试使用JCIFS将一些远程文件复制到Java中的本地驱动器。 远程计算机位于域内。域中的本地计算机不。
以下代码有效,但它真的慢(700Kb为2分钟......我有很多Mb ......):
SmbFile remoteFile = new SmbFile("smb://...")
OutputStream os = new FileOutputStream("/path/to/local/file");
InputStream is = remoteFile.getInputStream();
int ch;
while ((ch = is.read()) != -1) {
os.write(ch);
}
os.close();
is.close();
我想我可以使用SmbFile.copyTo(),但我不知道如何访问本地文件。如果我写下以下内容,则会出现连接错误:
localfile = new SmbFile("file:///path/to/localfile")
此问题与How to copy file from smb share to local drive using jcifs in Java?
有关答案 0 :(得分:5)
你只需要制作更大的缓冲区:
SmbFile remoteFile = new SmbFile("smb://...")
OutputStream os = new FileOutputStream("/path/to/local/file");
InputStream is = remoteFile.getInputStream();
int bufferSize = 5096;
byte[] b = new byte[bufferSize];
int noOfBytes = 0;
while( (noOfBytes = is.read(b)) != -1 )
{
os.write(b, 0, noOfBytes);
}
os.close();
is.close();
这里使用提到的代码对文件23 Mb进行了一些测试。
bufferSize = 1024经过时间:10.9587606066秒
bufferSize = 4096经过时间:5.6239662951秒
bufferSize = 5096经过时间:5.0798761245秒
bufferSize = 5096经过时间:4.879439883秒
bufferSize = 10240经过时间:4.0192989201秒
bufferSize = 50240经过时间:3.8876541543秒
bufferSize = 100240经过时间:3.742167582秒
答案 1 :(得分:4)
除了以及有效的 smb 网址外,无法构建SmbFile对象。请参阅http://jcifs.samba.org/src/docs/api/处的构造函数摘要,以及有关顶部SmbFile URL的讨论。
SmbFile URL具有以下语法: SMB:// [[[域]用户名[:密码] @]服务器[:端口] / [[份额/ [DIR /]文件]]]?[[PARAM =值[参数2 = 2 [...] ]
因此,如果您真的想避免使用输入流并使用copyTo(),那么您必须在本地计算机上拥有一个可以指向jCIFS的SMB共享。
如果您的本地计算机是Windows计算机,则可能有一些您可以访问的默认共享,例如C $。
所以,你可以这样做:
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain", "username", "password") //or whatever authentication works on your local machine.
SmbFile myFile = new SmbFile("smb://localhost/C\$/path/to/localfile", auth)
然后你可以使用remoteFile.copyTo(myFile)
。
如果您不在Windows主机上,则必须安装Samba并设置Samba共享才能连接到本地计算机上......如果您绝对不想使用inputStream,则必须再次使用。
答案 2 :(得分:4)
作为@maxmimko答案的替代方案,您还可以使用Apache Commons IO库,并使用IOUtils
为您处理复制:
NtlmPasswordAuthentication creds = new NtlmPasswordAuthentication("domain", "user", "password");
SmbFile remoteFile = new SmbFile("smb://REMOTEHOST/SHARE/path/to/file", creds);
try (
InputStream is = remoteFile.getInputStream();
OutputStream os = new FileOutputStream("/path/to/local/file");
) {
long bytesCopied = IOUtils.copyLarge(is, os);
} catch (IOException e) {
// handle exception here; log it?
}
// streams are automatically closed by try-with-resources block
还有IOUtils.copyLarge(InputStream is, OutputStream os, byte[] buffer)
,如果你想控制缓冲区大小,但我发现IOUtils
使用的默认值相对较好。