Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.7k views
in Technique[技术] by (71.8m points)

c# - How to extract files from single file back to disk correctly?

Hi developers! I need u help. 2 days left now i'll try extract files back to disk use this code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Packer
{
    public class SimplePack
    {
        public class Header
        {
            public Int32 TotalEntries { get; set; }
            public Int64[] EntriesSize
            {
                get
                {
                    return EntriesSizeList.ToArray();
                }
            }
            private List<Int64> EntriesSizeList { get; set; }

            public Header()
            {
                TotalEntries = 0;
                EntriesSizeList = new List<Int64>();
            }

            public void AddEntrySize(Int64 newSize)
            {
                EntriesSizeList.Add(newSize);
            }
        }

        public class Item
        {
            public Byte[] RawData { get; set; }
            public String Name { get; set; }
            public String RelativeUri { get; set; }

            public Int64 ItemSize
            {
                get
                {
                    Int64 retVal = 4; //Name.Lenght;
                    retVal += Name.Length;
                    retVal += 4; //RelativeUri.Length
                    retVal += RelativeUri.Length;
                    retVal += RawData.Length;

                    return retVal;
                }
            }

            public Byte[] SerializedData
            {
                get
                {
                    List<Byte> retVal = new List<Byte>();
                    retVal.AddRange(BitConverter.GetBytes(Name.Length));
                    retVal.AddRange(Encoding.Default.GetBytes(Name));
                    retVal.AddRange(BitConverter.GetBytes(RelativeUri.Length));
                    retVal.AddRange(Encoding.Default.GetBytes(RelativeUri));
                    retVal.AddRange(RawData);
                    return retVal.ToArray();
                }
            }

            public Item()
            {
                RawData = new Byte[0];
                Name = String.Empty;
                RelativeUri = String.Empty;
            }
            public Item(Byte[] serializedItem)
            {
                Int32 cursor = 0;
                Int32 nl = BitConverter.ToInt32(serializedItem, cursor);
                cursor += 4;
                Name = Encoding.Default.GetString(serializedItem, cursor, nl);
                cursor += nl;
                Int32 rl = BitConverter.ToInt32(serializedItem, cursor);
                cursor += 4;
                RelativeUri = Encoding.Default.GetString(serializedItem, cursor, rl);
                cursor += rl;
                RawData = new Byte[serializedItem.Length - cursor];
                for (int i = cursor; i < serializedItem.Length; i++)
                {
                    RawData[i - cursor] = serializedItem[cursor];
                }
            }
        }

        public FileInfo PackedFile { get; private set; }
        public List<Item> Data { get; private set; }

        public Header FileHeaderDefinition { get; private set; }

        public SimplePack(String fileName)
        {
            PackedFile = new FileInfo(fileName);
            FileHeaderDefinition = new Header();
            Data = new List<Item>();
        }

        public Boolean PackFolderContent(String folderFullName)
        {
            Boolean retVal = false;

            DirectoryInfo di = new DirectoryInfo(folderFullName);

            //Think about setting up strong checks and errors trapping

            if (di.Exists)
            {
                FileInfo[] files = di.GetFiles("*", SearchOption.AllDirectories);
                foreach (FileInfo fi in files)
                {
                    Item it = setItem(fi, di.FullName);
                    if (it != null)
                    {
                        Data.Add(it);
                        FileHeaderDefinition.TotalEntries++;
                        FileHeaderDefinition.AddEntrySize(it.ItemSize);
                    }
                }
            }
            //althoug it isn't checked
            retVal = true;

            return retVal;
        }

        private Item setItem(FileInfo sourceFile, String packedRoot)
        {
            if (sourceFile.Exists)
            {
                Item retVal = new Item();
                retVal.Name = sourceFile.Name;
                retVal.RelativeUri = sourceFile.FullName.Substring(packedRoot.Length).Replace("\", "/");
                retVal.RawData = File.ReadAllBytes(sourceFile.FullName);
                return retVal;
            }
            else
            {
                return null;
            }
        }

        public void Save()
        {
            if (PackedFile.Exists)
            {
                PackedFile.Delete();
                System.Threading.Thread.Sleep(100);
            }
            using (FileStream fs = new FileStream(PackedFile.FullName, FileMode.CreateNew, FileAccess.Write))
            {
                //Writing Header
                //4 bytes
                fs.Write(BitConverter.GetBytes(FileHeaderDefinition.TotalEntries), 0, 4);
                //8 bytes foreach size
                foreach (Int64 size in FileHeaderDefinition.EntriesSize)
                {
                    fs.Write(BitConverter.GetBytes(size), 0, 8);
                }
                foreach (Item it in Data)
                {
                    fs.Write(it.SerializedData, 0, it.SerializedData.Length);
                }

                fs.Close();
            }
        }

        public void Open() //here so good, open i see files
        {
            if (PackedFile.Exists)
            {
                using (FileStream fs = new FileStream(PackedFile.FullName, FileMode.Open, FileAccess.Read))
                {
                    Byte[] readBuffer = new Byte[4];
                    fs.Read(readBuffer, 0, readBuffer.Length);
                    FileHeaderDefinition.TotalEntries = BitConverter.ToInt32(readBuffer, 0);
                    for (Int32 i = 0; i < FileHeaderDefinition.TotalEntries; i++)
                    {
                        readBuffer = new Byte[8];
                        fs.Read(readBuffer, 0, readBuffer.Length);
                        FileHeaderDefinition.AddEntrySize(BitConverter.ToInt64(readBuffer, 0));
                    }

                    foreach (Int64 size in FileHeaderDefinition.EntriesSize)
                    {
                        readBuffer = new Byte[size];
                        fs.Read(readBuffer, 0, readBuffer.Length);
                        Data.Add(new Item(readBuffer));
                    }

                    fs.Close();
                }
                
            

But here.... I don't know, how to correctly extract files back to disk, because files extract, but corrupt.

foreach (Item its in Data) 
                {
                using (FileStream fs1 = new FileStream(Environment.CurrentDirectory + @"Unpack" + its.Name, FileMode.Create, FileAccess.Write))
                {

                    fs1.Write(its.RawData, 0, (int)its.ItemSize);
                    //fs1.Write(its.RawData, 0, (int)its.ItemSize);                      
                }
            }
        }
   }
}

Problem in foreach, where's i'll try extract files use foreach, files is extracted back, but corrupted, why? How to correctly extract files? Where's i'm wrong?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...