我正在测试类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);
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不断得到的错误是:无法将'char'类型转换为'string'
while循环确实有效,如下所示:
while((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
Run Code Online (Sandbox Code Playgroud)
我可能忽略了一些非常基本的东西,但我看不到它.
Mar*_*ell 36
如果要通过foreach(以可重用的方式)逐行读取文件,请考虑以下迭代器块:
public static IEnumerable<string> ReadLines(string path)
{
using (StreamReader reader = File.OpenText(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这是懒惰的评估 - 没有与之关联的缓冲File.ReadAllLines().该foreach语法将确保迭代器Dispose()甚至例外正确Ð,关闭文件:
foreach(string line in ReadLines(file))
{
Console.WriteLine(line);
}
Run Code Online (Sandbox Code Playgroud)
(这个位只是为了兴趣...)
这种抽象的另一个优点是它可以很好地与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);
}
Run Code Online (Sandbox Code Playgroud)
而且,所有人都懒洋洋地评估(没有缓冲).
Ale*_*dar 24
要读取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());
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 23
LineReader我的MiscUtil项目中有一个类.它比这里给出的解决方案略胜一筹,主要是根据你构建它的方式:
该类"拥有"它使用的任何资源,并适当地关闭它们.但是,它没有实现IDisposable自己就这样做了.这就是为什么它需要Func<Stream>而Func<TextReader>不是流或读取器直接 - 它需要能够推迟开放直到它需要它.它是迭代器本身(由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;
Run Code Online (Sandbox Code Playgroud)
这将从一大堆日志文件中流出所有错误,随着时间的推移打开和关闭.结合Push LINQ,你可以做各种好东西:)
这不是一个特别"棘手"的课程,但它真的很方便.这里是完整的源代码,为方便起见,如果您不想下载MiscUtil.源代码的许可证在这里.
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace MiscUtil.IO
{
/// <summary>
/// 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.
/// </summary>
public sealed class LineReader : IEnumerable<string>
{
/// <summary>
/// Means of creating a TextReader to read from.
/// </summary>
readonly Func<TextReader> dataSource;
/// <summary>
/// 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.
/// </summary>
/// <param name="streamSource">Data source</param>
public LineReader(Func<Stream> streamSource)
: this(streamSource, Encoding.UTF8)
{
}
/// <summary>
/// Creates a LineReader from a stream source. The delegate is only
/// called when the enumerator is fetched.
/// </summary>
/// <param name="streamSource">Data source</param>
/// <param name="encoding">Encoding to use to decode the stream
/// into text</param>
public LineReader(Func<Stream> streamSource, Encoding encoding)
: this(() => new StreamReader(streamSource(), encoding))
{
}
/// <summary>
/// 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.
/// </summary>
/// <param name="filename">File to read from</param>
public LineReader(string filename)
: this(filename, Encoding.UTF8)
{
}
/// <summary>
/// Creates a LineReader from a filename. The file is only opened
/// (or even checked for existence) when the enumerator is fetched.
/// </summary>
/// <param name="filename">File to read from</param>
/// <param name="encoding">Encoding to use to decode the file
/// into text</param>
public LineReader(string filename, Encoding encoding)
: this(() => new StreamReader(filename, encoding))
{
}
/// <summary>
/// Creates a LineReader from a TextReader source. The delegate
/// is only called when the enumerator is fetched
/// </summary>
/// <param name="dataSource">Data source</param>
public LineReader(Func<TextReader> dataSource)
{
this.dataSource = dataSource;
}
/// <summary>
/// Enumerates the data source line by line.
/// </summary>
public IEnumerator<string> GetEnumerator()
{
using (TextReader reader = dataSource())
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
/// <summary>
/// Enumerates the data source line by line.
/// </summary>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
66171 次 |
| 最近记录: |