从文件中删除一行

时间:2011-08-19 06:06:46

标签: java

请帮忙解决这个问题。 我想在读取该行后删除文件中的每一行。我们可以这样删除吗? 我不想使用任何临时文件来执行此过程。

请帮帮我,谢谢。

2 个答案:

答案 0 :(得分:4)

如果没有临时文件,则无法执行此操作,除非它是最后一行。您可以覆盖文本行(虽然这并不像您想象的那么容易,除非行是一个固定的大小) - 如果有某种方法可以指示任何读取文件的行应该是忽略了,这是一个选择。但是,您无法通过从中间删除数据来减小文件大小。它绝不是大多数文件系统支持的操作。

同样,您无法在文件中间插入额外信息。基本上可用的操作是覆盖,追加和截断。

答案 1 :(得分:0)

你绝对可以做到。认为这将是System.Text.Encoding ninjitsu的挑战和良好考验。你走了:

static bool DeleteEveryLineAfter(Stream data, string search, Encoding encoding)
{
    const int WindowsPageSize = 4096;

    var decoder = encoding.GetDecoder();
    var encoder = encoding.GetEncoder();

    var buffer = new byte[WindowsPageSize];
    var length = 0;
    var searchPosition = 0;

    var newLine = Environment.NewLine.ToCharArray();
    var newLinePosition = 0;
    var currentLinePosition = 0;
    var lineIsValid = true;

    while ((length = data.Read(buffer, 0, WindowsPageSize)) != 0)
    {
        // Get the characters.
        var chars = new char[decoder.GetCharCount(buffer, 0, length, false)];
        decoder.GetChars(buffer, 0, length, chars, 0, false);

        for (var i = 0; i < chars.Length; i++)
        {
            var c = chars[i];

            if (
                // Only if the line isn't LONGER than what we are searching for.
                searchPosition < search.Length &&
                // And if the current character matches.
                search[searchPosition] == c &&
                // And we have matched something in it, or it is the start of the line.
                (searchPosition > 0 || currentLinePosition == 0) &&
                // And if a previous character didn't fail.
                lineIsValid
                )
            {
                searchPosition++;
                newLinePosition = 0;
            }
            else if (newLinePosition < newLine.Length && c == newLine[newLinePosition])
            {
                newLinePosition++;
                // Did we match the whole newline.
                if (newLinePosition == newLine.Length)
                {
                    // Was the current line a match?
                    if (lineIsValid && searchPosition == search.Length)
                    {
                        // Figure out the different between the amount of data
                        // we read, and how long the line was.
                        var bytesLeft = encoder.GetByteCount(chars, i, chars.Length - i, true);
                        var finalLength = data.Position - bytesLeft;
                        data.SetLength(finalLength);
                        return true;
                    }
                    else
                    {
                        lineIsValid = true;
                        newLinePosition = 0;
                        searchPosition = 0;
                        currentLinePosition = -1; // Compensate for ++ below.
                    }
                }
            }
            else
            {
                lineIsValid = false;
            }

            currentLinePosition++;
        }
    }

    return false;
}