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

转载 2007年10月10日 14:13:00
对于一个文件的读写,其实很简单,就是用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:/" );
 
以上代码由于写得比较急,细节处理并不是很完善,因此使用的时候要加以细化,甚至可以在我的基础上进行扩充。
 

多个进程对同一文件写入的问题

转载。 讨论关于并发环境下,多个进程对同一文件写入的问题,我们会涉及到文件共享的知识。在开始之前,我们先讨论一些有关文件共享的知识。 1. 文件共享   Unix系统支持在不同进程间共享打开...
  • lk07828
  • lk07828
  • 2016年10月14日 10:00
  • 1746

多进程同时写一个文件会怎样?

一、问题还原在多进程的环境下,父子进程同时去写一个文件,例如父进程每次写入aaaaa,子进程每次写入bbbbb,问题是会不会出现写操作被打断的现象,比如出现aabbbaaabb这样交替的情况?二、结论...
  • yangbodong22011
  • yangbodong22011
  • 2017年03月18日 01:46
  • 2398

将多个文本文件合并成一个文件的3种方法

第一种: WinRAR的另类应用:将多个文本文件合成一个文件                大家在日常Windows系统操作应用中,肯定会经常用到将多个文本文件合并成一个文件,想必大多数都是利用复...
  • u012543266
  • u012543266
  • 2013年12月22日 19:58
  • 6280

JAVA多线程之两个线程同时写一个文件

1.多线程    线程是程序执行流的最小单元。是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所...
  • qq_32971807
  • qq_32971807
  • 2016年08月04日 09:20
  • 4542

linux中echo命令向一个文件写入内容

转自:http://blog.chinaunix.net/uid-28458801-id-3460227.html 覆盖型写法 (文件里原来的内容被覆盖) echo "aaa" > a.txt ...
  • huanggang982
  • huanggang982
  • 2014年12月09日 17:16
  • 3986

export与source 一个shell脚本文件的关系

source命令用法: source FileName 作用:在当前bash环境下读取并执行FileName中的命令。 注:该命令通常用命令“.”来替代。 如:source .bash_rc ...
  • u013176681
  • u013176681
  • 2016年01月15日 09:25
  • 568

Java 如何对文件进行多个Object对象流的读写操作

思路:把已经序列化的对象存入容器(如LinkedList)中,然后用ObjectInputStream和ObjectOutputStream对这个实例化的LinkedList对象进行读写。 ...
  • u010355144
  • u010355144
  • 2015年08月24日 15:11
  • 2758

XML基础知识——写入数据到XML文件(二)

一、写入数据到XML文件中 往XML文件中写入数据,特别要注意编码问题,这里写入数据采用了两种不同的编码。一般情况下如果xml文件时gb2312,就采用第一种方式,如果为UTF-8,就使用第二种方式写...
  • spring_model
  • spring_model
  • 2017年01月12日 15:27
  • 537

Google多线程面试题: 4个线程向4个文件里写入数据, 每个线程只能写一个值

By Long Luo 个人博客链接 最近在学习Java多线程时,遇到了一个下面的笔试题,题目如下: 编写一个程序,程序会启动4个线程,向4个文件A,B,C,D里写入数据,每个线程只能写...
  • love__linux
  • love__linux
  • 2015年04月21日 18:29
  • 3173

java读取excel文件并写入另一个excel文件

package com.excel.action; import java.io.BufferedInputStream; import java.io.File; import java....
  • kristenlee1218
  • kristenlee1218
  • 2016年02月22日 10:28
  • 369
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何把多个文件写入到一个文件中去并能分解
举报原因:
原因补充:

(最多只允许输入30个字)