I feel like the only way to shorten a file is really copy some of it, then skip, then copy the rest. If you really need to do it in place, you could opt for some form of logical deletion. For instance you could use only LF to encode new lines in your text file (which is not the default on Windows, which uses instead a pair CR-LF), which most likely would need to be 8 bit ASCII and opt for something like this:
public static void LogicalEraseLine(string filename, int toDel)
{
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite);
fs.Seek(toDel, SeekOrigin.Current);
int c;
while ((c = fs.ReadByte()) != -1)
{
if (c == '\n')
{
break;
}
else
{
fs.Seek(-1, SeekOrigin.Current);
fs.WriteByte((byte)'\n');
}
}
fs.Close();
}
Note that toDel is the index of the first character to delete, not the index of the line to delete. This code simply replaces all characters between the one at toDel and the end of the line with an equal number of empty lines. Then you would need another function to copy the file to another file, but skipping all empty lines. You could do this cleanup at any convenient time in the future. Your actual algorithm would need to be able to cope with lots of blank lines in the file though. Also, you are right that you should read the file in chunks, but the basic idea shown in this example could be applied also in that case.
Edit
You could use this function to erase logically deleted lines:
public static void Cleanup (string filename)
{
FileStream input = new FileStream(filename, FileMode.Open, FileAccess.Read);
FileStream output = new FileStream(filename + ".tmp", FileMode.Create, FileAccess.Write);
bool emptyLine = true;
int c;
while ((c = input.ReadByte()) != -1)
{
if (c == '\n')
{
if (!emptyLine)
{
output.WriteByte((byte)c);
emptyLine = true;
}
}
else
{
output.WriteByte((byte)c);
emptyLine = false;
}
}
input.Close();
output.Close();
File.Delete (filename);
File.Copy(filename + ".tmp", filename);
File.Delete(filename + ".tmp");
}
Also, when deleting files it's a good idea to be very careful and double check everything that may go wrong.
Edit
The first algorithm was kinda meaningless because I was still reading the entire file; now it makes sense.