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

使用Gson序列化apache-commons-io获取的目录文件树仅返回部分内容

解决Gson序列化File列表仅返回部分内容的问题

这个问题我之前也碰到过,核心原因是File对象存在循环引用(比如子目录的getParentFile()会指向父目录,父目录又包含子目录),Gson默认序列化时遇到循环引用会直接停止,所以只能得到部分内容。另外直接序列化File对象会包含很多我们不需要的内部属性,也容易出问题。

下面是完整的解决方案,分三步实现:

1. 定义自定义的目录结构DTO

创建一个只包含我们需要信息的实体类,避免循环引用和冗余字段:

import java.util.ArrayList;
import java.util.List;
import java.io.File;

public class FileNode {
    private String absolutePath;
    private boolean isDirectory;
    private List<FileNode> children;

    public FileNode(File file) {
        this.absolutePath = file.getAbsolutePath();
        this.isDirectory = file.isDirectory();
        this.children = new ArrayList<>();
    }

    // Getter和Setter方法,或者用Lombok的@Data注解简化
    public String getAbsolutePath() {
        return absolutePath;
    }

    public void setAbsolutePath(String absolutePath) {
        this.absolutePath = absolutePath;
    }

    public boolean isDirectory() {
        return isDirectory;
    }

    public void setDirectory(boolean directory) {
        isDirectory = directory;
    }

    public List<FileNode> getChildren() {
        return children;
    }

    public void setChildren(List<FileNode> children) {
        this.children = children;
    }
}

2. 将扁平的File列表转换为树形结构

FileUtils.listFilesAndDirs返回的是扁平列表,我们需要把它转换成树形结构,这样既符合目录的层级逻辑,又能避免循环引用:

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import android.os.Environment;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.DirectoryFileFilter;

public class DirectoryTreeBuilder {
    public static FileNode buildDirectoryTree() {
        // 获取外部存储根目录的所有文件和子目录
        List<File> flatFileList = (List<File>) FileUtils.listFilesAndDirs(
            Environment.getExternalStorageDirectory(),
            DirectoryFileFilter.INSTANCE,
            DirectoryFileFilter.INSTANCE
        );

        File rootDir = Environment.getExternalStorageDirectory();
        FileNode rootNode = new FileNode(rootDir);

        // 用Map快速映射File到对应的FileNode,方便查找父节点
        Map<File, FileNode> fileNodeMap = new HashMap<>();
        fileNodeMap.put(rootDir, rootNode);

        // 遍历所有文件/目录,构建树形结构
        for (File file : flatFileList) {
            if (file.equals(rootDir)) continue;

            FileNode currentNode = new FileNode(file);
            fileNodeMap.put(file, currentNode);

            // 找到父节点并添加当前节点到子列表
            File parentFile = file.getParentFile();
            FileNode parentNode = fileNodeMap.get(parentFile);
            if (parentNode != null) {
                parentNode.getChildren().add(currentNode);
            }
        }

        return rootNode;
    }
}

3. 用Gson序列化树形结构

现在序列化自定义的FileNode对象就不会有循环引用问题了,能得到完整的目录结构JSON:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class JsonSerializer {
    public static void serializeDirectoryTreeToJson() {
        FileNode rootNode = DirectoryTreeBuilder.buildDirectoryTree();

        // 初始化Gson,可选开启格式化输出
        Gson gson = new GsonBuilder()
            .setPrettyPrinting()
            .create();

        // 转换为JSON字符串
        String directoryJson = gson.toJson(rootNode);

        // 保存到JSON文件
        File outputFile = new File(Environment.getExternalStorageDirectory(), "directory_structure.json");
        try {
            FileUtils.writeStringToFile(outputFile, directoryJson, StandardCharsets.UTF_8);
            System.out.println("JSON文件已成功生成:" + outputFile.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

关键注意事项

  • 权限问题:Android 6.0及以上需要动态申请READ_EXTERNAL_STORAGE权限;Android 10及以上如果需要访问所有文件,需要申请MANAGE_EXTERNAL_STORAGE权限,或者改用MediaStore API。
  • 性能优化:如果目录结构非常庞大,构建树形结构可能会占用较多内存,建议分批处理或者按需加载子目录。
  • 避免循环引用:自定义DTO只保留必要的路径、是否为目录、子节点列表,完全切断了File对象的循环引用链,这是解决序列化不完整的核心。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:39:01