Yesky首页| 产品报价| 行情| 手机 | 数码 | 笔记本 | 台式机 | DIY硬件 | 外设 | 网络 | 数字家庭 | 评测 | 软件 | e时代 | 游戏 | 图片 | 壁纸 | 群乐 | 社区 | 博客 | 下载
软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|产品中心下载向SOA转型
您现在的位置: 天极网 > 开发频道 > 将多个文件写入一个文件中去并能分解
全文
群乐:.NET

将多个文件写入一个文件中去并能分解

2007-10-07 22:23 作者: 佚名 出处: 天极网软件频道 责任编辑:五月

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

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

网友关注
最新上市
编辑推荐
欢迎订阅天极网RSS聚合资讯:http://www.yesky.com/index.xml