生活随笔
收集整理的這篇文章主要介紹了
Java解析魔兽争霸3录像W3G文件(二):压缩数据块解压合并
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在上一篇博文中,分析了魔獸爭霸3錄像W3G文件的Header部分的解析。Header部分占文件的前68個字節,緊接著Header之后,也就是從68字節之后,就是多個壓縮數據塊。壓縮數據塊的個數保存在Header中,也就是Header的45~48字節。
所有的壓縮數據塊中的數據實際上是一個整體,被分割成很多塊。錄像文件生成的時候,將原始的數據按8K(8192字節)分割成很多段,最后一段如果不足8K則補0,然后將每一段zlib壓縮,生成一個壓縮數據塊,在每一段前面加上壓縮數據塊的Header(注意,這里所指的Header不是整個錄像文件的Header,而是每個壓縮數據塊的Header)。
所以這里要做的就是遍歷每個壓縮數據塊,解壓縮后再合并,這樣才能還原成原始的數據。
每個壓縮數據塊的結構:
每個壓縮數據塊,由Header和壓縮數據組成。Header部分總共是8個字節,而壓縮數據的字節數大小保存在每一個壓縮數據塊的Header中。
1~2字節(2個字節):壓縮數據的字節數,小字節序。
3~4字節(2個字節):解壓后數據的字節數,固定的值是8192(8KB),小字節序。
5~8字節(4個字節):未知。
9~(n-8)字節(n個字節):壓縮數據(壓縮數據的字節數n就是Header部分1~2字節中的字節數)。
Java處理壓縮數據塊:
定義一個CompressedDataBlock類用來處理每一個壓縮數據庫,包括解析壓縮數據塊的Header,解壓縮數據。在Java中可以使用java.util.zip.Inflater類來解壓縮zlib格式的壓縮數據。
CompressedDataBlock.java
package com.xxg.w3gparser;import java.util.zip.DataFormatException;
import java.util.zip.Inflater;public class CompressedDataBlock {private int compressedDataSize;private int uncompressedDataSize;private byte[] uncompressedDataBytes;/*** @param fileBytes 錄像文件轉成的字節數組* @param offset 壓縮數據塊的開始位置* @throws DataFormatException* @throws W3GException*/public CompressedDataBlock(byte[] fileBytes, int offset) throws DataFormatException, W3GException {System.out.println("開始處理一個壓縮數據塊...");// 壓縮數據大小compressedDataSize = LittleEndianTool.getUnsignedInt16(fileBytes, offset);System.out.println("1-2字節:" + compressedDataSize);// 解壓縮后數據大小uncompressedDataSize = LittleEndianTool.getUnsignedInt16(fileBytes, offset + 2);System.out.println("3-4字節:" + uncompressedDataSize);// 壓縮數據,從第8個字節開始,長度為compressedDataSize,解壓縮uncompressedDataBytes = new byte[uncompressedDataSize];Inflater inflater = new Inflater();inflater.setInput(fileBytes, offset + 8, compressedDataSize);int realUncompressedDataSize = inflater.inflate(uncompressedDataBytes);if(realUncompressedDataSize != uncompressedDataSize) {throw new W3GException("解壓縮數據異常");}}public int getCompressedDataSize() {return compressedDataSize;}public int getUncompressedDataSize() {return uncompressedDataSize;}public byte[] getUncompressedDataBytes() {return uncompressedDataBytes;}}
在Replay類中,遍歷每一個壓縮數據塊,將解壓縮后的數據合并成一個字節數組。
Replay.java
package com.xxg.w3gparser;import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;public class Replay {private Header header;public Replay(File w3gFile) throws IOException, W3GException, DataFormatException {// 將文件轉為字節數組,方便處理byte[] fileBytes = fileToByteArray(w3gFile);// 解析Headerheader = new Header(fileBytes);// 遍歷解析每個壓縮數據塊,解壓縮,合并long compressedDataBlockCount = header.getCompressedDataBlockCount();byte[] uncompressedDataBytes = new byte[0]; // 所有壓縮數據塊中數據解壓合并到這個數組中int offset = 68;for(int i = 0; i < compressedDataBlockCount; i++) {CompressedDataBlock compressedDataBlock = new CompressedDataBlock(fileBytes, offset);// 數組合并byte[] blockUncompressedData = compressedDataBlock.getUncompressedDataBytes();byte[] temp = new byte[uncompressedDataBytes.length + blockUncompressedData.length];System.arraycopy(uncompressedDataBytes, 0, temp, 0, uncompressedDataBytes.length);System.arraycopy(blockUncompressedData, 0, temp, uncompressedDataBytes.length, blockUncompressedData.length);uncompressedDataBytes = temp;int blockCompressedDataSize = compressedDataBlock.getCompressedDataSize();offset += 8 + blockCompressedDataSize;}// 壓縮數據塊解壓合并后結果就是字節數組uncompressedDataBytesSystem.out.println("解壓縮合并后的原始數據字節數:" + uncompressedDataBytes.length);}/*** 將文件轉換成字節數組* @param w3gFile 文件* @return 字節數組* @throws IOException*/private byte[] fileToByteArray(File w3gFile) throws IOException {FileInputStream fileInputStream = new FileInputStream(w3gFile);ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int n;try {while((n = fileInputStream.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, n);}} finally {fileInputStream.close();}return byteArrayOutputStream.toByteArray();}public Header getHeader() {return header;}}
運行程序,輸出:
開始處理一個壓縮數據塊...
1-2字節:4122
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:4218
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:4145
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3849
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3958
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3877
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3783
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3996
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3962
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3987
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:4169
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:4062
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:3828
3-4字節:8192
開始處理一個壓縮數據塊...
1-2字節:1323
3-4字節:8192
解壓縮合并后的原始數據字節數:114688
參考文檔:http://w3g.deepnode.de/files/w3g_format.txt
作者:叉叉哥 ? 轉載請注明出處:http://blog.csdn.net/xiao__gui/article/details/17993589
總結
以上是生活随笔為你收集整理的Java解析魔兽争霸3录像W3G文件(二):压缩数据块解压合并的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。