首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Gson库获取文件树

使用Gson库获取文件树
EN

Stack Overflow用户
提问于 2018-05-06 12:09:19
回答 2查看 337关注 0票数 0

我试图获得一个具有目录结构的JSON文件,包括递归的文件和子目录。

使用apache-commons-io库,我得到了一个子目录和文件的列表,这些子目录和文件具有我想要的结构:

代码语言:javascript
复制
List<File> files = (List<File>) FileUtils.listFilesAndDirs(
                Environment.getExternalStorageDirectory(),
                DirectoryFileFilter.INSTANCE,
                DirectoryFileFilter.INSTANCE);

但是,当我试图使用Gson库将其序列化为JSON文件时,返回的字符串只包含根路径:

代码语言:javascript
复制
Gson gson = new Gson();
String json = gson.toJson(files.get(0));

输出:

代码语言:javascript
复制
{
  "path": "/storage/emulated/0"
}

如何获得包含所有子目录和文件的JSON对象?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-05-07 06:31:47

你的问题有很多方面的问题。例如,我发现:

  • 假设
    • 正如Hemant Patel在回答中指出的那样,files.get(0)只是返回第一个孩子。如果没有孩子肯定会失败。
    • 而且,我从未使用过Apache,但是事实证明,DirectoryFileFilter只接受目录,正如Java中所指出的那样,您需要TrueFileFilter

  • 内存和一般性能问题
    • 我不确定Apache在幕后是如何工作的,但是返回内存中的集合LinkedList可能是内存问题。例如,Google fileTreeTraverser返回遍历器,该遍历器允许遍历不需要将整个列表存储在内存中的可迭代性(但是,它将需要Iterable的自定义序列化程序/反序列化器对并检测目录输入/离开)。
    • 使用String Gson.toJson(...)将潜在的大型集合序列化为字符串是另一个内存问题。如果可能的话,您应该考虑流。

  • 兼容性问题
    • 我不建议直接序列化File,因为Gson没有为它提供序列化器/反序列化器对。在最新的Gson版本2.8.4中,它使用ReflectiveTypeAdapterFactory$Adapter,所以它使用File字段。如果File内部结构因任何原因而发生变化,则无法将其反序列化。此外,拥有一个path属性也不允许区分目录和文件。

尽管如此,您可能希望自己遍历一个文件目录,将每个目录和文件转换为您希望使用的尽可能小的文件表示。

下面的接口将允许您构建任何JSON结构。例如:

  • 一个超级简单的单子表:
代码语言:javascript
复制
[
    "./file1",
    "./file2",
    "./dir1",
    "./dir1/file1",
    "./dir1/file2",
    "./dir2",
    "./dir2/file1"
]
  • 打印的平面列表:
代码语言:javascript
复制
[
    {"type": "file", "path": "./file1"},
    {"type": "file", "path": "./file2"},
    {"type": "directory", "path": "./dir1"},
    {"type": "file", "path": "./dir1/file1"},
    {"type": "file", "path": "./dir1/file2"},
    {"type": "directory", "path": "./dir2"},
    {"type": "file", "path": "./dir2/file1"}
]
  • 一个目录/文件JSON对象,其中一个对象表示一个目录,而一个null表示一个文件:
代码语言:javascript
复制
{
    "file1": null
    "file2": null,
    "dir1": {
        "file1": null,
        "file2": null
    },
    "dir2": {
        "file1": null
    }
}
  • 一个目录/文件JSON数组,其中字符串表示文件,而对象表示目录:
代码语言:javascript
复制
[
    "file1"
    "file2",
    {
        "name": "dir1",
        "children": [
            "file1",
            "file2"
        ]
    },
    {
        "name": "dir2",
        "children": [
            "file1"
        ]
    }
]
代码语言:javascript
复制
interface IDirectoryWalkListener {

    void onEnterDirectory(int level, @Nonnull File directory)
            throws IOException;

    void onFile(@Nonnull File file)
            throws IOException;

    void onLeaveDirectory(int level, @Nonnull File directory)
            throws IOException;

}
代码语言:javascript
复制
final class DirectoryWalk {

    private DirectoryWalk() {
    }

    static void walk(final File root, final IDirectoryWalkListener listener)
            throws IOException {
        walk(0, root, listener);
    }

    private static void walk(final int level, final File root, final IDirectoryWalkListener listener)
            throws IOException {
        if ( !root.isDirectory() ) {
            throw new IOException(root + " must be a directory");
        }
        @Nullable
        final File[] files = root.listFiles();
        if ( files == null ) {
            throw new IOException("Cannot list files in " + root);
        }
        listener.onEnterDirectory(level, root);
        for ( final File file : files ) {
            if ( file.isDirectory() ) {
                walk(level + 1, file, listener);
            } else {
                listener.onFile(file);
            }
        }
        listener.onLeaveDirectory(level, root);
    }

}
代码语言:javascript
复制
final class ToFlatJsonArrayDirectoryWalkListener
        implements IDirectoryWalkListener {

    private final JsonWriter jsonWriter;

    private ToFlatJsonArrayDirectoryWalkListener(final JsonWriter jsonWriter) {
        this.jsonWriter = jsonWriter;
    }

    static IDirectoryWalkListener get(final JsonWriter jsonWriter) {
        return new ToFlatJsonArrayDirectoryWalkListener(jsonWriter);
    }

    @Override
    public void onEnterDirectory(final int level, @Nonnull final File directory)
            throws IOException {
        if ( level == 0 ) {
            jsonWriter.beginArray();
        }
        jsonWriter.value(directory.getPath());
    }

    @Override
    public void onFile(@Nonnull final File file)
            throws IOException {
        jsonWriter.value(file.getPath());
    }

    @Override
    public void onLeaveDirectory(final int level, @Nonnull final File directory)
            throws IOException {
        if ( level == 0 ) {
            jsonWriter.endArray();
        }
    }

}

使用实例:

代码语言:javascript
复制
// Writing to a string is a potential performance and memory issue
final Writer out = new StringWriter();
final JsonWriter jsonWriter = new JsonWriter(out);
jsonWriter.setIndent("\t");
DirectoryWalk.walk(root, ToFlatJsonArrayDirectoryWalkListener.get(jsonWriter));
System.out.println(out);
代码语言:javascript
复制
final Writer out = new OutputStreamWriter(System.out) {
    @Override
    public void close() {
        // do not close System.out
    }
};
final JsonWriter jsonWriter = new JsonWriter(out);
jsonWriter.setIndent("\t");
DirectoryWalk.walk(root, ToFlatJsonArrayDirectoryWalkListener.get(jsonWriter));
out.flush();

如果root./target,示例输出

代码语言:javascript
复制
[
    "./target",
    "./target/data",
    "./target/data/journal",
    "./target/data/journal/server.lock",
    "./target/classes",
    "./target/classes/com",
    "./target/classes/com/google",
    "./target/classes/com/google/gson",
    "./target/classes/com/google/gson/interceptors",
    "./target/classes/com/google/gson/interceptors/InterceptorFactory$InterceptorAdapter.class",
    "./target/classes/com/google/gson/interceptors/InterceptorFactory$1.class",
    "./target/classes/com/google/gson/interceptors/InterceptorFactory.class",
    "./target/classes/com/google/gson/interceptors/JsonPostDeserializer.class",
    "./target/classes/com/google/gson/interceptors/Intercept.class",
    ...
]

为了从JSON恢复文件结构,您需要一个JsonReader (以更有效的方式使用内存)或一个自定义反序列化器(如果可以将所有内容读入内存)。

票数 0
EN

Stack Overflow用户

发布于 2018-05-06 15:43:42

你打印的,你得到的:

代码语言:javascript
复制
Gson gson = new Gson();
String json = gson.toJson(files.get(0)); // one file
{
  "path": "/storage/emulated/0"
}


String json = gson.toJson(files); // all files
[
  {
    "path": "/storage/emulated/0"
  },
  {
    "path": "/storage/emulated/0/dir1"
  },
  {
    "path": "/storage/emulated/dir2"
  }
]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50199511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档