如何在两种方法中使用StreamReader相同的流?

时间:2014-07-08 18:05:04

标签: c#

我试图用两种不同的方法读取.json文件,如下所示:

void mainMethod() 
{
    Stream theFile = Assembly.GetExecutingAssembly().GetManifestResourcesStream("pathToFile");

    Method1(theFile);

    Method2(theFile);

}

void Method1(Stream file)
{
   using (StreamReader fileUsage_1 = new StreamReader(file))
   {
      //do stuff with file
   }
}

void Method2(Stream file)
{
   using (StreamReader fileUsage_2 = new StreamReader(file))
   {
      //do stuff with file
   }
}

运行mainMethod()会在Stream was not readable.中出现例外:Method2()我认为问题是Method2()正在尝试阅读theFileMethod1()中使用。我以为using块会自动关闭文件?如何在theFileMethod1()中自定义我正在阅读Method2()的方式,以便它们不会“重叠”?

4 个答案:

答案 0 :(得分:2)

打开StreamReader一次,并在每个方法中设置位置。这样,调用方法的顺序不固定。当您第一次打开StreamReader时,默认情况下将位置设置为开头,因此第一次调用Seek(0,SeekOrigin.Begin)是多余的,但允许将来调用的顺序可以互换。

    void mainMethod() 
    {
        Stream theFile = Assembly.GetExecutingAssembly().GetManifestResourcesStream("pathToFile");
        using (StreamReader fileUsage = new StreamReader(theFile))
        {
            Method1(fileUsage);
            Method2(fileUsage);
        }
    }

    private static void Method1(StreamReader fileUsage)
    {
        if (fileUsage != null && fileUsage.BaseStream.CanSeek && fileUsage.BaseStream.CanRead)
        {
            fileUsage.BaseStream.Seek(0, SeekOrigin.Begin);
            fileUsage.DiscardBufferedData();
            Console.WriteLine(fileUsage.ReadLine());
        }
    }

答案 1 :(得分:1)

叫我疯了......但你不能简单地从方法中抽象出使用声明并进入主程序吗?像这样。编辑包括重置位置,如果您选择这样做。 (可以转到Here以获取有关丢弃缓冲区数据的更多信息)

namespace ConsoleApplication12
{
    class Program
    {
        static void Main(string[] args)
        {

            Stream theFile = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApplication12.test.txt");
            using (StreamReader fileUsage_1 = new StreamReader(theFile))
            {
                Method1(fileUsage_1);
                ResetPosition(theFile, fileUsage_1); // If needed
                Method2(fileUsage_1);
            }

            Console.ReadLine();
        }

        private static void Method2(StreamReader fileUsage)
        {
            var test = fileUsage.ReadLine();
        }

        private static void Method1(StreamReader fileUsage)
        {
            var test = fileUsage.ReadLine();
        }

        private static void ResetPosition(Stream s, StreamReader sr)
        {
            s.Position = 0;
            sr.DiscardBufferedData();
        }
    }
}

答案 2 :(得分:0)

如果符合以下条件,则可以重新读取整个流:

  1. stream是可搜索的(stream.CanSeek == true
  2. 读者不要关闭流
  3. 您通常无法控制1,但如果需要,您可以将整个srteam复制到可搜索的位置(即使用Stream.CopyMemoryStream)。

    要阻止读者关闭流 - 请使用不取得流所有权的构造函数,因为reslut在使用后不会关闭流。即StreamReader(...,bool leaveOpen)

    最后,你需要寻找一个流来定位其他读者需要开始(通常是开始)的地方,例如Stream.Position = 0;

    注释

    • 如果您只是需要继续使用Method2从您不需要Method1离开的地方阅读流,请确保读者不要关闭。
    • 另外,您可以明确地不关闭读者(删除using / .Close来电),但这样的代码看起来不对,当一个人通过添加using“修复”它时,它将不再工作正常。

答案 3 :(得分:0)

如前所述设置Stream.Position。 这样设置:

file.Seek(System.IO.SeekOrigin.Begin);

StreamReader上的Using块在退出时关闭底层流。您可以使用File.ReadAllText方法通过该单个调用打开,读取和关闭(处置)文件:

string jsonString = File.ReadAllText(filePath);