Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Inserting a files content in the middle of another file.

Posted on 2004-11-17
8
Medium Priority
?
298 Views
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!
0
Comment
Question by:A1ternity
  • 4
  • 3
8 Comments
 
LVL 14

Accepted Solution

by:
Pierre Cornelius earned 2000 total points
ID: 12607569
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;
begin
  RenameFile(DestFilename, ChangeFileExt(DestFilename, '.tmp'));
  src:= TFileStream.Create(srcFilename, fmOpenRead);
  dest:= TFileStream.Create(ChangeFileExt(DestFilename, '.tmp'), fmOpenRead);
  NewFile:= TFileStream.Create(DestFilename, fmCreate);

  try
    NewFile.CopyFrom(dest, pos-1);
    NewFile.CopyFrom(src, src.Size);
    Dest.Seek(pos, soBeginning);
    NewFile.CopyFrom(Dest, Dest.Size-pos);
  finally
    src.free;
    dest.free;
    NewFile.Free;
  end;
end;

Regards
Pierre
0
 

Author Comment

by:A1ternity
ID: 12607605
Yeah I figured as much... was just hoping there would be a simpler way.

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

Expert Comment

by:Wim ten Brink
ID: 12613475
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 );
var
  AFile: file;
  Buffer: array[ 0..4095 ] of char;
  EndOfFile: Int64;
  BufPos: Int64;
  DataLen: Int64;
  Size: Int64;
begin
  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 );
  end;
  if ( Size > 0 ) then begin
    Seek( AFile, Position );
    BlockRead( AFile, Buffer, Size );
    Seek( AFile, Position + DataLen );
    BlockWrite( AFile, Buffer, Size );
  end;
  Seek( AFile, Position );
  BlockWrite( AFile, PChar( Data )^, Length( Data ) );
  CloseFile( AFile );
end;

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.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 17

Expert Comment

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

Author Comment

by:A1ternity
ID: 12614089
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? ;)
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12614726
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.
0
 

Author Comment

by:A1ternity
ID: 12614760
*nods*

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!
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 12615248
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.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
This is an update to some code that someone else posted on Experts Exchange. It is an alternate approach, I think a little easier to use, & makes sure that things like the Task Bar will update.
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
The Relationships Diagram is a good way to get an overall view of what a database is keeping track of. It is also where relationships are defined. A relationship specifies how two tables connect to each other. As you build tables in Microsoft Ac…
Suggested Courses

581 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