Подтвердить что ты не робот

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

Я схожу с ума, я создал файл-объект, поэтому его можно прочитать с помощью 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);"

почему??

4b9b3361

Ответ 1

Столкнулась с той же проблемой. Я разрезал свой файл размером 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();
}

Ответ 2

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

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

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

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

Ответ 3

Как и Сева, вы можете разделить свой файл на куски. Я использовал это, чтобы разделить мой файл размером 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()));

Ответ 4

une methode pas propre состоит из расширений чейнджера du fichier ttf a mp3

Ответ 5

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

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

Ответ 6

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

В корне ваших источников, где у вас есть файл build.xml, вы можете перезаписать цель -package-resources в файле custom_rules.xml, который используется для добавления/изменения целей в ant без нарушения чего-либо в стандартная система сборки приложений 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>

Ответ 7

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

Ответ 8

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

Ответ 9

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

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

  • Для копирования DB в firs run, я 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();
    }

Ответ 11

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