Unity使用lzma的测试记录

本文记录了在Unity中使用LZMA压缩资源文件的测试过程。通过创建头文件存储资源路径和长度,将所有资源合并压缩到单一内存流中。
对资源文件的传输总会需要压缩以减小尺寸。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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值