对资源文件的传输总会需要压缩以减小尺寸。unity支持lzma格式,其压缩效果也挺好。
[下载地址: LZMA SDK ](http://www.7-zip.org/sdk.html)
为了实现不同资源文件压缩成一个,首先需要记录每个资源文件的路径以及长度,作为头文件信息,将此头文件和对应资源文件(byte格式)一起写入memoryStream。
for (int i = 0; i < filePathCount; i++)
{
string assetPath = AssetDatabase.GetAssetPath(resourcesLis[i]);
string filePath = prePath + assetPath;
string zipBundlePath = assetPath.Replace("Assets/", "");
FileStream tempFileStream = File.Open(filePath, FileMode.Open);
//头文件信息设置 assets下路径 + 尺寸 + 回车分隔符
StringBuilder sb = new StringBuilder();
sb.Append(zipBundlePath).
Append(",").
Append(tempFileStream.Length).
Append("\n");
byte[] tempBuff = new byte[tempFileStream.Length];
byte[] header = Encoding.UTF8.GetBytes(sb.ToString());
//字节数组格式的文件数据
tempFileStream.Read(tempBuff, 0, (int)tempFileStream.Length);
// 写入临时内存流
memoryStream.Write(header, 0, header.Length);
memoryStream.Write(tempBuff, 0, tempBuff.Length);
tempFileStream.Close();
}
之后进行lzma接口。调用需要先将组合文件的临时内存流的Position重置为0。
SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
encoder.WriteCoderProperties(compressStream);
CodeProgress codeProgress = new CodeProgress();
codeProgress.totalSize = memoryStream.Length;
// 压缩有回调,可以展示进度
encoder.Code(memoryStream, compressStream, memoryStream.Length, -1, codeProgress);
解压缩就是调逆的过程。先调用lzma的接口。
FileStream compressStream = new FileStream(destFolderPath, FileMode.Open, FileAccess.Read);
MemoryStream tempStream = new MemoryStream();
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
byte[] properties = new byte[5];
compressStream.Read(properties, 0, 5);
decoder.SetDecoderProperties(properties);
long compressRealLen = compressStream.Length - compressStream.Position;
decoder.Code(compressStream, tempStream, compressRealLen, outsize, null);
解压后的文件集合,顺序读取每个文件的头文件信息, 获取解压路径以及每个文件尺寸。
while (tempStream.Position != tempStream.Length)
{
int one = tempStream.ReadByte();
// 根据之前记录的 \n 来切割头文件数据
if (one != 10)
{
head[index++] = (byte)one;
}
else
{
index = 0;
string headStr = Encoding.UTF8.GetString(head);
head = new byte[1024];
string[] headArr = headStr.Split(',');
// assets 下路径名
string fileBundleName = headArr[0];
int lastXIndex = fileBundleName.LastIndexOf("/");
string fileName = fileBundleName.Substring(lastXIndex + 1, fileBundleName.Length - lastXIndex - 1);
string fileFolderName = fileBundleName.Substring(0, lastXIndex);
int fileSize = 0;
if(!int.TryParse(headArr[1], out fileSize))
{
EditorUtility.DisplayDialog("Error", "File size exception!!! -->> " + headArr[1], "ok");
break;
}
// 写入文件路径
string filePath = assetbundlePath + "/Decompress/" + fileFolderName;
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
WriteToLocal(tempStream, fileSize, filePath + "/" + fileName);
}
}
我写时几个问题没考虑好:
1:临时memoryStream的写入后,其Position是否需要进行重置。
2:异常需要添加try catch, 否则文件写入报错会使unity目录出现一些奇怪的反应。
以下是项目路径(其实一个脚本就搞定了ABTest.cs):
https://github.com/feixus/UnityLzmaTest
本文记录了在Unity中使用LZMA压缩资源文件的测试过程。通过创建头文件存储资源路径和长度,将所有资源合并压缩到单一内存流中。

7770

被折叠的 条评论
为什么被折叠?



