2011-12-06 5 views
13

Hej、wheteher android asset entryがファイルまたはディレクトリであることを確認します。

私はいくつかのデータを外部ストレージにコピーする必要があります。いくつかのサブフォルダに入れ子になっており、構造全体をコピーしたいと思います。

/assetsにすべてのリソースのFileオブジェクトを取得するのに苦労しています。しかし私は、私がFile.isDirectory()のようなものを必要としているので、私がそれを依存していると思う。

私の最初のアプローチはAssets Managerでしたが、クラスが必要な情報を提供していないようです。最も有望な理由は、AssetFileDescriptorを取得し、[FileDescriptor][2]に移動することでした。しかし、それらのうちのどれもisDirectory - 方法を持っているようです。

私の他のアプローチはまっすぐです:ファイルオブジェクトを作成し、満足してください。しかし、私はファイルオブジェクトをインスタンス化するための適切なパスがないというこの問題を抱えているようです。私はfile://android_assetを認識していますが、fileコンストラクタでは動作しません。

私の最後のアイデアは、(私はとにかくコピーするために必要な)InputStreamを利用し、どういうわけか、このリソースがディレクトリであることを示す重要なビットのバイトをフィルタリングします。それはかなりハッキーな解決策であり、おそらく無効である可能性が高いですが、私はそれを回避する別の方法は見当たりません。

+0

また、*** AssetManager.list()***と*** AssetManager.open()***メソッドの両方を組み合わせたhttps://stackoverflow.com/a/46827944/2179872をチェックすることもできます – Cosmin

答えて

4

list()(AssetManager上)は、ファイルに対してリストを取得しようとすると、null /長さゼロの配列/ IOExceptionを返すことがありますが、ディレクトリに対しては有効な応答を返します。

しかし、それ以外の場合はファイルである必要があります:/// android_asset

+0

私はlist-hackを探します。 ええ、新しいファイル(file:///android_asset/foo.bar)を使用しても動作しないようです。私は実際に戻ってくるオブジェクトのタイプはわかりませんが、isDirectory()AND(!)isFile()の両方のテストで失敗します。 – yoshi

+1

この回答を2倍にしたいと思います。 'filename [filename]がファイルの場合、' String [] s = am.list(filename) 'は' IOException'をスローします。私はこのソリューションが本当に好きです、ありがとう! – yoshi

+0

しかし、list()は本当に遅いです(他の回答を参照) –

12

(3 /で)私は同じ問題を抱えていました。

私はアセットファイルを作成するたびにインデックスファイルを作成する(eclipse)ant-builderを持っていますが、フォルダが変更されます。ファイルには1行に1つのファイル名が含まれるだけなので、ディレクトリは暗黙的にリストされます(空でない場合)。

ビルダー:

<?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; 
    } 
} 
+1

これは非常に便利で便利ですが、私は 'dirsep = "/"'をpathconvertに追加する必要がありました。それ以外の場合、Windoze Javaでは、パスの区切り文字は「\」で、Androidのアセットマネージャでは機能しません。 – Flynny75

+1

Gradleを使用している場合は、http://stackoverflow.com/questions/18569983/androidgradle-list-directoriesを参照してください。 -into-a-file –

2

を私の特定のケースでは、通常のファイルは、 filename.extのような名前を持ちますが、ディレクトリは拡張子のない名前しか持たず、名前には "。"が含まれていません。 (ドット)文字。 だから、通常のファイルは、以下のようにその名前をテストすることによって、ディレクトリと区別することができます。

filename.contains(".") 

これはあなたの場合ならば、あまりにも、同じソリューションは、あなたのために働く必要があります。

+0

ブリリアント!通常のローディング時間の80%を節約できました。 –

関連する問題