Проблемы с ресурсами .openRawResource()

У меня есть файл базы данных в папке res/raw/. Я вызываю Resources.openRawResource() с именем файла как R.raw.FileName, и я получаю поток ввода, но у меня есть другой файл базы данных на устройстве, поэтому для копирования содержимого этого db на устройство db я использую:

 BufferedInputStream bi = new BufferedInputStream(is);

и FileOutputStream, но я получаю исключение, что файл базы данных поврежден. Как я могу продолжить? Я пытаюсь прочитать файл с помощью File и FileInputStream, а путь - /res/raw/fileName, но это также не работает.

Ответ 1

Да, вы можете использовать openRawResource для копирования двоичного файла из папки исходных ресурсов на устройство.

На основе кода примера в демонстрационных версиях API (content/ReadAsset) вы можете использовать вариант следующего фрагмента кода для чтения данных файла db.

InputStream ins = getResources().openRawResource(R.raw.my_db_file);
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
int size = 0;
// Read the entire resource into a local byte buffer.
byte[] buffer = new byte[1024];
while((size=ins.read(buffer,0,1024))>=0){
  outputStream.write(buffer,0,size);
}
ins.close();
buffer=outputStream.toByteArray();

Теперь копия вашего файла должна существовать в buffer, поэтому вы можете использовать FileOutputStream для сохранения буфера в новый файл.

FileOutputStream fos = new FileOutputStream("mycopy.db");
fos.write(buffer);
fos.close();

Ответ 2

InputStream.available имеет серьезные ограничения и никогда не должен использоваться для определения длины содержимого, доступного для потоковой передачи.

http://developer.android.com/reference/java/io/FileInputStream.html#available(): "[...] Возвращает оценочное количество байтов, которые могут быть прочитаны или пропущены без блокировки для большего ввода. [...] Обратите внимание, что этот метод обеспечивает такую ​​слабую гарантию, что на практике это не очень полезно."

У вас есть 3 решения:

  • Просматривайте содержимое дважды, сначала просто для вычисления длины содержимого, во-вторых, чтобы действительно прочитать данные.
  • Поскольку ресурсы Android подготовлены вами, разработчик, hardcode его ожидаемая длина
  • Поместите файл в каталог /asset и прочитайте его через AssetManager, который даст вам доступ к AssetFileDescriptor и его методам длины содержимого. Однако это может дать вам значение UNKNOWN для длины, что не так полезно.