如何使用 JCIFS 将文件从 SMB 共享复制到不在域中的本地驱动器
Posted
技术标签:
【中文标题】如何使用 JCIFS 将文件从 SMB 共享复制到不在域中的本地驱动器【英文标题】:How to copy file from SMB share to local drive not in domain with JCIFS 【发布时间】:2013-01-22 20:28:41 【问题描述】:我正在尝试使用 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?有关
【问题讨论】:
【参考方案1】:你只需要做更大的缓冲区:
SmbFile remoteFile = new SmbFile("smb://...")
try(OutputStream os = new FileOutputStream("/path/to/local/file"))
try(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);
这里我使用提到的代码对 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 秒
【讨论】:
制作 InputStream 并复制到目标文件需要太多时间。我有 1KB 的文件,完成活动需要超过 1 分钟。有什么办法让它快吗???【参考方案2】:无法使用有效的 smb URL 构造 SmbFile 对象除了。请参阅http://jcifs.samba.org/src/docs/api/ 的构造函数摘要,以及顶部有关 SmbFile URL 的讨论。
SmbFile URL 具有以下语法: smb://[[[domain;]username[:password]@]server[:port]/[[share/[dir/]file]]][?[param=value[param2=value2[...] ]]
因此,如果您真的想避免使用输入流并使用 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 共享以连接到您的本地计算机...再次,如果您绝对一心要避免使用 inputStreams。
【讨论】:
值得注意的是,nagualjj 表示您也可以使用格式“C:/path/to/file”,但我没有成功。 ***.com/questions/13359164 什么是remoteFile
??
从原始问题来看,remoteFile
是 OP 想要复制到另一个位置的 SmbFile(在本例中为 myFile
)。
哦,是的,谢谢。我实现了这个及其工作。但是它花费了太多时间来制作 InputStream 和复制。有什么办法让它快点?【参考方案3】:
作为@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
使用的默认值总体上比较好。
【讨论】:
以上是关于如何使用 JCIFS 将文件从 SMB 共享复制到不在域中的本地驱动器的主要内容,如果未能解决你的问题,请参考以下文章