我试图获得一个具有目录结构的JSON文件,包括递归的文件和子目录。
使用apache-commons-io库,我得到了一个子目录和文件的列表,这些子目录和文件具有我想要的结构:
List<File> files = (List<File>) FileUtils.listFilesAndDirs(
Environment.getExternalStorageDirectory(),
DirectoryFileFilter.INSTANCE,
DirectoryFileFilter.INSTANCE);但是,当我试图使用Gson库将其序列化为JSON文件时,返回的字符串只包含根路径:
Gson gson = new Gson();
String json = gson.toJson(files.get(0));输出:
{
"path": "/storage/emulated/0"
}如何获得包含所有子目录和文件的JSON对象?
发布于 2018-05-07 06:31:47
你的问题有很多方面的问题。例如,我发现:
files.get(0)只是返回第一个孩子。如果没有孩子肯定会失败。DirectoryFileFilter只接受目录,正如Java中所指出的那样,您需要TrueFileFilter。
LinkedList可能是内存问题。例如,Google fileTreeTraverser返回遍历器,该遍历器允许遍历不需要将整个列表存储在内存中的可迭代性(但是,它将需要Iterable的自定义序列化程序/反序列化器对并检测目录输入/离开)。String Gson.toJson(...)将潜在的大型集合序列化为字符串是另一个内存问题。如果可能的话,您应该考虑流。
File,因为Gson没有为它提供序列化器/反序列化器对。在最新的Gson版本2.8.4中,它使用ReflectiveTypeAdapterFactory$Adapter,所以它使用File字段。如果File内部结构因任何原因而发生变化,则无法将其反序列化。此外,拥有一个path属性也不允许区分目录和文件。
尽管如此,您可能希望自己遍历一个文件目录,将每个目录和文件转换为您希望使用的尽可能小的文件表示。
下面的接口将允许您构建任何JSON结构。例如:
[
"./file1",
"./file2",
"./dir1",
"./dir1/file1",
"./dir1/file2",
"./dir2",
"./dir2/file1"
][
{"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"}
]null表示一个文件:{
"file1": null
"file2": null,
"dir1": {
"file1": null,
"file2": null
},
"dir2": {
"file1": null
}
}[
"file1"
"file2",
{
"name": "dir1",
"children": [
"file1",
"file2"
]
},
{
"name": "dir2",
"children": [
"file1"
]
}
]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;
}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);
}
}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();
}
}
}使用实例:
// 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);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,示例输出
[
"./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 (以更有效的方式使用内存)或一个自定义反序列化器(如果可以将所有内容读入内存)。
发布于 2018-05-06 15:43:42
你打印的,你得到的:
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"
}
]https://stackoverflow.com/questions/50199511
复制相似问题