我觉得缩短文件的唯一方法是真正复制其中一些,然后跳过,然后复制其余部分。如果您真的需要就地执行,您可以选择某种形式的逻辑删除。例如,您可以仅使用 LF 对文本文件中的新行进行编码(这不是Windows 上的默认设置,而是使用一对 CR-LF),这很可能需要 8 位 ASCII 并选择类似这样的内容:
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();
}
注意toDel是要删除的第一个字符的索引,而不是要删除的行的索引。这段代码只是用相同数量的空行替换了toDel 处和行尾之间的所有字符。然后你需要另一个函数将文件复制到另一个文件,但跳过所有空行。您可以在将来任何方便的时间进行此清理。不过,您的实际算法需要能够处理文件中的大量空白行。此外,您应该分块读取文件是对的,但是在这种情况下也可以应用此示例中显示的基本思想。
编辑
您可以使用此功能擦除逻辑删除的行:
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");
}
此外,在删除文件时,最好非常小心并仔细检查可能出错的所有内容。
编辑
第一个算法有点没有意义,因为我还在阅读整个文件;现在它是有道理的。