Ответ 1
list() в AssetManager, вероятно, даст массив с нулевой длиной/нулевой длиной /IOException, если вы попытаетесь получить список в файле, но действительный ответ в каталоге.
Но в противном случае это должен быть файл:///android_asset (с 3/)
Хей,
У меня есть некоторые данные, отправленные с приложением, которые должны быть скопированы на внешнем хранилище. Он вложен в пару подпапок, и я хотел бы скопировать всю структуру.
Мне трудно получить объект File для любого ressource в /assets
. Но я думаю, что я зависим от этого, потому что мне нужно что-то вроде File.isDirectory(), чтобы определить, нужно ли мне начинать копирование или погружаться глубже в систему.
Мой первый подход заключался в использовании Assets Manager, но кажется, что класс не предоставляет необходимую мне информацию. Наиболее перспективным было бы получить AssetFileDescriptor
и перейти к [FileDescriptor][2]
. Однако у них не существует метода isDirectory
.
Итак, мой другой подход прямо: создание объекта файла и быть счастливым. Однако кажется, что я бегу в этой проблеме из-за отсутствия надлежащего пути к экземпляру объекта файла. Я знаю file://android_asset
, но он не работает для конструктора file
.
Моя последняя идея должна была бы использовать InputStream (который мне нужен для копирования в любом случае) и каким-то образом фильтровать байт для значительного бита, который указывает, что этот ресурс является каталогом. Это довольно хакерское решение и, вероятно, прямо в аду неэффективности, но я не вижу другого способа обойти это.
list() в AssetManager, вероятно, даст массив с нулевой длиной/нулевой длиной /IOException, если вы попытаетесь получить список в файле, но действительный ответ в каталоге.
Но в противном случае это должен быть файл:///android_asset (с 3/)
У меня была та же проблема. В какой-то момент я понял, что list()
очень медленный (50 мс при каждом вызове), поэтому теперь я использую другой подход:
У меня есть (eclipse) ant -builder, который создает индексный файл каждый раз при изменении моей папки с активами. Файл содержит только одно имя файла для каждой строки, поэтому каталоги отображаются неявно (если они не пусты).
Конструктор:
<?xml version="1.0"?>
<project default="createAssetIndex">
<target name="createAssetIndex">
<fileset id="assets.fileset" dir="assets/" includes="**"
excludes="asset.index" />
<pathconvert pathsep="${line.separator}" property="assets"
refid="assets.fileset">
<mapper>
<globmapper from="${basedir}/assets/*" to="*"
handledirsep="yes" />
</mapper>
</pathconvert>
<echo file="assets/asset.index">${assets}</echo>
</target>
</project>
Класс, который загружает asset.index
в список строк, поэтому вы можете делать с ним произвольные вещи, быстро:
import android.content.ContextWrapper;
import com.google.common.collect.ImmutableList;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* uses asset.index file (which is pregenerated) since asset-list()s take very long
*
*/
public final class AssetIndex {
//~ Static fields/initializers -------------------------------------------------------------------------------------
private static final Logger L = LoggerFactory.getLogger(AssetIndex.class);
//~ Instance fields ------------------------------------------------------------------------------------------------
private final ImmutableList<String> files;
//~ Constructors ---------------------------------------------------------------------------------------------------
public AssetIndex(final ContextWrapper contextWrapper) {
ImmutableList.Builder<String> ib = ImmutableList.builder();
L.debug("creating index from assets");
InputStream in = null;
Scanner scanner = null;
try {
in = contextWrapper.getAssets().open("asset.index");
scanner = new Scanner(new BufferedInputStream(in));
while (scanner.hasNextLine()) {
ib.add(scanner.nextLine());
}
scanner.close();
in.close();
} catch (final IOException e) {
L.error(e.getMessage(), e);
} finally {
if (scanner != null) {
scanner.close();
}
if (in != null) {
try {
in.close();
} catch (final IOException e) {
L.error(e.getMessage(), e);
}
}
}
this.files = ib.build();
}
//~ Methods --------------------------------------------------------------------------------------------------------
/* returns the number of files in a directory */
public int numFiles(final String dir) {
String directory = dir;
if (directory.endsWith(File.separator)) {
directory = directory.substring(0, directory.length() - 1);
}
int num = 0;
for (final String file : this.files) {
if (file.startsWith(directory)) {
String rest = file.substring(directory.length());
if (rest.charAt(0) == File.separatorChar) {
if (rest.indexOf(File.separator, 1) == -1) {
num = num + 1;
}
}
}
}
return num;
}
}
В моем конкретном случае обычные файлы имеют имя типа filename.ext, в то время как в каталогах есть только имя, без расширения, и их имя никогда не содержит ".". (точка). Поэтому обычный файл можно отличить от каталога, проверяя его имя следующим образом:
filename.contains(".")
Если это ваш случай тоже, то одно и то же решение должно работать для вас.