Загружать файлы размером более 1M из папки с файлами

Я схожу с ума, я создал файл-объект, поэтому его можно прочитать с помощью ObjectInputStream, и я поместил папку с ресурсами. Метод работает с файлом, меньшим 1M, и дает ошибку с большими файлами. Я читал, что это предел платформы Android, но я также знаю, что можно «легко» избежать. Например, те, кто загрузил игру Reging Thunder, могут легко увидеть, что в их папке с файлами находится файл размером 18.9M. Это мой код для чтения 1 объекта из ObjecInputStream

File f = File.createTempFile("mytempfile", "dat"); FileOutputStream fos = new FileOutputStream(f); InputStream is = mc.getAssets().open(path,3); ObjectInputStream ois=new ObjectInputStream(is); byte[] data = (byte[]) ois.readObject(); fos.write(data); fos.flush(); fos.close(); ois.close(); is.close(); 

Теперь у меня есть несжатый файл, и я могу использовать его, не беспокоясь об ошибке «Этот файл не может быть открыт как дескриптор файла, он, вероятно, сжат»

Эта функция хорошо работает с файлами размером менее 1 МБ, а большие файлы возвращают java.io.IOException в строке «ObjectInputStream ois = new ObjectInputStream (is)»;

Зачем??

Solutions Collecting From Web of "Загружать файлы размером более 1M из папки с файлами"

Столкнулся с той же проблемой. Я разрезал свой файл размером 4 МБ в 1 Мб фрагментов, и в первом запуске я присоединяюсь к кускам в папку с данными по телефону. В качестве дополнительного бонуса APK должным образом сжимается. Файлы chunk называются 1.db, 2.db и т. Д. Код выглядит следующим образом:

 File Path = Ctxt.getDir("Data", 0); File DBFile = new File(Path, "database.db"); if(!DBFile.exists() || DatabaseNeedsUpgrade) //Need to copy... CopyDatabase(Ctxt, DBFile); static private void CopyDatabase(Context Ctxt, File DBFile) throws IOException { AssetManager assets = Ctxt.getAssets(); OutputStream outstream = new FileOutputStream(DBFile); DBFile.createNewFile(); byte []b = new byte[1024]; int i, r; String []assetfiles = assets.list(""); Arrays.sort(assetfiles); for(i=1;i<10;i++) //I have definitely less than 10 files; you might have more { String partname = String.format("%d.db", i); if(Arrays.binarySearch(assetfiles, partname) < 0) //No such file in assets - time to quit the loop break; InputStream instream = assets.open(partname); while((r = instream.read(b)) != -1) outstream.write(b, 0, r); instream.close(); } outstream.close(); } 

Ограничение на сжатые активы. Если ресурс несжатый, система может отображать данные на карте памяти и использовать систему подкачки виртуальной памяти Linux, чтобы потянуть или отбросить 4K куски, если это необходимо. (Инструмент «zipalign» гарантирует, что несжатые ресурсы выравниваются по словам в файле, что означает, что они также будут выровнены в памяти при прямом сопоставлении.)

Если актив сжат, система должна распаковать всю вещь в памяти. Если у вас есть ресурс 20 МБ, это означает, что 20 МБ физической памяти привязано к вашему приложению.

В идеале система использует какое-то оконное сжатие, так что должны присутствовать только части, но для этого требуется определенная привязанность API-интерфейса и схема сжатия, которая хорошо работает со случайным доступом. Прямо сейчас APK == Zip с «спящим» сжатием, так что это не практично.

Вы можете сохранить свои активы несжатыми, указав им суффикс типа файла, который не сжимается (например, «.png» или «.mp3»). Вы также можете добавить их вручную во время процесса сборки с помощью «zip -0» вместо того, чтобы связать их с помощью aapt. Вероятно, это увеличит размер вашего APK.

Как и Сева, вы можете разделить свой файл на куски. Я использовал это, чтобы разделить мой файл размером 4 МБ

 public static void main(String[] args) throws Exception { String base = "tracks"; String ext = ".dat"; int split = 1024 * 1024; byte[] buf = new byte[1024]; int chunkNo = 1; File inFile = new File(base + ext); FileInputStream fis = new FileInputStream(inFile); while (true) { FileOutputStream fos = new FileOutputStream(new File(base + chunkNo + ext)); for (int i = 0; i < split / buf.length; i++) { int read = fis.read(buf); fos.write(buf, 0, read); if (read < buf.length) { fis.close(); fos.close(); return; } } fos.close(); chunkNo++; } } 

Если вам не нужно снова объединять файлы в один файл на устройстве, просто используйте этот InputStream, который объединяет их в один на лету.

 import java.io.IOException; import java.io.InputStream; import android.content.res.AssetManager; public class SplitFileInputStream extends InputStream { private String baseName; private String ext; private AssetManager am; private int numberOfChunks; private int currentChunk = 1; private InputStream currentIs = null; public SplitFileInputStream(String baseName, String ext, int numberOfChunks, AssetManager am) throws IOException { this.baseName = baseName; this.am = am; this.numberOfChunks = numberOfChunks; this.ext = ext; currentIs = am.open(baseName + currentChunk + ext, AssetManager.ACCESS_STREAMING); } @Override public int read() throws IOException { int read = currentIs.read(); if (read == -1 && currentChunk < numberOfChunks) { currentIs.close(); currentIs = am.open(baseName + ++currentChunk + ext, AssetManager.ACCESS_STREAMING); return read(); } return read; } @Override public int available() throws IOException { return currentIs.available(); } @Override public void close() throws IOException { currentIs.close(); } @Override public void mark(int readlimit) { throw new UnsupportedOperationException(); } @Override public boolean markSupported() { return false; } @Override public int read(byte[] b, int offset, int length) throws IOException { int read = currentIs.read(b, offset, length); if (read < length && currentChunk < numberOfChunks) { currentIs.close(); currentIs = am.open(baseName + ++currentChunk + ext, AssetManager.ACCESS_STREAMING); read += read(b, offset + read, length - read); } return read; } @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @Override public synchronized void reset() throws IOException { if (currentChunk == 1) { currentIs.reset(); } else { currentIs.close(); currentIs = am.open(baseName + currentChunk + ext, AssetManager.ACCESS_STREAMING); currentChunk = 1; } } @Override public long skip(long n) throws IOException { long skipped = currentIs.skip(n); if (skipped < n && currentChunk < numberOfChunks) { currentIs.close(); currentIs = am.open(baseName + ++currentChunk + ext, AssetManager.ACCESS_STREAMING); skipped += skip(n - skipped); } return skipped; } } 

Применение:
ObjectInputStream ois = new ObjectInputStream(new SplitFileInputStream("mytempfile", ".dat", 4, getAssets()));

Une methode pas propre состоит из сменщика extention du fichier ttf mp3

Я нашел другое решение, возможно, вас это интересует.

В корне ваших источников, где у вас есть файл build.xml , вы можете перезаписать цель custom_rules.xml -package-resources в файле custom_rules.xml , который используется для добавления / изменения целей в муравье, не нарушая ничего в стандартном приложении для Android. Построить систему.

Просто создайте файл с этим контентом:

 <?xml version="1.0" encoding="UTF-8"?> <project name="yourAppHere" default="help"> <target name="-package-resources" depends="-crunch"> <!-- only package resources if *not* a library project --> <do-only-if-not-library elseText="Library project: do not package resources..." > <aapt executable="${aapt}" command="package" versioncode="${version.code}" versionname="${version.name}" debug="${build.is.packaging.debug}" manifest="${out.manifest.abs.file}" assets="${asset.absolute.dir}" androidjar="${project.target.android.jar}" apkfolder="${out.absolute.dir}" nocrunch="${build.packaging.nocrunch}" resourcefilename="${resource.package.file.name}" resourcefilter="${aapt.resource.filter}" libraryResFolderPathRefid="project.library.res.folder.path" libraryPackagesRefid="project.library.packages" libraryRFileRefid="project.library.bin.r.file.path" previousBuildType="${build.last.target}" buildType="${build.target}" ignoreAssets="${aapt.ignore.assets}"> <res path="${out.res.absolute.dir}" /> <res path="${resource.absolute.dir}" /> <nocompress /> <!-- forces no compression on any files in assets or res/raw --> <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw --> </aapt> </do-only-if-not-library> </target> </project> 

Я знаю, что это старый вопрос, но я подумал о хорошем решении. Почему бы не сохранить файл, предварительно запрограммированный в папке с ресурсами. Тогда, поскольку он уже является zip-файлом и поэтому сжат, его больше не нужно будет сжимать. Поэтому, если вы хотите, чтобы файл был сжат, чтобы уменьшить размер вашего apk, но вы не хотите заниматься расщеплением файлов, я думаю, что это проще.

Когда вам нужно прочитать этот файл с устройства, просто оберните входной поток в zipinputstream http://developer.android.com/reference/java/util/zip/ZipInputStream.html

Добавить расширение файла mp3.I использовать mydb.mp3in папку с ресурсами и скопировать. Это бежать без error.show проверить его.

Использование GZIP было бы другим методом. Вам нужно только обернуть InputStream внутри GZIPInputStream .

Я использовал это для базы данных размером около 3,0 МБ, а выходной файл сжатия – около 600 КБ.

  • Для копирования DB в первый запуск, я gzipped мой исходный .db файл с помощью GZIP инструмент .
  • Затем переименовали его в .jpg, чтобы избежать большего сжатия (эти процессы выполняются перед компиляцией APK FILE).
  • Затем для чтения сжатого файла GZIP из активов

И копирование:

 private void copydatabase() throws IOException { // Open your local db as the input stream InputStream myinput = mContext.getAssets().open(DB_NAME_ASSET); BufferedInputStream buffStream = new BufferedInputStream(myinput); GZIPInputStream zis = new GZIPInputStream(buffStream); // Path to the just created empty db String outfilename = DB_PATH + DB_NAME; // Open the empty db as the output stream OutputStream myoutput = new FileOutputStream(outfilename); // transfer byte to inputfile to outputfile byte[] buffer = new byte[1024]; int length; while ((length = zis.read(buffer)) > 0) { myoutput.write(buffer, 0, length); } // Close the streams myoutput.flush(); myoutput.close(); zis.close(); buffStream.close(); myinput.close(); } 

Установите базу данных на несколько частей с помощью программы, например «Win Hex», которую вы можете скачать из Link

И продолжить Загружать файлы размером более 1M из папки с файлами

Вместо папки с ресурсами я поместил свои большие файлы в необработанную папку. Меня устраивает.

Я использую NetBeans для сборки пакета, и я не нашел, как изменить настройки AAPT. Я не пробовал png, но mp3 сжаты. Я могу скомпилировать пакет, а затем ввести папку с параметрами -0? Что было бы правильной командой для использования?