アセットからファイルを読み取る


178
public class Utils {
    public static List<Message> getMessages() {
        //File file = new File("file:///android_asset/helloworld.txt");
        AssetManager assetManager = getAssets();
        InputStream ims = assetManager.open("helloworld.txt");    
     }
}

アセットからファイルを読み取ろうとするこのコードを使用しています。これを行うには2つの方法を試しました。まず、File受け取っFileNotFoundExceptionた使用AssetManager getAssets()方法で、使用方法が認識されません。ここに解決策はありますか?

回答:


225

ここに私があなたのニーズに合うようにバッファリングされた読み取り拡張/変更のアクティビティで何をするかがあります

BufferedReader reader = null;
try {
    reader = new BufferedReader(
        new InputStreamReader(getAssets().open("filename.txt")));

    // do reading, usually loop until end of file reading  
    String mLine;
    while ((mLine = reader.readLine()) != null) {
       //process line
       ...
    }
} catch (IOException e) {
    //log the exception
} finally {
    if (reader != null) {
         try {
             reader.close();
         } catch (IOException e) {
             //log the exception
         }
    }
}

編集:あなたの質問が活動の外でそれを行う方法についてである場合、私の答えはおそらく役に立たないです。あなたの質問が単にアセットからファイルを読み取る方法であるならば、答えは上記です。

更新

タイプを指定してファイルを開くには、次のようにInputStreamReader呼び出しにタイプを追加するだけです。

BufferedReader reader = null;
try {
    reader = new BufferedReader(
        new InputStreamReader(getAssets().open("filename.txt"), "UTF-8")); 

    // do reading, usually loop until end of file reading 
    String mLine;
    while ((mLine = reader.readLine()) != null) {
       //process line
       ...
    }
} catch (IOException e) {
    //log the exception
} finally {
    if (reader != null) {
         try {
             reader.close();
         } catch (IOException e) {
             //log the exception
         }
    }
}

編集

@Stanがコメントで言っているように、私が提供しているコードは行を合計していません。mLineパスごとに置き換えられます。それが私が書い//process lineた理由です。ファイルにはある種のデータ(連絡先リストなど)が含まれており、各行は個別に処理する必要があると思います。

何も処理せずに単にファイルをロードしたい場合はmLine、各パスを使用StringBuilder()および追加して、各パスで合計する必要があります。

別の編集

@Vincentのコメントによると、私はfinallyブロックを追加しました。

また、Java 7以降でtry-with-resourcesは、AutoCloseableおよびを使用できます。Closeableは、最近のJavaの機能ます。

環境

コメントで@LunarWatcher getAssets()はそれがclassinであることを指摘しcontextます。したがって、外部で呼び出す場合activityは、それを参照して、コンテキストインスタンスをアクティビティに渡す必要があります。

ContextInstance.getAssets();

これは@Maneeshの回答で説明されています。それで、これがあなたに役立つ場合は、彼の答えを賛成投票してください。


2
@Stan、それからコメントでそれについて書いて、作者にそれを更新したいかどうか決定させます。編集は明確さを向上させるためのものであり、意味を変えるものではありません。コードリビジョンは、常に最初にコメントとして投稿する必要があります。
KyleMit 2014年

2
コードは、ストリームを閉じてリソースを適時に解放することを保証していません。の使用をお勧めしますfinally {reader.close();}
Vincent Cantin 2014

2
上記のコードがADTのエラーを示していることを指摘することは有用だと思います-"reader.close();" 行を別のtry-catchブロックに配置する必要があります。このスレッドを確認してください:stackoverflow.com/questions/8981589/… :)
JakeP '7/07/14

1
getAssetsはContextのクラスであるため、アクティビティ外で使用するには、Contextの呼び出しを行う必要があります。つまり、アクティビティ以外では、次のようなものになりますcontext.getAssets(.....)
Zoe

1
更新に従って(そのbtwを追加してくれてありがとう)、静的フィールドにコンテキストがあるとメモリリークが発生します。これは注意して使用し、適切にクリーンアップする必要があります。そうしないと、アプリに大きな影響を与える可能性のあるメモリリークが発生します。
ゾーイ

65
getAssets()

あなたがそれに使用する必要がある他の任意のクラスのアクティビティでのみ機能ますContext

作るutilsに関するコンストラクタそれにパラメータとしてクラスパス活動の基準(醜い方法)、またはアプリケーションのコンテキスト。これを使用するには、UtilsクラスでgetAsset()を使用します。


1
これは、Contextのサブクラスであるすべてのものに対して機能します。
ジェレミーローガン

ちょうど私が書いたことを指摘したContext
user370305 2013

@ user370305ご存知ですか、InputStreamをFileInputStreamに変換する方法を教えてください。
hotHead

@ user370305はどのように醜いですか?
Sevastyan Savanyuk

結果を考慮せずにUIオブジェクトを渡すことは、一般的に悪い習慣です。注意しないと、メモリリークが発生したり、無効なコンテキストが使用されたりする可能性があります。トピックに関する良い読み:android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570
milosmns

49

遅れることはない。

状況によっては、ファイルを1行ずつ読み取るのが困難でした。以下の方法は、私が見つけた中で最高の方法であり、私はそれをお勧めします。

使用法: String yourData = LoadData("YourDataFile.txt");

YourDataFile.txtassets /にあると想定されている場所

 public String LoadData(String inFile) {
        String tContents = "";

    try {
        InputStream stream = getAssets().open(inFile);

        int size = stream.available();
        byte[] buffer = new byte[size];
        stream.read(buffer);
        stream.close();
        tContents = new String(buffer);
    } catch (IOException e) {
        // Handle exceptions here
    }

    return tContents;

 }

私の戻り文字列はandroid.content.res.AssetManager$AssetInputStream@4195dfa0 ..
Boldijar Paul

ここでも同じです。res.AssetManager$ AssetInputStream @ ....これが返される特別な理由はありますか?
Bigs 2014年

最初にバッファに、次に文字列に、メモリを二重に割り当てます。大きなファイルでは機能しません。
JaakL 2017年

1
バッファにサイズを割り当てるための完璧な方法stream.available()
カシムランワラ2018

39
public String ReadFromfile(String fileName, Context context) {
    StringBuilder returnString = new StringBuilder();
    InputStream fIn = null;
    InputStreamReader isr = null;
    BufferedReader input = null;
    try {
        fIn = context.getResources().getAssets()
                .open(fileName, Context.MODE_WORLD_READABLE);
        isr = new InputStreamReader(fIn);
        input = new BufferedReader(isr);
        String line = "";
        while ((line = input.readLine()) != null) {
            returnString.append(line);
        }
    } catch (Exception e) {
        e.getMessage();
    } finally {
        try {
            if (isr != null)
                isr.close();
            if (fIn != null)
                fIn.close();
            if (input != null)
                input.close();
        } catch (Exception e2) {
            e2.getMessage();
        }
    }
    return returnString.toString();
}

BufferedReaderを閉じると、InputStreanReaderとInputStreamも自動的に閉じる必要があると考えるでしょう。それはあなたがそれらのハンドルを作成しないからですinput = new BufferedReader(new InputStreamReader(fIn));
トランス

3
最後に、すべてのリソースを閉じるための個別のtry / catchブロックを作成することをお勧めします。それらをすべて1つにまとめるのではなく、以前に別のリソースを閉じようとしたときに例外がスローされた場合、他のリソースが閉じられないままになる可能性があります。
2016年

9
AssetManager assetManager = getAssets();
InputStream inputStream = null;
try {
    inputStream = assetManager.open("helloworld.txt");
}
catch (IOException e){
    Log.e("message: ",e.getMessage());
}

8

kotlinの1行のソリューション:

fun readFileText(fileName: String): String {
    return assets.open(fileName).bufferedReader().use { it.readText() }
}

7

getAssets() メソッドは、Activityクラス内で呼び出すときに機能します。

非Activityクラスでこのメソッドを呼び出す場合、Activityクラスから渡されるContextからこのメソッドを呼び出す必要があります。以下は、メソッドにアクセスできる行です。

ContextInstance.getAssets();

ContextInstance これをActivityクラスとして渡すことができます。


5

ファイルの読み取りと書き込みは常に冗長でエラーが発生しやすくなっています。これらの答えを避け、代わりにOkioを使用してください:

public void readLines(File file) throws IOException {
  try (BufferedSource source = Okio.buffer(Okio.source(file))) {
    for (String line; (line = source.readUtf8Line()) != null; ) {
      if (line.contains("square")) {
        System.out.println(line);
      }
    }
  }
}

1
これがより美しく短く見える理由を知っていますか?まあ、あなたが省略したので、少なくとも、ここのコードの半分。省略された部分:1)IOExceptionのtry / catchブロック2)例外がスローされた場合のストリームのクローズ3)このコードは、ファイル全体ではなく、1行を読み取ります。パフォーマンスに関しては、このライブラリは間違いなくその種類の1つです。ここで、「これらの答え」を回避し、ファイルを読み取るためだけにOkioを実装する必要があるかどうかを教えてください。それがすでにアプリの一部でない限り、答えはノーです。
ファリド

私の答えを更新しました。
Saket

4

アセット内のファイルを読み取る方法は次のとおりです。

/**
 * Reads the text of an asset. Should not be run on the UI thread.
 * 
 * @param mgr
 *            The {@link AssetManager} obtained via {@link Context#getAssets()}
 * @param path
 *            The path to the asset.
 * @return The plain text of the asset
 */
public static String readAsset(AssetManager mgr, String path) {
    String contents = "";
    InputStream is = null;
    BufferedReader reader = null;
    try {
        is = mgr.open(path);
        reader = new BufferedReader(new InputStreamReader(is));
        contents = reader.readLine();
        String line = null;
        while ((line = reader.readLine()) != null) {
            contents += '\n' + line;
        }
    } catch (final Exception e) {
        e.printStackTrace();
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException ignored) {
            }
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ignored) {
            }
        }
    }
    return contents;
}

これは良い答えですが、文字列連結を使用するのは悪いアプローチです。代わりにStringBuilderの使用を検討してください。StringBuilder contentBuilder = new StringBuilder(); while((line = reader.readLine())!= null){builder.append( "\ n")。append(line); そして、最後に、これによって新しいStringオブジェクトを作成できます。content = contentBuilder.toString();
Barterio 2018

4

ファイルからコンテンツをロードできます。ファイルがアセットフォルダに存在することを考慮してください。

public static InputStream loadInputStreamFromAssetFile(Context context, String fileName){
    AssetManager am = context.getAssets();
    try {
        InputStream is = am.open(fileName);
        return is;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static String loadContentFromFile(Context context, String path){
    String content = null;
    try {
        InputStream is = loadInputStreamFromAssetFile(context, path);
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        content = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return content;
}

これで、次のように関数を呼び出してコンテンツを取得できます

String json= FileUtil.loadContentFromFile(context, "data.json");

data.jsonがApplication \ app \ src \ main \ assets \ data.jsonに格納されていることを考慮


3

MainActivity.java内

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView tvView = (TextView) findViewById(R.id.tvView);

        AssetsReader assetsReader = new AssetsReader(this);
        if(assetsReader.getTxtFile(your_file_title)) != null)
        {
            tvView.setText(assetsReader.getTxtFile(your_file_title)));
        }
    }

また、すべての作業を行う個別のクラスを作成することもできます

public class AssetsReader implements Readable{

    private static final String TAG = "AssetsReader";


    private AssetManager mAssetManager;
    private Activity mActivity;

    public AssetsReader(Activity activity) {
        this.mActivity = activity;
        mAssetManager = mActivity.getAssets();
    }

    @Override
    public String getTxtFile(String fileName)
    {
        BufferedReader reader = null;
        InputStream inputStream = null;
        StringBuilder builder = new StringBuilder();

        try{
            inputStream = mAssetManager.open(fileName);
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;

            while((line = reader.readLine()) != null)
            {
                Log.i(TAG, line);
                builder.append(line);
                builder.append("\n");
            }
        } catch (IOException ioe){
            ioe.printStackTrace();
        } finally {

            if(inputStream != null)
            {
                try {
                    inputStream.close();
                } catch (IOException ioe){
                    ioe.printStackTrace();
                }
            }

            if(reader != null)
            {
                try {
                    reader.close();
                } catch (IOException ioe)
                {
                    ioe.printStackTrace();
                }
            }
        }
        Log.i(TAG, "builder.toString(): " + builder.toString());
        return builder.toString();
    }
}

私の意見では、インターフェースを作成する方が良いですが、それは必要ではありません

public interface Readable {
    /**
     * Reads txt file from assets
     * @param fileName
     * @return string
     */
    String getTxtFile(String fileName);
}

2

Activity以外のクラスを使用する場合は、次のようにすることができます。

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( YourApplication.getInstance().getAssets().open("text.txt"), "UTF-8"));

2

Kotlinを使用すると、次のようにしてAndroidのアセットからファイルを読み取ることができます。

try {
    val inputStream:InputStream = assets.open("helloworld.txt")
    val inputString = inputStream.bufferedReader().use{it.readText()}
    Log.d(TAG,inputString)
} catch (e:Exception){
    Log.d(TAG, e.toString())
}

2

手遅れかもしれませんが、桃の答えを探している他の人のために:

public static String loadAssetFile(Context context, String fileName) {
    try {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(context.getAssets().open(fileName)));
        StringBuilder out= new StringBuilder();
        String eachline = bufferedReader.readLine();
        while (eachline != null) {
            out.append(eachline);
            eachline = bufferedReader.readLine();
        }
        return out.toString();
    } catch (IOException e) {
        Log.e("Load Asset File",e.toString());
    }
    return null;
}

1

cityfile.txt

   public void getCityStateFromLocal() {
        AssetManager am = getAssets();
        InputStream inputStream = null;
        try {
            inputStream = am.open("city_state.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String[]> map = new HashMap<String, String[]>();
        try {
            map = mapper.readValue(getStringFromInputStream(inputStream), new TypeReference<Map<String, String[]>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        ConstantValues.arrayListStateName.clear();
        ConstantValues.arrayListCityByState.clear();
        if (map.size() > 0)
        {
            for (Map.Entry<String, String[]> e : map.entrySet()) {
                CityByState cityByState = new CityByState();
                String key = e.getKey();
                String[] value = e.getValue();
                ArrayList<String> s = new ArrayList<String>(Arrays.asList(value));
                ConstantValues.arrayListStateName.add(key);
                s.add(0,"Select City");
                cityByState.addValue(s);
                ConstantValues.arrayListCityByState.add(cityByState);
            }
        }
        ConstantValues.arrayListStateName.add(0,"Select States");
    }
 // Convert InputStream to String
    public String getStringFromInputStream(InputStream is) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        String line;
        try {
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb + "";

    }

リンクが返されるFile no longer available That file has now been permanently removed and cannot be recovered
gregn3

1

Scannerクラスはこれを単純化するかもしれません。

        StringBuilder sb=new StringBuilder();
        Scanner scanner=null;
        try {
            scanner=new Scanner(getAssets().open("text.txt"));
            while(scanner.hasNextLine()){
                sb.append(scanner.nextLine());
                sb.append('\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(scanner!=null){try{scanner.close();}catch (Exception e){}}
        }
        mTextView.setText(sb.toString());

これらの2行をマージできますsb.append(scanner.nextLine()); sb.append( '\ n'); sb.appendln(scanner.nextLine());に
Mojtaba

0

@HpTerm回答Kotlinバージョン:

private fun getDataFromAssets(): String? {

    var bufferedReader: BufferedReader? = null
    var data: String? = null

    try {
        bufferedReader = BufferedReader(
            InputStreamReader(
                activity?.assets?.open("Your_FILE.html"),     
                "UTF-8"
            )
        )                  //use assets? directly if in activity

       var mLine:String = bufferedReader?.readLine()
        while (mLine != null) {
            data+= mLine
            mLine=bufferedReader.readLine()
        }

    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        try {
            bufferedReader?.close()
        } catch (e: Exception) {
           e.printStackTrace()
        }
    }
    return data
}

現在、これは文字列の前にnullを付加します。必要な変更:var mLine:Stringあるべきvar mLine:String? var data: String?である必要がありvar data = ""、戻り値の型でなければなりませんString
fupduck

0

ここで取得する方法でInputStream、ファイルのためassetsせずにフォルダをContextActivityFragmentまたはApplication。それからデータを取得する方法はあなた次第InputStreamです。そのための提案は他にもたくさんあります。

コトリン

val inputStream = ClassLoader::class.java.classLoader?.getResourceAsStream("assets/your_file.ext")

ジャワ

InputStream inputStream = ClassLoader.class.getClassLoader().getResourceAsStream("assets/your_file.ext");

カスタムClassLoaderがプレイされている場合、すべてのベットはオフになります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.