You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过smbj获取SMB共享文件的实际大小?

如何用SMBJ获取SMB共享文件的实际字节大小?

我正在使用smbj库读取SMB共享中的文件,需要将文件内容读取到byte数组中,但读取前得知道文件实际大小。目前只能获取到文件的分配大小,这个数值通常比实际文件大,所以请问怎么获取准确的实际字节大小?

我的错误代码如下:

SMBClient client = new SMBClient();
try(Connection connection = client.connect(hostname)) {
  AuthenticationContext ac = new AuthenticationContext(user, password.toCharArray(), domain);
  Session session = connection.authenticate(ac);

  // 连接共享
  try (DiskShare share = (DiskShare) session.connectShare(shareName)) {
      FileAllInformation fileInfo = share.getFileInformation(path);
      File file = share.openFile(path, EnumSet.of(AccessMask.GENERIC_READ), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null);

      long fileSize = fileInfo.getStandardInformation().getAllocationSize();

      // 这里会抛IOException,因为实际读取的字节数可能小于分配大小
      byte[] bytes = IOUtils.toByteArray(fileIn, fileInfo.getStandardInformation().getAllocationSize());
  }
}

补充说明

  • 为何要读取到byte数组?我正在为Apache Nutch编写协议插件,其API要求以byte[]形式提供文件内容。
  • 为何不直接让IOUtils读取完整文件?调用IOUtils.toByteArray(fileIn)可读取完整文件,但当文件超过2GB时会抛出IOException。因此我希望指定读取的最大字节数,IOUtils的IOUtils.toByteArray(fileIn, amount)方法支持此操作,但如果文件实际大小小于指定值,该调用会失败。因此我需要先获取准确的文件大小。

解决方案:使用getEndOfFile()获取实际文件大小

SMBJ的FileStandardInformation类提供了getEndOfFile()方法,它返回的是文件的实际逻辑大小,也就是文件中已写入数据的字节总数,和你在系统中看到的文件大小一致,而非磁盘分配的空间大小。

只需修改代码中获取文件大小的行:

// 替换原有的getAllocationSize()调用
long fileSize = fileInfo.getStandardInformation().getEndOfFile();

修改后的完整代码:

SMBClient client = new SMBClient();
try(Connection connection = client.connect(hostname)) {
  AuthenticationContext ac = new AuthenticationContext(user, password.toCharArray(), domain);
  Session session = connection.authenticate(ac);

  // 连接共享
  try (DiskShare share = (DiskShare) session.connectShare(shareName)) {
      FileAllInformation fileInfo = share.getFileInformation(path);
      File file = share.openFile(path, EnumSet.of(AccessMask.GENERIC_READ), null, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN, null);

      // 获取实际文件大小
      long fileSize = fileInfo.getStandardInformation().getEndOfFile();

      // 安全读取指定字节数
      byte[] bytes = IOUtils.toByteArray(file.getInputStream(), fileSize);
  }
}

关键区别说明

  • getEndOfFile():对应SMB协议的EndOfFile字段,代表文件的实际数据长度,是你需要的准确值。
  • getAllocationSize():磁盘为文件分配的物理空间大小,受文件系统簇大小影响,通常大于实际文件大小,不适合作为读取字节数的依据。

内容的提问来源于stack exchange,提问作者queeg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:17:39