我要疯了,我创建了一个文件对象,因此它可以用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的(是)”
为什么??
面对同样的问题。 我剪了我的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();
}
限制是对压缩的资产。 如果该资源是未压缩的,该系统可以内存映射文件数据,并使用Linux虚拟内存分页系统来拉或丢弃4K块适当。 (其中“的zipalign”工具确保了未压缩的资产是字对齐的文件,这意味着它们会也在存储器时直接映射对齐英寸)
如果资产被压缩,系统具有解压缩整个事情的记忆。 如果你有一个20MB的资产,这意味着物理内存20MB,通过您的应用程序捆绑。
理想情况下,系统会采用某种形式的窗口压缩的,因此,只有部分需要存在,但是这需要资产API以及与随机存取行之有效的压缩方案中的一些装饰性。 眼下APK ==拉链与“放气”的压缩,所以这是不实际的。
你可以把你的资产,让他们不会得到压缩(例如,“巴纽”或” .MP3" )的文件类型的后缀压缩。 您还可能能够在构建过程与手动添加“拉链-0”,而不是让他们通过AAPT捆绑起来。 这可能会增加您的APK的大小。
像舍瓦建议您可以在块分割你的文件。 我用这个分裂我的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()));
我知道这是一个老问题,但我认为一个好的解决方案。 为什么不能存储文件已经预先压缩的资源文件夹。 然后,因为它已经是一个zip文件,因此压缩也不会需要被再次压缩。 所以,如果你想要的文件进行压缩以减少apk文件的大小,但你不想对付分裂的文件,我觉得这是比较容易。
当你需要阅读该文件关闭设备只是包装在zipinputstream InputStream的http://developer.android.com/reference/java/util/zip/ZipInputStream.html
我发现了另一个解决方案,也许你对它感兴趣。
在你的源代码,在那里你有根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>
添加文件扩展名是mp3.I使用mydb.mp3in资产文件夹,复制。这不error.show检查运行。
用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();
}
组数据库与程序如“赢十六进制”多个零件,您可以从下载链接
并继续加载文件大于1M的文件夹中的资产做大
相反,资产的文件夹的,我已经把我的大文件中的原始文件夹中。 这个对我有用。
我使用NetBeans构建包,我没有找到如何改变AAPT的设置。 我还没有试过PNG,但MP3被压缩。 我可以编译包,然后输入与参数-0资产文件夹? 什么是正确的命令使用?