我如何编写一个巨大的字节数组来逐步归档并避免可怕的内存错误
How do I write a huge bytearray to file progressively and avoid that dreaded memory error
我正在开发一个 Air 项目,它下载巨大的 (zip) 文件,然后解压缩它们,最后删除它下载的原始 .zip 文件。
一切都运行顺利,除了我想将解压缩的文件写入磁盘时。
麻烦的是,我一直运行进入这个小怪物的错误。
Error: Error #1000: The system is out of memory.
这是让我感到悲伤的代码部分。当文件很小(在 3 MB 文件上测试)时,这非常有效,但是当我尝试其中一个大文件(458 MB)时,我得到了错误。
private function unzipFile()
{
var pulledFile:FZipFile;
var index:int = 0;
var chunkSize:int = 1000000;
Console.log("Unzipping file...");
var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onUnzipComplete);
var fileStream:FileStream = new FileStream();
zip.load(new URLRequest(urlToUnzip));
function onUnzipComplete(e:Event)
{
pulledFile = zip.getFileAt(0);
var file:File = File.documentsDirectory.resolvePath(pulledFile.filename);
fileStream.openAsync(file, FileMode.WRITE);
writeChunk();
}
function writeChunk()
{
var bytesToGet:int = pulledFile.content.bytesAvailable;
if (bytesToGet > chunkSize)
bytesToGet = chunkSize;
Console.log("Writing chunk " + (int((pulledFile.content.length - pulledFile.content.bytesAvailable) / chunkSize) + 1) + " of " + (int(pulledFile.content.length / chunkSize) + 1));
var fileData:ByteArray = new ByteArray();
pulledFile.content.readBytes(fileData, 0, bytesToGet);
fileStream.writeBytes(fileData, 0, fileData.length);
if (index < pulledFile.content.bytesAvailable)
{
writeChunk();
index += bytesToGet;
}
else
{
fileStream.close();
Console.log("Unzipping complete");
}
}
}
代码崩溃具体在行
var bytesToGet:int = pulledFile.content.bytesAvailable;
我如何在不知道有多少字节可用的情况下仍将内容逐步写入文件?如果我无法访问 bytesAvailable
属性,我怎么知道我写完了?
我正在使用the FZip library解压
这很难,但我想通了。诀窍是使用 FZip
的 "serialize" 方法并避免完全接触内容的属性 ByteArray
。
这是有效的最终代码。
private function unzipFile()
{
var pulledFile:FZipFile;
Console.log("Decompressing file...");
var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onUnzipComplete);
var fileStream:FileStream = new FileStream();
zip.load(new URLRequest(urlToUnzip));
function onUnzipComplete(e:Event)
{
pulledFile = zip.getFileAt(0);
var file:File = File.documentsDirectory.resolvePath("Easywatch/" + pulledFile.filename);
fileStream.open(file, FileMode.WRITE);
zip.serialize(fileStream, false);
fileStream.close();
Console.log("Decompression complete");
}
}
我正在开发一个 Air 项目,它下载巨大的 (zip) 文件,然后解压缩它们,最后删除它下载的原始 .zip 文件。
一切都运行顺利,除了我想将解压缩的文件写入磁盘时。
麻烦的是,我一直运行进入这个小怪物的错误。
Error: Error #1000: The system is out of memory.
这是让我感到悲伤的代码部分。当文件很小(在 3 MB 文件上测试)时,这非常有效,但是当我尝试其中一个大文件(458 MB)时,我得到了错误。
private function unzipFile()
{
var pulledFile:FZipFile;
var index:int = 0;
var chunkSize:int = 1000000;
Console.log("Unzipping file...");
var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onUnzipComplete);
var fileStream:FileStream = new FileStream();
zip.load(new URLRequest(urlToUnzip));
function onUnzipComplete(e:Event)
{
pulledFile = zip.getFileAt(0);
var file:File = File.documentsDirectory.resolvePath(pulledFile.filename);
fileStream.openAsync(file, FileMode.WRITE);
writeChunk();
}
function writeChunk()
{
var bytesToGet:int = pulledFile.content.bytesAvailable;
if (bytesToGet > chunkSize)
bytesToGet = chunkSize;
Console.log("Writing chunk " + (int((pulledFile.content.length - pulledFile.content.bytesAvailable) / chunkSize) + 1) + " of " + (int(pulledFile.content.length / chunkSize) + 1));
var fileData:ByteArray = new ByteArray();
pulledFile.content.readBytes(fileData, 0, bytesToGet);
fileStream.writeBytes(fileData, 0, fileData.length);
if (index < pulledFile.content.bytesAvailable)
{
writeChunk();
index += bytesToGet;
}
else
{
fileStream.close();
Console.log("Unzipping complete");
}
}
}
代码崩溃具体在行
var bytesToGet:int = pulledFile.content.bytesAvailable;
我如何在不知道有多少字节可用的情况下仍将内容逐步写入文件?如果我无法访问 bytesAvailable
属性,我怎么知道我写完了?
我正在使用the FZip library解压
这很难,但我想通了。诀窍是使用 FZip
的 "serialize" 方法并避免完全接触内容的属性 ByteArray
。
这是有效的最终代码。
private function unzipFile()
{
var pulledFile:FZipFile;
Console.log("Decompressing file...");
var zip:FZip = new FZip();
zip.addEventListener(Event.COMPLETE, onUnzipComplete);
var fileStream:FileStream = new FileStream();
zip.load(new URLRequest(urlToUnzip));
function onUnzipComplete(e:Event)
{
pulledFile = zip.getFileAt(0);
var file:File = File.documentsDirectory.resolvePath("Easywatch/" + pulledFile.filename);
fileStream.open(file, FileMode.WRITE);
zip.serialize(fileStream, false);
fileStream.close();
Console.log("Decompression complete");
}
}