c# - 当行的字节位置已知时,从 C# 中的文件中删除一行文本

标签 c# buffer filestream

我有一个大文本文件 (>2gb)。我目前正在使用 Filestream 以 1kb 的 block 读取文件。在每个 block 中,我计算行数并使用此计数找到文件中必须删除该行的位置。

例如,如果我要删除的行的字节位置是 4097,在 C# 中有没有一种方法可以删除从 4097 开始直到我命中\n 字符的行中的字符。

我在看 Filestream.Seek() 方法直接转到删除位置。但是,我不确定如何进一步进行。

因为这是一个大文件,我不想创建另一个文件,因为它会占用大量系统空间和内存。有没有一种有效的方法可以让我在不创建新文件的情况下删除该行。

如有任何建议和帮助,我们将不胜感激。

提前致谢!

最佳答案

我觉得缩短文件的唯一方法就是复制其中的一部分,然后跳过,然后复制其余部分。如果您确实需要就地执行此操作,您可以选择某种形式的逻辑删除。例如,您可以仅使用 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");
    }

此外,在删除文件时,最好非常小心并仔细检查所有可能出错的地方。

编辑 第一个算法有点无意义,因为我还在阅读整个文件;现在有道理了。

关于c# - 当行的字节位置已知时,从 C# 中的文件中删除一行文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15191808/

相关文章:

c# - WPF 中的 Windows 小工具 - 在激活 "Show desktop"时显示

VIM:在光标移动时在每一行上执行 Ruby 脚本并更新缓冲区以在拆分窗口中显示

Silverlight 4.0 文件流

c# - 从 Wunderground 解析 JSON 预测数据

c# - 在 if 语句中检查多个字符串是否为 null

c# - 为什么我收到错误 No overload for ... matches delegate?

javascript - 为什么长度为 3 的字符串的字节长度为 3?

c - 只读来自 FILE 对象的缓冲日期

.net - 异步文件IO线程安全吗?

c - 如果链接到它们的 fd 用于其他目的,FILE * 是否继续工作?