当前位置:  开发笔记 > 编程语言 > 正文

C#中的FileStream StreamReader问题

如何解决《C#中的FileStreamStreamReader问题》经验,为你挑选了3个好方法。

我正在测试类FileStream和StreamReader如何工作.通过控制台应用程序.我正在尝试进入文件并读取行并在控制台上打印它们.

我已经能够使用while循环来完成它,但我想尝试使用foreach循环.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace testing
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string file = @"C:\Temp\New Folder\New Text Document.txt";
            using(FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {
                using(StreamReader sr = new StreamReader(fs))
                {
                    foreach(string line in file)
                    {
                        Console.WriteLine(line);
                    }
                }
            }
        }
    }
}

我不断得到的错误是:无法将'char'类型转换为'string'

while循环确实有效,如下所示:

while((line = sr.ReadLine()) != null)
{
    Console.WriteLine(line);
}

我可能忽略了一些非常基本的东西,但我看不到它.



1> Marc Gravell..:

如果要通过foreach(以可重用的方式)逐行读取文件,请考虑以下迭代器块:

    public static IEnumerable ReadLines(string path)
    {
        using (StreamReader reader = File.OpenText(path))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                yield return line;
            }
        }
    }

请注意,这是懒惰的评估 - 没有与之关联的缓冲File.ReadAllLines().该foreach语法将确保迭代器Dispose()甚至例外正确Ð,关闭文件:

foreach(string line in ReadLines(file))
{
    Console.WriteLine(line);
}

(这个位只是为了兴趣...)

这种抽象的另一个优点是它可以很好地与LINQ一起使用 - 即使用这种方法很容易进行转换/过滤等:

        DateTime minDate = new DateTime(2000,1,1);
        var query = from line in ReadLines(file)
                    let tokens = line.Split('\t')
                    let person = new
                    {
                        Forname = tokens[0],
                        Surname = tokens[1],
                        DoB = DateTime.Parse(tokens[2])
                    }
                    where person.DoB >= minDate
                    select person;
        foreach (var person in query)
        {
            Console.WriteLine("{0}, {1}: born {2}",
                person.Surname, person.Forname, person.DoB);
        }

而且,所有人都懒洋洋地评估(没有缓冲).



2> Aleksandar..:

要读取New Text Document.txt中的所有行:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace testing
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string file = @"C:\Temp\New Folder\New Text Document.txt";
            using(FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
            {                    
                using(StreamReader sr = new StreamReader(fs))
                {
                    while(!sr.EndOfStream)
                    {
                       Console.WriteLine(sr.ReadLine());
                    }
                }
            }
        }
    }
}



3> Jon Skeet..:

LineReader我的MiscUtil项目中有一个类.它比这里给出的解决方案略胜一筹,主要是根据你构建它的方式:

从返回流的函数,在这种情况下,它将使用UTF-8

从返回流的函数和编码

从返回文本阅读器的函数

仅从文件名,在这种情况下,它将使用UTF-8

从文件名和编码

该类"拥有"它使用的任何资源,并适当地关闭它们.但是,它没有实现IDisposable自己就这样做了.这就是为什么它需要FuncFunc不是流或读取器直接 - 它需要能够推迟开放直到它需要它.它是迭代器本身(由foreach循环自动处理),它关闭资源.

正如Marc所指出的,这在LINQ中非常有效.我想给出的一个例子是:

var errors = from file in Directory.GetFiles(logDirectory, "*.log")
             from line in new LineReader(file)
             select new LogEntry(line) into entry
             where entry.Severity == Severity.Error
             select entry;

这将从一大堆日志文件中流出所有错误,随着时间的推移打开和关闭.结合Push LINQ,你可以做各种好东西:)

这不是一个特别"棘手"的课程,但它真的很方便.这里是完整的源代码,为方便起见,如果您不想下载MiscUtil.源代码的许可证在这里.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace MiscUtil.IO
{
    /// 
    /// Reads a data source line by line. The source can be a file, a stream,
    /// or a text reader. In any case, the source is only opened when the
    /// enumerator is fetched, and is closed when the iterator is disposed.
    /// 
    public sealed class LineReader : IEnumerable
    {
        /// 
        /// Means of creating a TextReader to read from.
        /// 
        readonly Func dataSource;

        /// 
        /// Creates a LineReader from a stream source. The delegate is only
        /// called when the enumerator is fetched. UTF-8 is used to decode
        /// the stream into text.
        /// 
        /// Data source
        public LineReader(Func streamSource)
            : this(streamSource, Encoding.UTF8)
        {
        }

        /// 
        /// Creates a LineReader from a stream source. The delegate is only
        /// called when the enumerator is fetched.
        /// 
        /// Data source
        /// Encoding to use to decode the stream
        /// into text
        public LineReader(Func streamSource, Encoding encoding)
            : this(() => new StreamReader(streamSource(), encoding))
        {
        }

        /// 
        /// Creates a LineReader from a filename. The file is only opened
        /// (or even checked for existence) when the enumerator is fetched.
        /// UTF8 is used to decode the file into text.
        /// 
        /// File to read from
        public LineReader(string filename)
            : this(filename, Encoding.UTF8)
        {
        }

        /// 
        /// Creates a LineReader from a filename. The file is only opened
        /// (or even checked for existence) when the enumerator is fetched.
        /// 
        /// File to read from
        /// Encoding to use to decode the file
        /// into text
        public LineReader(string filename, Encoding encoding)
            : this(() => new StreamReader(filename, encoding))
        {
        }

        /// 
        /// Creates a LineReader from a TextReader source. The delegate
        /// is only called when the enumerator is fetched
        /// 
        /// Data source
        public LineReader(Func dataSource)
        {
            this.dataSource = dataSource;
        }

        /// 
        /// Enumerates the data source line by line.
        /// 
        public IEnumerator GetEnumerator()
        {
            using (TextReader reader = dataSource())
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    yield return line;
                }
            }
        }

        /// 
        /// Enumerates the data source line by line.
        /// 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有