Inserting a files content in the middle of another file.

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!
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Pierre CorneliusCommented:
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);


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
A1ternityAuthor Commented:
Yeah I figured as much... was just hoping there would be a simpler way.

Still... Thanks for the help and here's your pts!
Wim ten BrinkSelf-employed developerCommented:
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.
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

Wim ten BrinkSelf-employed developerCommented:
One advantage of my solution: It requires a lot less diskspace if you're manipulating huge files... ;-)
A1ternityAuthor Commented:
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? ;)
Wim ten BrinkSelf-employed developerCommented:
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.
A1ternityAuthor Commented:

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!
Wim ten BrinkSelf-employed developerCommented:
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.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.