varlıklardan dosyayı oku


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

Bu kodu varlıklardan bir dosya okumaya çalışıyorum. Bunu yapmanın iki yolunu denedim. Birincisi, Filealdığım kullanım FileNotFoundException, AssetManager getAssets()yöntem kullanılırken tanınmıyor. Burada bir çözüm var mı?

Yanıtlar:


225

Tampon okuma için bir aktivitede yaptığım şey, ihtiyaçlarınıza göre genişlet / değiştir

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

DÜZENLEME: Sorunuz bir etkinliğin dışında nasıl yapılacağı ile ilgiliyse cevabım belki işe yaramaz. Sorunuz basitçe öğeden bir dosyayı nasıl okuyacağınız ise cevap yukarıdadır.

GÜNCELLEME :

Türü belirten bir dosyayı açmak için türü aşağıdaki gibi InputStreamReader çağrısına ekleyin.

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

DÜZENLE

@Stan'ın yorumda söylediği gibi, verdiğim kod satırları özetlemiyor. mLineher geçişte değiştirilir. Bu yüzden yazdım //process line. Dosya bir tür veri (yani bir kişi listesi) içeriyor ve her satır ayrı ayrı işlenmesi gerektiğini varsayalım.

Dosyayı herhangi bir işlem yapmadan yüklemek istiyorsanız mLine, her geçişi kullanarak StringBuilder()ve her geçişte özetlemeniz gerekir .

BAŞKA BİR DÜZENLEME

@ Vincent yorumuna göre finallybloğu ekledim .

Ayrıca Java 7 ve üst sürümlerinde, en son Java'nın ve özelliklerini kullanmak try-with-resourcesiçin kullanabileceğinizi unutmayın .AutoCloseableCloseable

BAĞLAM

Bir yorumda @LunarWatcher getAssets()bunun classiçinde olduğuna dikkat çekiyor context. Yani, bunu bir dışında çağırırsanız, ona activitybaşvurmanız ve bağlam örneğini etkinliğe geçirmeniz gerekir.

ContextInstance.getAssets();

Bu @Maneesh cevabında açıklanmaktadır. Eğer bu sizin için faydalıysa cevabını onaylayın, çünkü bunu işaret eden oydu.


2
@Stan, sonra yorumlarda yazın ve yazarın güncellemek isteyip istemediğine karar vermesine izin verin. Düzenlemeler, anlamı değiştirmek yerine netliği artırmak içindir. Kod revizyonları her zaman önce yorum olarak gönderilmelidir.
KyleMit

2
Kodunuz akışı kapatmayı ve kaynağı zamanında boşaltmayı garanti etmez. Kullanmanızı tavsiye ederim finally {reader.close();}.
Vincent Cantin

2
Yukarıdaki kod ADT - "reader.close ();" bir hata gösteriyor işaret etmek yararlı olduğunu düşünüyorum satırının başka bir try-catch bloğuna konması gerekir. Bu konuyu kontrol et: stackoverflow.com/questions/8981589/… :)
JakeP

1
getAssets, Context'te bir sınıftır, bu nedenle etkinlik dışındaki kullanım için Context çağrısının yapılması gerekir. Yani bir faaliyetin dışında, böyle bir şey olacakcontext.getAssets(.....)
Zoe

1
Güncellemenize göre (bu btw'yi eklediğiniz için teşekkürler), statik alanlarda bağlam olması bellek sızıntısıdır. Bu dikkatli kullanılmalı ve uygun şekilde temizlenmelidir. Aksi takdirde, uygulama üzerinde büyük etkisi olabilecek bir bellek sızıntısıyla karşılaşırsınız.
Zoe

65
getAssets()

yalnızca bunun için kullanmanız gereken herhangi bir sınıftaki Etkinlik'te çalışır Context.

Bir yapmak Utils kurucu buna bir parametre olarak sınıf geçme aktivitesinin referans (çirkin bir şekilde) ya da uygulama bağlamında. Bunu kullanarak Utils sınıfınızda getAsset () kullanın.


1
Faaliyetin pek çoğundan biri olduğu bir Bağlam alt sınıfı olan herhangi bir şey üzerinde çalışır.
Jeremy Logan

Az önce yazdığımı not ettim Context.
user370305

@ user370305, InputStream'i FileInputStream'e nasıl dönüştürebilirim biliyor musunuz?
hotHead

@ user370305 bu ne çirkin?
Sevastyan Savanyuk

Sonuçları dikkate almadan UI nesnelerini iletmek genellikle kötü bir uygulamadır. Dikkatli değilseniz, bellek sızıntılarına neden olabilir veya ölü bağlamlar kullanmaya çalışabilirsiniz. Konu hakkında iyi okuma: android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570
milosmlar

49

Geç olsun güç olmasın.

Bazı durumlarda dosyaları satır satır okumakta zorlandım. Aşağıdaki yöntem şimdiye kadar bulduğum en iyisidir ve tavsiye ederim.

Kullanımı: String yourData = LoadData("YourDataFile.txt");

Nerede YourDataFile.txt ikamet varsayılır varlıklar /

 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;

 }

Dönüş
dizem

burada aynı, res.AssetManager $ AssetInputStream @ .... bunu döndürmesinin belirli bir nedeni var mı?
Bigs

Belleği iki kez ayırırsınız - önce arabellek için, ardından Dize için. Daha büyük dosyalar için çalışmaz.
JaakL

1
arabellek boyutu ayırmak için mükemmel bir yol 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();
}

BufferedReader'ı kapatırsanız, InputStreanReader ve InputStream öğelerinin de otomatik olarak kapatılması gerektiğini düşünürsünüz. Çünkü bunlar için bir tutamaç oluşturmazsınız, örneğin input = new BufferedReader(new InputStreamReader(fIn));.
trans

3
Sonunda tüm kaynaklarınızı kapatmak için ayrı try / catch blokları oluşturmanızı öneririm; hepsini bir araya getirmek yerine - başka bir kaynağı kapatma girişimi bir istisna atarsa, diğer kaynakları açık bırakmayabilir.
Reece

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

8

kotlin için bir satır çözüm:

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

7

getAssets() yöntemi, Activity sınıfının içinde çağırdığınızda çalışır.

Bu yöntemi Activity olmayan sınıfta çağırıyorsanız, bu yöntemi Activity sınıfından geçirilen Context'ten çağırmanız gerekir. Bu nedenle, aşağıdaki yönteme erişebilirsiniz.

ContextInstance.getAssets();

ContextInstance Activity sınıfının bu haliyle iletilebilir.


5

Dosyaları okumak ve yazmak her zaman ayrıntılı ve hataya açık hale gelmiştir. Bu cevaplardan kaçının ve bunun yerine Okio'yu kullanın:

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
Bunun neden daha estetik ve kısa göründüğünü biliyor musunuz? En azından burada kodun yarısını atladınız. Atlanan bölümler: 1) IOExceptiondenemesi / yakalama bloğu 2) İstisna atıldığında akışları kapatma 3) Bu kod, dosyanın tamamını değil tek bir satırı okur. Performans açısından, bu kütüphane kesinlikle türünün biridir, şüphesiz. Şimdi söyle bana "bu cevaplardan" kaçınmalı mıyım ve Okio'yu sadece dosyaları okumak için mi uygulayayım? Zaten uygulamanızın bir parçası değilse, yanıt HAYIR.
Farid

Cevabım güncellendi.
Saket

4

Varlıklardaki bir dosyayı okumak için bir yöntem:

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

Bu iyi bir yanıttır, ancak Dize birleştirmeyi kullanmak kötü bir yaklaşımdır. Bunun yerine StringBuilder kullanmayı düşünün. StringBuilder contentBuilder = new StringBuilder (); while ((line = reader.readLine ())! = null) {builder.append ("\ n"). append (line); } Ve sonunda bununla yeni String nesnesi oluşturabilirsiniz: content = contentBuilder.toString ();
Barterio

4

İçeriği dosyadan yükleyebilirsiniz. Dosyanın varlık klasöründe olduğunu düşünün.

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

Şimdi fonksiyonu aşağıdaki gibi çağırarak içeriği alabilirsiniz

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

Data.json dikkate alındığında Application \ app \ src \ main \ asset \ data.json dizininde saklanır


3

MainActivity.java içinde

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

Ayrıca, tüm işi yapan ayrı bir sınıf oluşturabilirsiniz

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

Bence bir arayüz oluşturmak daha iyi, ama gerekli değil

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

2

Etkinlik dışında başka bir sınıf kullanıyorsanız, bunu yapmak isteyebilirsiniz,

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

2

Kotlin'i kullanarak Android'deki varlıklardan bir dosya okumak için aşağıdakileri yapabilirsiniz:

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

Belki çok geç ama şeftali gibi cevaplar arayan başkalarının uğruna:

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 + "";

    }

Bağlantı şimdi geri dönüyorFile no longer available That file has now been permanently removed and cannot be recovered
gregn3

1

Scanner sınıfı bunu basitleştirebilir.

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

Bu 2 satırı sb.append (scanner.nextLine ()); sb.append ( '\ n'); to sb.appendln (scanner.nextLine ());
Mojtaba

0

@HpTerm cevap Kotlin sürümü:

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
}

Şu anda bu dize null başlayacak. Gerekli değişiklikler: var mLine:Stringolması var mLine:String? var data: String?gerekir var data = ""dönüş türü olmalıdırString
fupduck

0

İşte bir almanın bir yoludur InputStreambir dosya için assetsbir olmadan klasörde Context, Activity, Fragmentveya Application. Verileri bundan nasıl elde InputStreamedeceğiniz size kalmış. Buradaki diğer cevaplarda bunun için birçok öneri var.

Kotlin

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

Java

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

Bir özel oyundaysa tüm bahisler kapalıdır ClassLoader.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.