views:

3133

answers:

7

I have a huge file, where I have to insert certain characters at a specific location. What is the easiest way to do that in C# without rewriting the whole file again.

+2  A: 

You will probably need to rewrite the file from the point you insert the changes to the end. You might be best always writing to the end of the file and use tools such as sort and grep to get the data out in the desired order. I am assuming you are talking about a text file here, not a binary file.

Mike Thompson
i was actually looking for some random access techniques using C#, even if I have to use unsafe code. Thanks for the suggestions anyway.
Gulzar
+1  A: 

You can use random access to write to specific locations of a file, but you won't be able to do it in text format, you'll have to work with bytes directly.

FlySwat
Can you pls point to some resources on the web? I was thinking it was not possible for random access file handling in C#.
Gulzar
I don't think that he wants to overwrite the old bytes.
Cristian Ciupitu
A: 

Depending on the scope of your project, you may want to decide to insert each line of text with your file in a table datastructure. Sort of like a database table, that way you can insert to a specific location at any given moment, and not have to read-in, modify, and output the entire text file each time. This is given the fact that your data is "huge" as you put it. You would still recreate the file, but at least you create a scalable solution in this manner.

Sev
+7  A: 

Filesystems do not support "inserting" data in the middle of a file. If you really have a need for a file that can be written to in a sorted kind of way, I suggest you look into using an embedded database.

You might want to take a look at SQLite or BerkeleyDB.

Then again, you might be working with a text file or a legacy binary file. In that case your only option is to rewrite the file, at least from the insertion point up to the end.

I would look at the FileStream class to do random I/O in C#.

bineteri
That is not exactly correct. You can use random access to arbitrarily read and write a file (in bytes) from any point. However, its up to you to shift the file offsets when inserting something.In other words, its simpler to just regenerate the file.
FlySwat
I disagree. Of course, you can seek to any point in a file using random access. But if you write at that point, you'll overwrite what was previously at that location. So, if you had "abced" in your file, you seek to the 'c' and write "123", you end up with "ab123", not "ab123cde".
bineteri
A: 

It may be "possible" depending on how the filesystem stores files to quickly insert (ie, add additional) bytes in the middle. If it is remotely possible it may only be feasible to do so a full block at a time, and only by either doing low level modification of the filesystem itself or by using a filesystem specific interface.

Filesystems are not generally designed for this operation. If you need to quickly do inserts you really need a more general database.

Depending on your application a middle ground would be to bunch your inserts together, so you only do one rewrite of the file rather than twenty.

Captain Segfault
+2  A: 

There is no way to insert characters in to a file without rewriting them. With C# it can be done with any Stream classes. If the files are huge, I would recommend you to use GNU Core Utils inside C# code. They are the fastest. I used to handle very large text files with the core utils ( of sizes 4GB, 8GB or more etc ). Commands like head, tail, split, csplit, cat, shuf, shred, uniq really help a lot in text manipulation.

For example if you need to put some chars in a 2GB file, you can use split -b BYTECOUNT, put the ouptut in to a file, append the new text to it, and get the rest of the content and add to it. This should supposedly be faster than any other way.

Hope it works. Give it a try.

A: 

If you know the specific location to which you want to write the new data, use the BinaryWriter class:

using (BinaryWriter bw = new BinaryWriter (File.Open (strFile, FileMode.Open)))
{
    string strNewData = "this is some new data";
    byte[] byteNewData = new byte[strNewData.Length];

    // copy contents of string to byte array
    for (var i = 0; i < strNewData.Length; i++)
    {
     byteNewData[i] = Convert.ToByte (strNewData[i]);
    }

    // write new data to file
    bw.Seek (15, SeekOrigin.Begin);  // seek to position 15
    bw.Write (byteNewData, 0, byteNewData.Length);
}
scottmarlowe
Mind that this code will OVERWRITE(!) the data at position 15.
data_smith