kedoumy的专栏

每天进步一点点...

如何把多个文件写入到一个文件中去并能分解
对于一个文件的读写,其实很简单,就是用FileStream进行Read或者Write就行了。但是如何把多个文件写入到同一个文件,之后要能把这个文件进行还原成多个文件。那么光靠FileStream的Read和Write方法是不够的,首先你需要自行建立文件索引,来标明每个文件在当前文件的位置。
 
那么最近作了一个简单的DEMO,其中类的部分代码如下:
//------------------------------- Compose Files ----------------------------------
//--------------------------------------------------------------------------------
//---File:clsComposeFiles.cs
//---Description:This file is to show how-to compose multi-files into one file
//               and decompose one file to multi-files.
//---Author:Knight
//---Date:May.16, 2006
//--------------------------------------------------------------------------------
//------------------------------{ Compose Files }---------------------------------
 
namespace ComposeFiles
{
    using System;
    using System.IO;
    using System.Collections;
    using System.Text;
 
    ///<summary>
    /// Summary description for clsComposeFiles.
    ///</summary>
    public class clsComposeFiles
    {
        private ArrayList arrFiles = new ArrayList();
 
        public clsComposeFiles()
        {
            //
            // TODO: Add constructor logic here
            //
        }
 
        ///<summary>
        /// Add a file to be composed
        ///</summary>
        ///<param name="sFileName"></param>
        public void AddFile( string sFileName )
        {
            arrFiles.Add( sFileName );
        }
 
        ///<summary>
        /// Compose files to the specific file
        ///</summary>
        ///<param name="sFileName"></param>
        ///<returns></returns>
        public bool ComposeFiles( string sFileName )
        {
            if( arrFiles.Count == 0 ) return false;
           
            FileInfo fi = new FileInfo( sFileName );
            // Open file to write
            FileStream fsWriter = null;
            try
            {
                if( !fi.Exists )
                {
                    fsWriter = new FileStream(
                        sFileName,
                        FileMode.CreateNew,
                        FileAccess.ReadWrite,
                        FileShare.None );
                }
                else
                    fsWriter = new FileStream(
                        sFileName,
                        FileMode.Truncate,
                        FileAccess.ReadWrite,
                        FileShare.None );
            }
            catch(Exception err)
            {
                System.Diagnostics.Debug.WriteLine( err.Message );
                return false;
            }
           
            byte[] bBuffer = null;
            // Write files count
            bBuffer = FileIndex.LongToBytes( arrFiles.Count );
            fsWriter.Write( bBuffer, 0, 8 );
 
            const long INDEX_START_POS = 8L;
            // Init files index
            FileIndex FI = new FileIndex();
            for( int i = 0; i < arrFiles.Count; i++ )
                fsWriter.Write( FileIndex.ConvertToBytes( ref FI ), 0, 32 );
 
            long FILE_START_POS = INDEX_START_POS + 32 * arrFiles.Count;
            long lCurFileStartPos = FILE_START_POS;
 
            // Write every file
            for( int i = 0; i < arrFiles.Count; i++ )
            {
                WriteFile( arrFiles[i].ToString(),
                    ref lCurFileStartPos,
                    INDEX_START_POS,
                    fsWriter,
                    i );
            }
 
            // Close stream
            fsWriter.Close();
            return true;
        }
 
        ///<summary>
        /// Write file name and data into composed file
        ///</summary>
        ///<param name="sFileName"></param>
        ///<param name="FileStartPos"></param>
        ///<param name="IndexStartPos"></param>
        ///<param name="fsWriter"></param>
        ///<param name="Index"></param>
        private void WriteFile(
            string sFileName,
            ref long FileStartPos,
            long IndexStartPos,
            FileStream fsWriter,
            int Index )
        {
            FileInfo fi = new FileInfo( sFileName );
            if( !fi.Exists ) return;
 
            FileStream fsReader = null;
            try
            {
                fsReader = new FileStream(
                    sFileName, FileMode.Open,
                    FileAccess.Read );
            }
            catch{ return;}
 
            // Get file name
            byte[] bFileName = Encoding.Unicode.GetBytes( fi.Name );
            // Write file name
            fsWriter.Write( bFileName, 0, bFileName.Length );
 
            const int BUFFER_LENGTH = 1024;
            byte[] bBuffer = new byte[BUFFER_LENGTH];
            int nRealRead = 0;
            // Write data using
            do
            {
                // Read data from file
                nRealRead = fsReader.Read( bBuffer, 0,
                    BUFFER_LENGTH );
                // Write data
                fsWriter.Write( bBuffer, 0, nRealRead );
            }while( nRealRead > 0 );
            // Close file reader
            fsReader.Close();
 
            FileIndex FINew = new FileIndex();
            FINew.NameStartPos = FileStartPos;
            FINew.NameLength = bFileName.Length;
            FINew.FileStartPos = FileStartPos + bFileName.Length;
            FINew.FileLength = fi.Length;
 
            // Go back to file index position
            fsWriter.Seek( IndexStartPos + Index * 32, SeekOrigin.Begin );
 
            // Write file index info
            fsWriter.Write( FileIndex.ConvertToBytes( ref FINew ), 0, 32 );
 
            // Go back to file end
            fsWriter.Seek( 0, SeekOrigin.End );
 
            // Set file current position
            FileStartPos += bFileName.Length + fi.Length;
        }
 
        ///<summary>
        /// Decompose file to multi files into specific directory
        ///</summary>
        ///<param name="sFileName"></param>
        ///<param name="sDestDir"></param>
        ///<returns></returns>
        public bool DecomposeFile( string sFileName, string sDestDir )
        {
            FileInfo fi = new FileInfo( sFileName );
            if( !fi.Exists ) return false;
 
            FileStream fsReader = null;
            try
            {
                fsReader = new FileStream(
                    sFileName, FileMode.Open,
                    FileAccess.Read );
            }
            catch{ return false;}
           
            // Read file count
            byte[] bFileCount = new byte[8];
            int nRealRead = 0;
            nRealRead = fsReader.Read( bFileCount, 0, 8 );
            if( nRealRead != 8 )
            {
                fsReader.Close();
                return false;
            }
 
            long lFileCount = FileIndex.BytesToLong( bFileCount );
            if( lFileCount > 0 )
            {
                //Init file index array
                FileIndex[] fiArray = new FileIndex[lFileCount];
                byte[] bFileIndex = new byte[32];
                for( int i = 0; i < lFileCount; i++ )
                {
                    fsReader.Read( bFileIndex, 0, 32 );
                    fiArray[i] = FileIndex.ConvertToFileIndex( bFileIndex );
                }
 
                if( sDestDir[ sDestDir.Length - 1] != '//' )
                    sDestDir += "//";
                // Save every file into current directory
                for( int i = 0; i < fiArray.Length; i++ )
                {
                    SaveFile( fsReader,
                        ref fiArray[i],
                        sDestDir );
                }
            }
 
            // Close file reader
            fsReader.Close();
            return true;
        }
 
        ///<summary>
        /// Save every file into directory
        ///</summary>
        ///<param name="fsReader"></param>
        ///<param name="FI"></param>
        ///<param name="sDestDir"></param>
        private void SaveFile(
            FileStream fsReader,
            ref FileIndex FI,
            string sDestDir )
        {
            // Read file name
            byte[] bFileName = new byte[ FI.NameLength ];
            int nRealRead = fsReader.Read( bFileName, 0, bFileName.Length );
            if( nRealRead != bFileName.Length ) return;
            string sFileName = Encoding.Unicode.GetString( bFileName );
            sFileName = sDestDir + sFileName;
            FileInfo fi = new FileInfo( sFileName );
            // Open file to write
            FileStream fsWriter = null;
            try
            {
                if( !fi.Exists )
                {
                    fsWriter = new FileStream(
                        sFileName,
                        FileMode.CreateNew,
                        FileAccess.ReadWrite,
                        FileShare.None );
                }
                else
                    fsWriter = new FileStream(
                        sFileName,
                        FileMode.Truncate,
                        FileAccess.ReadWrite,
                        FileShare.None );
            }
            catch(Exception err){
                System.Diagnostics.Debug.WriteLine( err.Message );
                return;
            }
       
            // Init buffer 
            const int BUFFER_LENGTH = 1024;
            byte[] bBuffer = new byte[BUFFER_LENGTH];
            long lLeft = FI.FileLength;
 
            // Copy file
            do
            {
                if( lLeft > BUFFER_LENGTH )
                {
                    fsReader.Read( bBuffer, 0, BUFFER_LENGTH );
                    fsWriter.Write( bBuffer, 0, BUFFER_LENGTH );
 
                    lLeft -= BUFFER_LENGTH;
                }
                else
                {
                    nRealRead = fsReader.Read( bBuffer, 0, (int)lLeft );
                    fsWriter.Write( bBuffer, 0, nRealRead );
 
                    lLeft -= nRealRead;
                }
            }
            while( lLeft > 0 );
 
            // close file writer
            fsWriter.Close();
        }
    }
 
    ///<summary>
    /// File index data structure
    ///</summary>
    public struct FileIndex
    {
        public long NameStartPos;
        public long NameLength;
        public long FileStartPos;
        public long FileLength;
 
        public static byte[] ConvertToBytes( ref FileIndex FI )
        {
            byte[] bData = new byte[32];
 
            Array.Copy( LongToBytes( FI.NameStartPos ), 0, bData, 0, 8 );
            Array.Copy( LongToBytes( FI.NameLength ), 0, bData, 8, 8 );
            Array.Copy( LongToBytes( FI.FileStartPos ), 0, bData, 16, 8 );
            Array.Copy( LongToBytes( FI.FileLength ), 0, bData, 24, 8 );
 
            return bData;
        }
 
        public static byte[] LongToBytes( long lValue )
        {
            byte[] bData = new byte[8];
   
            bData[0] = (byte)( ( lValue >> 56 ) & 0xFF);
            bData[1] = (byte)( ( lValue >> 48 ) & 0xFF);
            bData[2] = (byte)( ( lValue >> 40 ) & 0xFF);
            bData[3] = (byte)( ( lValue >> 32 ) & 0xFF);
            bData[4] = (byte)( ( lValue >> 24 ) & 0xFF);
            bData[5] = (byte)( ( lValue >> 16 ) & 0xFF);
            bData[6] = (byte)( ( lValue >> 8 ) & 0xFF);
            bData[7] = (byte)(lValue & 0xFF);
            return bData;
        }
 
        public static FileIndex ConvertToFileIndex( byte[] bData )
        {
            if( bData == null || bData.Length != 32 )
                throw new Exception( "Invalid parameters!" );
 
            FileIndex FI = new FileIndex();
            byte[] bBuffer = new byte[8];
            Array.Copy( bData, 0, bBuffer, 0, 8 );
            FI.NameStartPos = BytesToLong( bBuffer );
            Array.Copy( bData, 8, bBuffer, 0, 8 );
            FI.NameLength = BytesToLong( bBuffer );
            Array.Copy( bData, 16, bBuffer, 0, 8 );
            FI.FileStartPos = BytesToLong( bBuffer );
            Array.Copy( bData, 24, bBuffer, 0, 8 );
            FI.FileLength = BytesToLong( bBuffer );
            return FI;
        }
 
        public static long BytesToLong( byte[] bData )
        {
            if( bData == null || bData.Length != 8 )
                throw new Exception( "Invalid parameters!" );
 
            long lngValue = 0;
            lngValue += bData[0];
            lngValue = ( lngValue << 8 );
            lngValue += bData[1];
            lngValue = ( lngValue << 8 );
            lngValue += bData[2];
            lngValue = ( lngValue << 8 );
            lngValue += bData[3];
            lngValue = ( lngValue << 8 );
            lngValue += bData[4];
            lngValue = ( lngValue << 8 );
            lngValue += bData[5];
            lngValue = ( lngValue << 8 );
            lngValue += bData[6];
            lngValue = ( lngValue << 8 );
            lngValue += bData[7];
            return lngValue;
        }
    }
}
 
其中类的操作参看clsComposeFiles这个类,而文件索引结构参看FileIndex这个Structure。
 
之后的调用就很简单,例如:
合成文件:
    clsComposeFiles myComposeFiles = new clsComposeFiles();
    myComposeFiles.AddFile( @"D:/Ship.exe" );
    myComposeFiles.AddFile( @"D:/LoginPage.JPG" );
myComposeFiles.ComposeFiles( @"D:/Ship.dat" );
 
分解文件:
    clsComposeFiles myComposeFiles = new clsComposeFiles();
    myComposeFiles.DecomposeFile( @"D:/Ship.dat", @"E:/" );
 
以上代码由于写得比较急,细节处理并不是很完善,因此使用的时候要加以细化,甚至可以在我的基础上进行扩充。
 
阅读更多
个人分类: 文件管理
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

如何把多个文件写入到一个文件中去并能分解

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭