baca file dari aset

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");    
     }
}

Saya menggunakan kode ini mencoba membaca file dari aset. Saya mencoba dua cara untuk melakukan ini. Pertama, ketika menggunakan Filesaya terima FileNotFoundException, saat menggunakan AssetManager getAssets()metode tidak dikenali. Apakah ada solusi di sini?

ikan40
sumber

Jawaban:

225

Berikut adalah apa yang saya lakukan dalam aktivitas untuk memperpanjang / memodifikasi bacaan buffered yang sesuai dengan kebutuhan Anda

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
         }
    }
}

EDIT: Jawaban saya mungkin tidak berguna jika pertanyaan Anda adalah bagaimana melakukannya di luar kegiatan. Jika pertanyaan Anda hanyalah cara membaca file dari aset, maka jawabannya ada di atas.

MEMPERBARUI :

Untuk membuka file yang menentukan tipe cukup tambahkan tipe dalam panggilan InputStreamReader sebagai berikut.

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
         }
    }
}

EDIT

Seperti @Stan katakan dalam komentar, kode yang saya berikan tidak merangkum garis. mLinediganti setiap pass. Itu sebabnya saya menulis//process line . Saya berasumsi file tersebut berisi beberapa jenis data (yaitu daftar kontak) dan setiap baris harus diproses secara terpisah.

Jika Anda hanya ingin memuat file tanpa proses apa pun, Anda harus meringkas mLinepada setiap pass menggunakan StringBuilder()dan menambahkan setiap pass.

EDIT LAIN

Menurut komentar @Vincent saya menambahkan finally blok.

Perhatikan juga bahwa di Java 7 dan di atasnya Anda dapat menggunakan try-with-resourcesuntuk menggunakan AutoCloseabledan Closeablefitur-fitur Java terbaru.

KONTEKS

Dalam komentar @LunarWatcher menunjukkan bahwa itu getAssets()adalah classin context. Jadi, jika Anda menyebutnya di luar activityAnda perlu merujuknya dan meneruskan contoh konteks ke aktivitas.

ContextInstance.getAssets();

Ini dijelaskan dalam jawaban @aneane. Jadi jika ini bermanfaat bagi Anda, jawablah jawabannya karena dialah yang menunjukkan itu.

HpTerm
sumber
2
@Stan, lalu tulis tentang itu di komentar dan biarkan penulis memutuskan apakah mereka ingin memperbaruinya. Suntingan untuk meningkatkan kejelasan, bukan mengubah makna. Revisi kode harus selalu diposting sebagai komentar terlebih dahulu.
KyleMit
2
Kode Anda tidak menjamin untuk menutup aliran dan membebaskan sumber daya tepat waktu. Saya sarankan Anda untuk menggunakannya finally {reader.close();}.
Vincent Cantin
2
Saya pikir ini berguna untuk menunjukkan bahwa kode di atas menunjukkan kesalahan dalam ADT - "reader.close ();" line perlu dimasukkan ke blok try-catch lainnya. Periksa utas ini: stackoverflow.com/questions/8981589/... :)
JakeP
1
getAssets adalah kelas dalam Konteks, jadi untuk penggunaan di luar aktivitas, panggilan ke Konteks perlu dilakukan. Jadi di luar suatu kegiatan, itu akan menjadi seperticontext.getAssets(.....)
Zoe
1
Sesuai pembaruan Anda (terima kasih telah menambahkan btw itu), memiliki konteks di bidang statis adalah kebocoran memori. Ini harus digunakan dengan hati-hati dan dibersihkan dengan benar. Kalau tidak, Anda berakhir dengan kebocoran memori yang dapat berdampak besar pada aplikasi.
Zoe
65
getAssets()

hanya berfungsi di Aktivitas di kelas lain yang harus Anda gunakanContext untuk itu.

Jadikan konstruktor untuk Utils melalui referensi aktivitas (cara jelek) atau konteks aplikasi sebagai parameter. Menggunakan yang menggunakan getAsset () di kelas Utils Anda.

pengguna370305
sumber
1
Ini bekerja pada apa pun yang merupakan subkelas dari Konteks, yang Kegiatannya adalah salah satu dari banyak.
Jeremy Logan
Hanya mencatat saya telah menulis Context.
user370305
@ user370305 tahukah Anda, bagaimana saya bisa mengubah InputStream menjadi FileInputStream?
hotHead
@ user370305 dengan cara apa ini jelek?
Sevastyan Savanyuk
Melewati objek UI tanpa mempertimbangkan konsekuensinya umumnya merupakan praktik yang buruk. Jika Anda tidak hati-hati, Anda dapat menyebabkan kebocoran memori atau mencoba menggunakan konteks mati. Selamat membaca tentang topik: android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570
milosmns
49

Lebih baik terlambat daripada tidak sama sekali.

Saya mengalami kesulitan membaca file baris demi baris dalam beberapa keadaan. Metode di bawah ini adalah yang terbaik yang saya temukan, sejauh ini, dan saya merekomendasikannya.

Pemakaian: String yourData = LoadData("YourDataFile.txt");

Di mana YourDataFile.txt diasumsikan berada di aset /

 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;

 }
Florin Mircea
sumber
String pengembalian saya adalah android.content.res.AssetManager$AssetInputStream@4195dfa0 ..
Boldijar Paul
sama di sini, res.AssetManager $ AssetInputStream @ .... ada alasan khusus mengapa mengembalikan ini?
Bigs
Anda mengalokasikan memori dua kali - pertama untuk buffer dan kemudian untuk String. Tidak berfungsi untuk file yang lebih besar.
JaakL
1
cara sempurna untuk mengalokasikan ukuran ke buffer stream.available().
Kasim Rangwala
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();
}
swathi
sumber
Anda akan berpikir bahwa jika Anda menutup BufferedReader, daripada harus menutup InputStreanReader dan InputStream secara otomatis. Karena apa yang Anda tidak membuat pegangan untuk itu, misalnya input = new BufferedReader(new InputStreamReader(fIn));.
trans
3
Saya menyarankan untuk membuat blok coba / tangkap terpisah untuk menutup semua sumber daya Anda di akhir; alih-alih mengelompokkannya menjadi satu - karena dapat membuat sumber daya lain tidak tertutup jika upaya sebelumnya untuk menutup sumber daya lain menimbulkan pengecualian.
Reece
9
AssetManager assetManager = getAssets();
InputStream inputStream = null;
try {
    inputStream = assetManager.open("helloworld.txt");
}
catch (IOException e){
    Log.e("message: ",e.getMessage());
}
Siva Charan
sumber
8

solusi satu baris untuk kotlin:

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

getAssets() Metode akan berfungsi saat Anda memanggil di dalam kelas Activity.

Jika Anda memanggil metode ini di kelas non-Aktivitas maka Anda perlu memanggil metode ini dari Konteks yang dilewatkan dari kelas Activity. Jadi di bawah ini adalah garis oleh Anda dapat mengakses metode ini.

ContextInstance.getAssets();

ContextInstance dapat dilewati sebagai kelas Activity ini.

Maneesh
sumber
5

Membaca dan menulis file selalu verbose dan rawan kesalahan. Hindari jawaban ini dan gunakan Okio saja:

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);
      }
    }
  }
}
Saket
sumber
1
Tahukah Anda mengapa ini terlihat lebih estetis dan pendek? Ya, karena Anda telah menghilangkan, setidaknya, setengah dari kode di sini. Bagian yang dihilangkan: 1) IOExceptionmencoba / menangkap blok 2) Menutup aliran dalam kasus pengecualian dilemparkan 3) Kode ini membaca satu baris, bukan seluruh file. Dari segi kinerja, perpustakaan ini jelas merupakan salah satu dari jenisnya, tidak diragukan lagi. Sekarang, beri tahu saya apakah saya masih harus menghindari "jawaban ini" dan menerapkan Okio hanya untuk membaca file? Jawabannya adalah TIDAK, kecuali itu sudah menjadi bagian dari aplikasi Anda.
Farid
Memperbarui jawaban saya.
Saket
4

Berikut adalah metode untuk membaca file dalam aset:

/**
 * 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;
}
Jared Rummler
sumber
Ini adalah jawaban yang bagus, tetapi ini adalah pendekatan yang buruk untuk menggunakan rangkaian string. Pertimbangkan untuk menggunakan StringBuilder sebagai gantinya. StringBuilder contentBuilder = StringBuilder baru (); while ((line = reader.readLine ())! = null) {builder.append ("\ n"). append (line); } Dan pada akhirnya Anda dapat membuat objek String baru dengan ini: content = contentBuilder.toString ();
Barterio
4

Anda dapat memuat konten dari file. Anggap file tersebut ada di folder aset.

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;
}

Sekarang Anda bisa mendapatkan konten dengan memanggil fungsi sebagai berikut

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

Mengingat data.json disimpan di Application \ app \ src \ main \ assets \ data.json

Siddarth Kanted
sumber
3

Di 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)));
        }
    }

Anda juga dapat membuat kelas terpisah yang melakukan semua pekerjaan

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();
    }
}

Menurut pendapat saya lebih baik untuk membuat antarmuka, tetapi itu tidak perlu

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

Jika Anda menggunakan kelas lain selain Aktivitas, Anda mungkin ingin melakukannya seperti,

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

Menggunakan Kotlin, Anda dapat melakukan hal berikut untuk membaca file dari aset di 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())
}
Vamsi Tallapudi
sumber
2

Mungkin sudah terlambat tetapi demi orang lain yang mencari jawaban bagus:

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;
}
ucMedia
sumber
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 + "";

    }
tej shah
sumber
Tautan sekarang kembaliFile no longer available That file has now been permanently removed and cannot be recovered
gregn3
1

Kelas Scanner dapat menyederhanakan ini.

        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());
Solomon P. Byer
sumber
Anda dapat menggabungkan 2 baris ini sb.append (scanner.nextLine ()); sb.append ('\ n'); ke sb.appendln (scanner.nextLine ());
Mojtaba
0

@HpTerm jawab versi 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
}
Manohar Reddy
sumber
Saat ini ini akan menambahkan nol ke string. Perubahan yang dibutuhkan: var mLine:Stringharus var mLine:String? var data: String?harus var data = ""kembali jenis harusString
fupduck
0

Berikut cara untuk mendapatkan InputStream untuk file dalam assetsfolder tanpa Context, Activity, Fragmentatau Application. Bagaimana Anda mendapatkan data dari itu InputStreamterserah Anda. Ada banyak saran untuk itu dalam jawaban lain di sini.

Kotlin

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

Jawa

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

Semua taruhan dibatalkan jika ada kebiasaan ClassLoaderyang dimainkan.

Bartonstanley
sumber