4

这是我的做法:

static void Main(string[] args)
{
    string FileName = "c:\\error.txt";
    long FilePosition = 137647;

    FileStream fr = new FileStream(FileName, FileMode.Open);
    byte[] b = new byte[1024];
    string data = string.Empty;
    fr.Seek(FilePosition, SeekOrigin.Begin);
    UTF8Encoding encoding = new UTF8Encoding();

    while (fr.Read(b, 0, b.Length) > 0)
    {
        data += encoding.GetString(b);
    }
    fr.Close();
    string[] str = data.Split(new string[] { "\r\n" }, StringSplitOptions.None);
    foreach (string s in str)
    {
        Console.WriteLine(s);
    }
    Console.ReadKey();
}

str 数组以这些行结束:

***** 手牌 T5-2847880-18 的历史(锦标赛:S-976-46079)*****
开始手牌:8 月 11 日星期二 18:14

但文件中有更多行。

我已将 error.txt 上传到 sendspace:http ://www.sendspace.com/file/5vgjtn 这是完整的控制台输出:the_same_site/file/k05x3a

请帮忙!我在这里真的一无所知。提前致谢!

4

5 回答 5

16

您的代码在以下方面存在一些细微的错误和问题:

  • 您假设整个缓冲区已通过调用填充GetString(b)
  • 您假设每个缓冲区都在一个字符的末尾结束。使用 a TextReader(eg StreamReader) 读取文本数据,避免此类问题。
  • 如果发生异常,您不会关闭文件(使用using指令)
  • 您在循环中使用字符串连接:preferStringBuilder

正如其他人指出的那样,File.ReadAllLines会避免很多这项工作。还有File.ReadAllText, 和TextReader.ReadToEnd用于非文件。

最后,Encoding.UTF8除非你真的需要调整一些选项,否则只需使用而不是创建一个新实例。

于 2009-08-11T16:52:49.407 回答
4

从技术上讲,这不是您问题的答案,但您可以将所有内容替换为:

string[] str = File.ReadAllLines("c:\\error.txt");

编辑(如承诺的那样):
在我看来,您将拥有最后一部分的副本,而不是遗漏一部分。您没有从文件中读取完整的 1024 个字节,而是将所有 1024 个字节转换为字符串并附加它。

你的循环应该是这样的:

int bytesRead;
while ((bytesRead = fr.Read(b, 0, b.Length)) > 0)
{
    data += encoding.GetString(b, 0, bytesRead);
}

除此之外:乔恩所说的:)

于 2009-08-11T16:50:56.493 回答
3

你为什么不让你的生活更轻松并做到这一点?

string[] str = System.IO.File.ReadAllLines("c:\\error.txt");
于 2009-08-11T16:51:53.120 回答
0

您可能会发现简单地使用 File.ReadLines() 要容易得多。跳过你不关心的行,而不是使用位置。

int counter = 0;
foreach (string s in File.ReadAllLines(FileName))
{
    ++counter;
    if (counter > 50?)
    {
        Console.WriteLine(s);
    }
}

您还可以使用 StreamReader,它允许您在设置其位置后包装流,然后使用 ReadLine() 方法。

于 2009-08-11T16:55:07.997 回答
0

我知道这是旧的,但检查一下:

public void StreamBuffer(Stream sourceStream, Stream destinationStream, int buffer = 4096)
{
    using (var memoryStream = new MemoryStream())
    {
        sourceStream.CopyTo(memoryStream);
        var memoryBuffer = memoryStream.GetBuffer();

        for (int i = 0; i < memoryBuffer.Length;)
        {
            var networkBuffer = new byte[buffer];
            for (int j = 0; j < networkBuffer.Length && i < memoryBuffer.Length; j++)
            {
                networkBuffer[j] = memoryBuffer[i];
                i++;
            }
            destinationStream.Write(networkBuffer, 0, networkBuffer.Length);
        }
    }
}

...并请记住,内存流很棒,并且可以保证从流中获取字节数组以用于其他方式。用它。

于 2019-10-29T01:09:01.133 回答