首页 | IT新闻 | 硬件 | 操作系统 | 开发 | 网络编程 | 数据库 | 热门框架 | 网络安全 | 组网 | 建站指南 | 网页制作 | 特效 | 实用技巧 | 服务器 | 办公 | QQ | 探索 | 社区

  • 技术部落
  • 部落首页 > 程序开发 > C/C#/C++ > 正文
  • 将多个文件写入到一个文件中去并能分解
      2007-10-15  来源:CSDN  编辑:Jsbulo  热度:

      对于一个文件的读写,其实很简单,就是用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:\" );

      以上代码由于写得比较急,细节处理并不是很完善,因此使用的时候要加以细化,甚至可以在我的基础上进行扩充。