如何用SMBJ从BufferedInputStream写入大文件?代码执行停滞排查
transferTo写入SMB共享文件时卡住,无法执行完成
问题现象
使用transferTo(...)向SMB共享目录写入文件时,目标文件持续增长,但System.out.println("Writing file done.");始终不执行,代码卡在transferTo调用处。
可能原因及解决方案
1. 缓冲输出流与SMB流的适配问题
BufferedOutputStream的缓存机制可能和SMB底层流的提交逻辑冲突,导致数据一直在缓冲中等待,或者transferTo无法触发流的完成信号。
解决方式:
- 直接使用SMB文件的原始输出流,去掉
BufferedOutputStream包装:try( File f = share.openFile(directory + "\\" + fileName, new HashSet(Arrays.asList(new AccessMask[]{AccessMask.GENERIC_ALL})), fileAttributes, SMB2ShareAccess.ALL, SMB2CreateDisposition.FILE_OPEN_IF, createOptions); OutputStream bo = f.getOutputStream() ) { System.out.println("Writing file to share..."); bi.transferTo(bo); System.out.println("Writing file done."); } - 或者在
transferTo执行后显式刷新缓冲:bi.transferTo(bo); bo.flush();
2. 源文件未终止输入
如果sourcePath对应的本地文件正在被其他进程持续写入,FileInputStream会不断读取新增数据,导致transferTo持续向目标文件写入,永远无法结束。
解决方式:
- 确认源文件为静态文件,无其他进程写入;
- 若需读取动态写入的文件,可先创建文件快照再读取,或限制读取字节数:
long sourceSize = new File(sourcePath).length(); bi.transferTo(bo, 0, sourceSize);
3. SMB创建选项的冲突
设置的FILE_SEQUENTIAL_ONLY选项提示服务器文件为顺序访问,但transferTo的底层实现可能不符合该选项的预期,导致服务器端阻塞。
解决方式:
- 移除
FILE_SEQUENTIAL_ONLY选项,使用默认创建配置:Set<SMB2CreateOptions> createOptions = new HashSet<>(); // 移除该行:createOptions.add(SMB2CreateOptions.FILE_SEQUENTIAL_ONLY);
4. 替换transferTo为手动循环读写
若上述方法无效,可绕过transferTo,手动实现缓冲区读写逻辑:
byte[] buffer = new byte[8192]; int readLen; while ((readLen = bi.read(buffer)) != -1) { bo.write(buffer, 0, readLen); } bo.flush();
内容的提问来源于stack exchange,提问作者user432024
相关产品推荐
相关产品推荐

