0
点赞
收藏
分享

微信扫一扫

SMB 共享目录递归遍历文档


SMB 共享目录递归遍历文档

一、背景说明

我们需要通过 Java 程序访问 SMB 协议的共享目录,递归遍历目标路径下的所有文件和子目录,输出其基本信息(名称、类型、大小等)。本文档提供完整的代码实现和操作说明。

二、开发环境

  • 语言:Java
  • 依赖库:
  • SMBJ:用于实现 SMB 协议的交互。

Maven 依赖

在项目的 pom.xml 文件中添加 SMBJ 的依赖:

xml


复制代码
<dependency>
    <groupId>com.hierynomus</groupId>
    <artifactId>smbj</artifactId>
    <version>0.13.0</version>
</dependency>

三、代码实现

完整代码

java


复制代码
import com.hierynomus.smbj.SMBClient;
import com.hierynomus.smbj.connection.Connection;
import com.hierynomus.smbj.session.Session;
import com.hierynomus.smbj.share.DiskShare;
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;

public class SMBRecursiveDirectoryExample {
    public static void main(String[] args) {
        // 目标 SMB 服务器和共享目录信息
        String serverAddress = "x.x.x.x"; // SMB 服务器地址
        String domain = "x";                // 域/工作组
        String username = "x";                // 用户名
        String password = "xxx";          // 密码
        String shareName = "管理中心";         // SMB 共享文件夹名称
        String startPath = "07人事管理\\02员工档案"; // 起始路径

        // 创建 SMB 客户端实例
        SMBClient client = new SMBClient();

        try (Connection connection = client.connect(serverAddress)) {
            // 使用指定的域、用户名和密码认证
            Session session = connection.authenticate(
                new com.hierynomus.smbj.auth.AuthenticationContext(username, password.toCharArray(), domain)
            );

            // 连接到共享目录
            DiskShare share = (DiskShare) session.connectShare(shareName);

            // 打印共享目录内容(递归遍历)
            System.out.println("共享目录内容:");
            listDirectory(share, startPath, 0); // 从指定路径开始遍历
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 递归遍历目录内容
     *
     * @param share SMB 共享实例
     * @param path 当前目录路径
     * @param level 当前目录层级,用于缩进
     */
    private static void listDirectory(DiskShare share, String path, int level) {
        try {
            // 获取指定路径下的文件和目录列表
            for (FileIdBothDirectoryInformation item : share.list(path)) {
                String name = item.getFileName();

                // 跳过当前目录和父目录
                if (name.equals(".") || name.equals("..")) continue;

                // 判断是否是目录
                boolean isDirectory = (item.getFileAttributes() & 0x10) != 0;

                // 打印目录或文件名,并根据层级增加缩进
                System.out.printf("%s名称: %s, 是否目录: %b, 大小: %d 字节\n",
                    "  ".repeat(level), name, isDirectory, item.getEndOfFile());

                // 如果是目录,递归遍历子目录
                if (isDirectory) {
                    String subPath = path.isEmpty() ? name : path + "\\" + name;
                    listDirectory(share, subPath, level + 1);
                }
            }
        } catch (Exception e) {
            System.err.printf("无法访问目录 %s: %s\n", path, e.getMessage());
        }
    }
}

四、代码逻辑详解

1. 主方法

  • 定义 SMB 服务器地址、用户凭据和共享目录信息。
  • 创建 SMBClient 实例,建立连接并认证。
  • 使用 DiskShare 接口访问共享目录。
  • 从指定路径开始递归遍历目录内容。

2. 递归方法 listDirectory

功能
  • 遍历给定路径下的所有文件和目录。
  • 输出文件/目录的名称、类型和大小。
  • 对于目录,递归调用自身以深入子目录。
关键实现
  • 过滤系统目录:通过跳过 "."".." 避免循环引用。
  • 目录判断:通过文件属性中的0x10位判断是否为目录:

java


复制代码
boolean isDirectory = (item.getFileAttributes() & 0x10) != 0;

  • 路径拼接:根据当前路径动态生成子目录路径:

java


复制代码
String subPath = path.isEmpty() ? name : path + "\\" + name;

五、运行结果

假设共享目录 \\x.x.x.x\管理中心\07人事管理\02员工档案 的结构如下:

markdown


复制代码
02员工档案
├── 文件1.txt
├── 文件2.pdf
└── 子文件夹
    ├── 子文件1.docx
    └── 子文件2.xlsx

程序运行后输出如下:

yaml


复制代码
共享目录内容:
名称: 文件1.txt, 是否目录: false, 大小: 1234 字节
名称: 文件2.pdf, 是否目录: false, 大小: 5678 字节
名称: 子文件夹, 是否目录: true, 大小: 0 字节
  名称: 子文件1.docx, 是否目录: false, 大小: 3456 字节
  名称: 子文件2.xlsx, 是否目录: false, 大小: 7890 字节

六、常见问题及解决方案

1. 访问无权限目录

问题:某些目录无法访问,抛出异常。 解决

  • 确保 SMB 用户有足够权限访问目标目录及其子目录。
  • 捕获异常并输出错误信息,跳过无权限目录。

2. 中文路径编码问题

问题:路径包含中文时,可能抛出 FileNotFoundException解决

  • 确保项目使用 UTF-8 编码。
  • 检查 SMB 服务器是否支持 Unicode。

3. 文件属性获取异常

问题:无法判断文件是否为目录。 解决

  • 使用 getFileAttributes() 返回值的位运算判断属性。

七、总结

本文档通过 Java 和 SMBJ 库实现了 SMB 共享目录的递归遍历,解决了中文路径处理、目录权限不足等问题。代码逻辑清晰,可扩展性强,适用于大多数 SMB 文件共享场景。


举报

相关推荐

0 条评论