从资产文件夹超过1M加载文件较大从资产文件夹超过1M加载文件较大(Load files bigger

2019-05-10 10:43发布

我要疯了,我创建了一个文件对象,因此它可以用ObjectInputStream中读出,并且我把资产的文件夹。 该方法适用于小于1M的文件,并且给出错误处理更大的文件。 我读的是Android平台的限制,但我也知道,可以“轻松地”避免。 这些谁下载了游戏Reging雷霆,例如,可以很容易地看到,在他们的资产文件夹是文件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();

现在我有一个未压缩的文件,我可以使用它,而不用担心错误“此文件无法打开的文件描述符;它可能压缩”

此功能与超过1M,更小的文件,效果很好具有更大的文件就行返回java.io.IOException的“ObjectInputStream的OIS =新ObjectInputStream的(是)”

为什么??

Answer 1:

面对同样的问题。 我剪了我的4MB的文件到1个MB块,并且在第一次运行我加入大块到手机上的数据文件夹。 作为额外的奖励,将APK适当压缩。 该块文件被称为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();
}


Answer 2:

限制是对压缩的资产。 如果该资源是未压缩的,该系统可以内存映射文件数据,并使用Linux虚拟内存分页系统来拉或丢弃4K块适当。 (其中“的zipalign”工具确保了未压缩的资产是字对齐的文件,这意味着它们会也在存储器时直接映射对齐英寸)

如果资产被压缩,系统具有解压缩整个事情的记忆。 如果你有一个20MB的资产,这意味着物理内存20MB,通过您的应用程序捆绑。

理想情况下,系统会采用某种形式的窗口压缩的,因此,只有部分需要存在,但是这需要资产API以及与随机存取行之有效的压缩方案中的一些装饰性。 眼下APK ==拉链与“放气”的压缩,所以这是不实际的。

你可以把你的资产,让他们不会得到压缩(例如,“巴纽”或” .MP3" )的文件类型的后缀压缩。 您还可能能够在构建过程与手动添加“拉链-0”,而不是让他们通过AAPT捆绑起来。 这可能会增加您的APK的大小。



Answer 3:

像舍瓦建议您可以在块分割你的文件。 我用这个分裂我的4MB的文件

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



Answer 4:

文件扩展名更改为.mp3



Answer 5:

我知道这是一个老问题,但我认为一个好的解决方案。 为什么不能存储文件已经预先压缩的资源文件夹。 然后,因为它已经是一个zip文件,因此压缩也不会需要被再次压缩。 所以,如果你想要的文件进行压缩以减少apk文件的大小,但你不想对付分裂的文件,我觉得这是比较容易。

当你需要阅读该文件关闭设备只是包装在zipinputstream InputStream的http://developer.android.com/reference/java/util/zip/ZipInputStream.html



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


Answer 7:

添加文件扩展名是mp3.I使用mydb.mp3in资产文件夹,复制。这不error.show检查运行。



Answer 8:

gzip将是另一个方法。 你只需要包装的InputStream里面GZIPInputStream

我用这一个数据库,其大小约3.0 MB和输出压缩文件约600KB。

  • 对于杉杉运行复制DB,我用gzip压缩我的源.db文件GZIP工具 。
  • 然后,它重命名为,以避免更多的压缩的.jpg(这些过程之前,编译APK文件进行)。
  • 然后从assetss读取压缩文件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();
    }


Answer 9:

组数据库与程序如“赢十六进制”多个零件,您可以从下载链接

并继续加载文件大于1M的文件夹中的资产做大



Answer 10:

相反,资产的文件夹的,我已经把我的大文件中的原始文件夹中。 这个对我有用。



Answer 11:

我使用NetBeans构建包,我没有找到如何改变AAPT的设置。 我还没有试过PNG,但MP3被压缩。 我可以编译包,然后输入与参数-0资产文件夹? 什么是正确的命令使用?



文章来源: Load files bigger than 1M from assets folder