4

我正在尝试使用 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")

这个问题与如何在 Java 中使用 jcifs 将文件从 smb 共享复制到本地驱动器有关?

4

3 回答 3

5

您只需要制作更大的缓冲区:

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 秒

于 2013-07-11T06:46:50.807 回答
4

除非使用有效的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 =值2[...]]]

所以,如果你真的想避免使用输入流并使用 copyTo(),你必须在你的本地机器上有一个 SMB 共享,你可以将 jCIFS 指向。

如果您的本地计算机是 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。

于 2013-03-01T21:26:15.187 回答
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是相对较好的。

于 2015-11-05T17:39:07.430 回答