我正在尝试阅读一些文本文件,其中每行都需要处理.目前我只使用StreamReader,然后单独读取每一行.
我想知道是否有更有效的方法(在LoC和可读性方面)使用LINQ来做到这一点而不影响运营效率.我看到的例子涉及将整个文件加载到内存中,然后处理它.在这种情况下,我不相信这会非常有效.在第一个示例中,文件可以达到大约50k,而在第二个示例中,不需要读取文件的所有行(大小通常小于10k).
您可能会争辩说,现在这对于这些小文件并不重要,但我相信这种方法会导致代码效率低下.
第一个例子:
// Open file
using(var file = System.IO.File.OpenText(_LstFilename))
{
// Read file
while (!file.EndOfStream)
{
String line = file.ReadLine();
// Ignore empty lines
if (line.Length > 0)
{
// Create addon
T addon = new T();
addon.Load(line, _BaseDir);
// Add to collection
collection.Add(addon);
}
}
}
Run Code Online (Sandbox Code Playgroud)
第二个例子:
// Open file
using (var file = System.IO.File.OpenText(datFile))
{
// Compile regexs
Regex nameRegex = new Regex("IDENTIFY (.*)");
while (!file.EndOfStream)
{
String line = file.ReadLine();
// Check name
Match m = nameRegex.Match(line);
if (m.Success)
{
_Name = m.Groups[1].Value;
// Remove me when other values are read
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Mar*_*ell 94
您可以使用迭代器块非常轻松地编写基于LINQ的读取器:
static IEnumerable<SomeType> ReadFrom(string file) {
string line;
using(var reader = File.OpenText(file)) {
while((line = reader.ReadLine()) != null) {
SomeType newRecord = /* parse line */
yield return newRecord;
}
}
}
Run Code Online (Sandbox Code Playgroud)
或让乔恩高兴:
static IEnumerable<string> ReadFrom(string file) {
string line;
using(var reader = File.OpenText(file)) {
while((line = reader.ReadLine()) != null) {
yield return line;
}
}
}
...
var typedSequence = from line in ReadFrom(path)
let record = ParseLine(line)
where record.Active // for example
select record.Key;
Run Code Online (Sandbox Code Playgroud)
然后你有ReadFrom(...)一个懒惰的评估序列没有缓冲,完美的Where等等.
请注意,如果您使用OrderBy或标准GroupBy,它将必须缓冲内存中的数据; 如果你需要分组和聚合,"PushLINQ"有一些花哨的代码,允许你对数据进行聚合但丢弃它(没有缓冲).乔恩的解释就在这里.
Jon*_*eet 23
读取一行并检查它是否为null比检查EndOfStream更简单.
不过,我也有一LineReader类MiscUtil,这使得这一切变得简单许多-基本上它暴露了一个文件(或Func<TextReader>作为IEnumerable<string>它可以让你做LINQ的东西了,所以你可以喜欢做的事情.
var query = from file in Directory.GetFiles("*.log")
from line in new LineReader(file)
where line.Length > 0
select new AddOn(line); // or whatever
Run Code Online (Sandbox Code Playgroud)
LineReader这个实施的核心是IEnumerable<string>.GetEnumerator:
public IEnumerator<string> GetEnumerator()
{
using (TextReader reader = dataSource())
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Run Code Online (Sandbox Code Playgroud)
几乎所有其他来源只是提供灵活的设置方式dataSource(这是一个Func<TextReader>).
| 归档时间: |
|
| 查看次数: |
64995 次 |
| 最近记录: |