예제 #1
0
        internal static string readRecordFilename(Stream s, Arc_V3_Header header, ArcRecordHeader recordHeader)
        {
            BinaryReader reader = new BinaryReader(s);

            s.Seek(header.recordTableOffset + header.recordTableSize + recordHeader.stringEntryOffset, SeekOrigin.Begin);
            return(Encoding.ASCII.GetString(reader.ReadBytes(recordHeader.stringEntryLength)));
        }
예제 #2
0
        public static Dictionary <string, byte[]> read(string filepath)
        {
            using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                // Check on the file header
                Arc_V3_Header header = (Arc_V3_Header)Program.readStructure(typeof(Arc_V3_Header), fs, null);
                if (header.magic != 0x435241 || header.version != 0x3)
                {
                    throw new Exception("I don't understand this ARC format!");
                }

                // Read out the records table
                var recordsTable = readRecordHeadersTable(fs, header.recordTableOffset + header.recordTableSize + header.stringTableSize, header.numberOfFileEntries);

                // Read out the contents of each "record" and return them in a map associated with their filename
                var arcContents = new Dictionary <string, byte[]>();
                foreach (var recordHeader in recordsTable)
                {
                    string filename = readRecordFilename(fs, header, recordHeader);
                    byte[] contents = readRecord(fs, header, recordHeader);
                    arcContents[filename] = contents;
                }

                return(arcContents);
            }
        }
예제 #3
0
        internal static byte[] readRecord(Stream s, Arc_V3_Header header, ArcRecordHeader recordHeader)
        {
            BinaryReader reader = new BinaryReader(s);

            s.Seek(recordHeader.fileOffset, SeekOrigin.Begin);

            // If the file contents isn't compressed, just read and return the contents now
            if (recordHeader.entryType == 1 && recordHeader.compressedSize == recordHeader.decompressedSize)
            {
                return(reader.ReadBytes(recordHeader.decompressedSize));
            }

            // The file content is compressed...
            MemoryStream contentsStream = new MemoryStream();
            BinaryWriter contentWriter  = new BinaryWriter(contentsStream);

            for (int partCursor = 0; partCursor < recordHeader.fileParts; partCursor++)
            {
                // Goto the beginning of the file part
                // Magic number "12" is the size of the ArcFilePart on disk
                s.Seek(header.recordTableOffset + (recordHeader.firstPartIndex + partCursor) * 12, SeekOrigin.Begin);

                // Read out the file part header
                var partHeader = (ArcFilePartHeader)Program.readStructure(typeof(ArcFilePartHeader), s, null);

                // Read out the part content
                s.Seek(partHeader.offset, SeekOrigin.Begin);
                byte[] contentBytes = reader.ReadBytes(partHeader.compressedSize);

                // If the content isn't compressed, just write it out
                if (partHeader.compressedSize == partHeader.decompressedSize)
                {
                    contentWriter.Write(contentBytes);
                    continue;
                }

                // If the content *is* compressed, decompress before writing it out
                byte[] decompressedBytes = LZ4.LZ4Codec.Decode(contentBytes, 0, contentBytes.Length, partHeader.decompressedSize);
                contentWriter.Write(decompressedBytes);
            }
            return(contentsStream.GetBuffer());
        }