Как получить строку пути Android к файлу в папке Assets? - PullRequest
59 голосов
/ 12 декабря 2011

Мне нужно знать строковый путь к файлу в папке ресурсов, потому что я использую API карты, который должен получить строковый путь, а мои карты должны храниться в папке ресурсов

Это код, который я пытаюсь:

    MapView mapView = new MapView(this);
    mapView.setClickable(true);
    mapView.setBuiltInZoomControls(true);
    mapView.setMapFile("file:///android_asset/m1.map");
    setContentView(mapView);

Что-то не так с "file:///android_asset/m1.map", потому что карта не загружается.

Какой правильный файл пути к файлу m1.map хранится в папке моих активов?

Спасибо

РЕДАКТИРОВАТЬ для Dimitru: Этот код не работает, он не работает на is.read(buffer); с IOException

        try {
            InputStream is = getAssets().open("m1.map");
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            text = new String(buffer);
        } catch (IOException e) {throw new RuntimeException(e);}

Ответы [ 4 ]

87 голосов
/ 12 декабря 2011

AFAIK файлы в каталоге ресурсов не распаковываются. Вместо этого они считываются непосредственно из файла APK (ZIP).

Таким образом, вы действительно не можете делать вещи, которые ожидают, что файл принимает "файл" ресурса.

Вместо этого вам придется извлечь ресурс и записать его в отдельный файл, как предлагает Думитру:

  File f = new File(getCacheDir()+"/m1.map");
  if (!f.exists()) try {

    InputStream is = getAssets().open("m1.map");
    int size = is.available();
    byte[] buffer = new byte[size];
    is.read(buffer);
    is.close();


    FileOutputStream fos = new FileOutputStream(f);
    fos.write(buffer);
    fos.close();
  } catch (Exception e) { throw new RuntimeException(e); }

  mapView.setMapFile(f.getPath());
9 голосов
/ 12 декабря 2011

Взгляните на файл ReadAsset.java из примеров API, поставляемых с SDK.

       try {
        InputStream is = getAssets().open("read_asset.txt");

        // We guarantee that the available method returns the total
        // size of the asset...  of course, this does mean that a single
        // asset can't be more than 2 gigs.
        int size = is.available();

        // Read the entire asset into a local byte buffer.
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();

        // Convert the buffer into a string.
        String text = new String(buffer);

        // Finally stick the string into the text view.
        TextView tv = (TextView)findViewById(R.id.text);
        tv.setText(text);
    } catch (IOException e) {
        // Should never happen!
        throw new RuntimeException(e);
    }
8 голосов
/ 04 ноября 2013

Вы можете использовать этот метод.

    public static File getRobotCacheFile(Context context) throws IOException {
        File cacheFile = new File(context.getCacheDir(), "robot.png");
        try {
            InputStream inputStream = context.getAssets().open("robot.png");
            try {
                FileOutputStream outputStream = new FileOutputStream(cacheFile);
                try {
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = inputStream.read(buf)) > 0) {
                        outputStream.write(buf, 0, len);
                    }
                } finally {
                    outputStream.close();
                }
            } finally {
                inputStream.close();
            }
        } catch (IOException e) {
            throw new IOException("Could not open robot png", e);
        }
        return cacheFile;
    }

Вы не должны никогда не использовать InputStream.available () в таких случаях.Он возвращает только байты, которые буферизируются.Метод с .available () никогда не будет работать с большими файлами и вообще не будет работать на некоторых устройствах.

В Kotlin (; D):

@Throws(IOException::class)
fun getRobotCacheFile(context: Context): File = File(context.cacheDir, "robot.png")
    .also {
        it.outputStream().use { cache -> context.assets.open("robot.png").use { it.copyTo(cache) } }
    }
3 голосов
/ 29 июня 2017

Просто чтобы добавить идеальное решение Яцека.Если вы пытаетесь сделать это в Котлине, это не сработает немедленно.Вместо этого вы захотите использовать это:

@Throws(IOException::class)
fun getSplashVideo(context: Context): File {
    val cacheFile = File(context.cacheDir, "splash_video")
    try {
        val inputStream = context.assets.open("splash_video")
        val outputStream = FileOutputStream(cacheFile)
        try {
            inputStream.copyTo(outputStream)
        } finally {
            inputStream.close()
            outputStream.close()
        }
    } catch (e: IOException) {
        throw IOException("Could not open splash_video", e)
    }
    return cacheFile
}
...