如何通过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
相关产品推荐
相关产品推荐

