Inserting a files content in the middle of another file.

Posted on 2004-11-17
Last Modified: 2011-10-03
Hi everyone,

I need to insert the content of an existing file at a position in the middle of another file. What would be the best way to do this??

Thanks in advance!
Question by:A1ternity
    LVL 14

    Accepted Solution

    Just use filestreams, very simple.

    I first rename the destination file to *.tmp and then write all the byte from the temp file up to the position specified to a new file. I then write the src file contents and then the rest of the temp file. see below.

    procedure InsertFileAt(srcFilename, DestFilename: string; pos: integer);
    var src, dest, NewFile: TFileStream;
      RenameFile(DestFilename, ChangeFileExt(DestFilename, '.tmp'));
      src:= TFileStream.Create(srcFilename, fmOpenRead);
      dest:= TFileStream.Create(ChangeFileExt(DestFilename, '.tmp'), fmOpenRead);
      NewFile:= TFileStream.Create(DestFilename, fmCreate);

        NewFile.CopyFrom(dest, pos-1);
        NewFile.CopyFrom(src, src.Size);
        Dest.Seek(pos, soBeginning);
        NewFile.CopyFrom(Dest, Dest.Size-pos);


    Author Comment

    Yeah I figured as much... was just hoping there would be a simpler way.

    Still... Thanks for the help and here's your pts!
    LVL 17

    Expert Comment

    by:Wim ten Brink
    Too bad you accepted an answer this fast... There's a nicer solution if the files you're manipulating aren't too big. The code below lacks a few checks but that's just to make the principle of the technique a lot clearer...

    procedure InsertIntoFile( const Filename: string; const Data: string; Position: Integer );
      AFile: file;
      Buffer: array[ 0..4095 ] of char;
      EndOfFile: Int64;
      BufPos: Int64;
      DataLen: Int64;
      Size: Int64;
      AssignFile( AFile, Filename );
      Reset( AFile, 1 );
      EndOfFile := FileSize( AFile );
      Size := EndOfFile - Position;
      BufPos := EndOfFile - SizeOf( Buffer );
      DataLen := Length( Data );
      while ( Size > SizeOf( Buffer ) ) do begin
        Seek( AFile, BufPos );
        BlockRead( AFile, Buffer, SizeOf( Buffer ) );
        Seek( AFile, BufPos + DataLen );
        BlockWrite( AFile, Buffer, SizeOf( Buffer ) );
        BufPos := BufPos - SizeOf( Buffer );
        Size := Size - SizeOf( Buffer );
      if ( Size > 0 ) then begin
        Seek( AFile, Position );
        BlockRead( AFile, Buffer, Size );
        Seek( AFile, Position + DataLen );
        BlockWrite( AFile, Buffer, Size );
      Seek( AFile, Position );
      BlockWrite( AFile, PChar( Data )^, Length( Data ) );
      CloseFile( AFile );

    This method doesn't use any temporary file but uses some internal memory to store the data. Basically, I first move blocks of 4 KB within the file to some other position. Thus, because I use small blocks, I can even manipulate large files. Once I run out of blocks of 4 KB I move the remaining block after the position to it's new position. Once that is in place too, I seek the position where the data needs to be inserted and insert it there.
    One risk, though. Any exception in this routine will damage the original file...

    This solution is not simpler but you might consider it cleaner since you don't need temporary files.

    FYI, I used a string for the data that needs to be inserted. Of course, this could be anything that you want to insert, but you must have an easy way to determine the size of this data.
    Considering performance, I don't think it will be really faster than the accepted solution. It's just a different technique.
    LVL 17

    Expert Comment

    by:Wim ten Brink
    One advantage of my solution: It requires a lot less diskspace if you're manipulating huge files... ;-)

    Author Comment

    Yes your solution seems more "optimized" WorkshopAlex. But the files I manipulate a pretty small and the first solution suits my needs fine (this is a case where simplicity and delay of implementation mattered a lot).

    Still I will keep your bit of code as a future reference... SO I'll open up a post to get you some points... Am I a good sport or not? ;)
    LVL 17

    Expert Comment

    by:Wim ten Brink
    Thanks, but since that post would exceed the maximum of 500 points that can be given to any question, I rephrased that other post a bit so hopefully the EE team will consider it as just another good question. :-)
    Anyway, I didn't really answer it to earn points. It was actually a challenge for me to see if it could be done without a temporary file. Btw, my solution can be used for small files too. My testfile added 5 characters to a textfile of 33 KB. It won't be any slower than the streamed version. It just has to move less blocks of data... But I wanted to be sure it could also support huge files without eating up too much memory. If you make that buffer array slightly larger than the average filesize that you'll be dealing with, then it just loops a little less... It just eats more memory.
    As I said, it was just an example of the technique, not a really well-tested method.

    Author Comment


    After looking at your code I have no doubt that it is more efficient... Sadly I had time contraints to deploy the solution (don't we always?)  so I used a "simpler" solution that is somewhat similar to the first answer to this post.

    If I have a bit more time later (do we ever??) I might go back to the code and optimize it inspiring myself from your code.

    So basically I wanted a quick answer and once I got the answer with the temp file (which was what I had come up with already) I decided to move forward with it...

    But still, thanks a lot!
    LVL 17

    Expert Comment

    by:Wim ten Brink
    Awww. Don't worry. I know the answer provided looked like a good one and basically it is a good solution already. It's less risky too since the tmp file that is created could be used as backup in case something goes wrong. (Power failure, for example while you've written half of the file.) Both solutions have their advantages and disadvantages. Since you needed a solution fast, I'm not suprised you accepted it that fast. My solution isn't really better since an error could damage your file beyond repair. But if you make sure all errors are handled correctly, then there's no problem with it. And I'm not inserting another file in it, just some text. However, you could instead insert the contents of a file in it, if you like. It's just that you would have to write a bit more code to open the other file and use the buffer again to move the data. This could be done using a fixed buffer block size or you just allocate memory for the whole file, read it as a single block and write it again as a single block.

    I knew what I was doing AFTER you closed the question again. Didn't expect to receive points for it either. :-)

    It's just that I wanted to show a nice, alternative method for doing this, since you're probably not the first person asking for this.

    Featured Post

    Free Trending Threat Insights Every Day

    Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

    Join & Write a Comment

    Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
    Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
    Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
    Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

    732 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    19 Experts available now in Live!

    Get 1:1 Help Now