public int readNodeFromBitArrStream(PvfHeader header, FileStream fs, byte[] unpackedHeaderTree, int offsite) { try { fileNumber = BitConverter.ToUInt32(unpackedHeaderTree, offsite); filePathLength = BitConverter.ToInt32(unpackedHeaderTree, offsite + 4); byte[] filePath = new byte[filePathLength]; Array.Copy(unpackedHeaderTree, offsite + 8, filePath, 0, filePathLength); fileLength = BitConverter.ToInt32(unpackedHeaderTree, (offsite + filePathLength) + 8); fileCrc32 = BitConverter.ToUInt32(unpackedHeaderTree, (offsite + filePathLength) + 12); relativeOffset = BitConverter.ToInt32(unpackedHeaderTree, (offsite + filePathLength) + 0x10); if (fileLength > 0) { computedFileLength = (int)((fileLength + 3L) & 4294967292L); unpackedFileByteArr = new byte[computedFileLength]; fs.Seek(Marshal.SizeOf(typeof(PvfHeader)) + header.dirTreeLength + relativeOffset, SeekOrigin.Begin); fs.Read(unpackedFileByteArr, 0, computedFileLength); Util.unpackHeaderTree(ref unpackedFileByteArr, computedFileLength, fileCrc32); for (int i = 0; i < (computedFileLength - fileLength); i++) { unpackedFileByteArr[fileLength + i] = 0; } } filePathName = Encoding.GetEncoding(0x3b5).GetString(filePath).TrimEnd(new char[1]);//CP949(韩语) return(filePathLength + 20); } catch { return(-1); } }
public Dictionary <string, string> nStringMap = new Dictionary <string, string>(); //n_string.lst文件的索引键值关系,键值均为字符串 /* * pvf共分三部分:Header头,Tree文件索引头,文件内容数据,本类中: * 使用struct PvfHeader{}来存储Header头,在本类中为header对象 * 使用Dictionary<string, HeaderTreeNode> headerTreeCache来存储Tree文件索引头,键为文件索引的文件名,值为索引对象 * 使用HeaderTreeNode的索引对象存储文件内容,详情请看本类构造方法。 */ public Pvf(string file) //本构造方法使用后需dispose释放内存,构造过程请放到线程中异步调用。 { fs = new FileStream(file, FileMode.Open); //打开文件 header = (PvfHeader)Util.readFileAsType(fs, typeof(PvfHeader)); //读取pvf文件头结构体到header变量 int headLength = header.dirTreeLength; //获取文件索引列表字节总大小 byte[] decryptedTree = new byte[header.dirTreeLength]; //分配内存 fs.Read(decryptedTree, 0, header.dirTreeLength); //读取文件索引列表 Util.unpackHeaderTree(ref decryptedTree, header.dirTreeLength, (uint)header.dirTreeChecksum); //解密,解密后的字节数组为decryptedTree int pos = 0; //模拟读取字节数组的指针 for (int i = 0; i < header.numFilesInDirTree; i++) { HeaderTreeNode item = new HeaderTreeNode(); int a = item.readNodeFromBitArrStream(header, fs, decryptedTree, pos);//从pos位置开始读取HeaderTreeNode对象,返回值为指针应该偏移的字节数 if (a < 0) { throw new Exception("读取错误,格式非法"); //读取错误直接报错 } pos += a; //指针后移 headerTreeCache[item.filePathName] = item; //把对象放入字典,以文件名为键 } loadStringTableBin(headerTreeCache["stringtable.bin"].unpackedFileByteArr); //读取stringtable.bin文件创建stringtable索引 loadNStringLst(headerTreeCache["n_string.lst"].unpackedFileByteArr); //读取n_string.lst文件创建n_string索引 return; }