繁体   English   中英

C#:FileStream.Read() 不读取文件直到最后,但返回 0

[英]C#: FileStream.Read() doesn't read the file up to the end, but returns 0

这是我如何做到的:

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

请帮忙! 我在这里真的一窍不通。 提前致谢!

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

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

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

最后,除非您确实需要调整某些选项,否则只需使用Encoding.UTF8而不是创建新实例。

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

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);
}

除此之外:乔恩说的:)

你为什么不让你的生活更轻松并这样做呢?

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

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

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

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

我知道这很旧,但请检查:

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);
        }
    }
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM