将多个文件写入一个文件中去并能分解
上一篇 / 下一篇 2007-10-08 16:43:00 / 个人分类:开发技术
对于一个文件的读写,其实很简单,就是用FileStream进行Read或者Write就行了。但是如何把多个文件写入到同一个文件,之后要能把这个文件进行还原成多个文件。那么光靠FileStream的Read和Write方法是不够的,首先你需要自行建立文件索引,来标明每个文件在当前文件的位置。
其中类的操作参看clsComposeFiles这个类,而文件索引结构参看FileIndex这个Structure。
那么最近作了一个简单的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.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 = 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, 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 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:\" ); |
以上代码由于写得比较急,细节处理并不是很完善,因此使用的时候要加以细化,甚至可以在我的基础上进行扩充。
标题搜索
日历
|
|||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
| 1 | 2 | 3 | 4 | ||||||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 | |||
| 12 | 13 | 14 | 15 | 16 | 17 | 18 | |||
| 19 | 20 | 21 | 22 | 23 | 24 | 25 | |||
| 26 | 27 | 28 | 29 | 30 | 31 | ||||
我的存档
数据统计
- 访问量: 2755
- 日志数: 63
- 建立时间: 2007-08-02
- 更新时间: 2008-07-11
