从文件中提取前10行到字符串中

13
public void get10FirstLines()
{ 
     StreamReader sr = new StreamReader(path);
     String lines = "";
     lines = sr.readLine();
}

我该如何从字符串中获取文件的前10行?


2
你的问题不是非常清楚 - 你的方法调用了 skip10Lines,这与将前10行获取到一个字符串中不同。同时也不清楚你是否真的想要将这些行作为单个字符串或列表。 - Jon Skeet
如果这是你的真实代码:path 应该作为一个参数传递。 - H H
8个回答

36

不要直接使用 StreamReader,而是使用返回 IEnumerable<string>File.ReadLines。然后可以使用LINQ:

var first10Lines = File.ReadLines(path).Take(10).ToList();

使用 File.ReadLines 而不是 File.ReadAllLines 能够让你仅读取感兴趣的行,而不是读取整个文件。但是它只在 .NET 4+ 中可用。如果你想在 .NET 3.5 中使用它,可以使用迭代器块轻松实现。

调用 ToList() 的目的是为了强制查询被求值(即实际读取数据),以便它被读取了恰好一次。如果没有 ToList 调用,如果你尝试多次迭代 first10Lines,它将多次读取文件(如果它能正常工作的话;我记得 File.ReadLines 在这方面的实现并不十分干净)。

如果你想把前10行作为一个单独的字符串(例如使用"\r\n"分隔它们),那么可以使用string.Join

var first10Lines = string.Join("\r\n", File.ReadLines(path).Take(10));

显然,您可以通过更改调用中的第一个参数来更改分隔符。


1
非常好的解决方案,我建议将其放在一个抽象层后面以便进行测试。 - Gent

6
var lines = File.ReadAllLines(path).Take(10);

如果用户读取一个大小为2 GB(9999行)的文件,并且只想要前10行,那么它是否只会访问前10行? - huseyin tugrul buyukisik
@huseyintugrulbuyukisik:不,它会读取所有内容 - 这就是我的答案。 - Jon Skeet
2
File.ReadLines() 在这里可能是一个非常大的优化。 - H H
感谢你们的回答。问题在于,我需要它是一个字符串。因为我之后需要用 g.drawline() 进行画线。它不能是一个迭代器。它需要直接进入一个字符串。String myString = ""; - user2891133

5
您可以尝试使用File.ReadLines。请尝试以下代码:
var lines = File.ReadLines(path).Take(10);

如果您想将前10行作为单个字符串,请尝试以下方法:string.Join()

var myStr= string.Join("", File.ReadLines(path).Take(10));

应该使用 string.Empty 代替 "" - Gistiv

3
StringBuilder myString = new StringBuilder();

TextReader sr = new StreamReader(path);

for (int i=0; i < 10; i++)
{
myString.Append(sr.ReadLine())
}

2
String[] lines = new String[10];
for (int i = 0; i < 10; i++)
     lines[i] = sr.readLine();

这个循环会执行十次,并将结果放入一个新数组中。


0

原因是嵌套的操作符File.ReadLines(path).Take(10).ToList();将真正执行以下操作:

string[] lines = File.ReadLines(path); // reads all lines of the file
string[] selectedlines = lines.Take(10); // takes first 10 line s into a new array
List<String> LinesList = selectedlines.ToList();

特别是第一部分,它将整个文件读入行的可枚举对象中,这会消耗性能和内存。提问者明确要求处理大文件。

因此,我更愿意推荐:

/// <summary>
/// This function loads and returns the first x lines from a file
/// </summary>
/// <param name="path">The path to the file to read</param>
/// <param name="amountOfLines">the number of lines which should be read</param>
/// <param name="encoding">optional value, which specifies the format in which the text file is saved</param>
/// <returns></returns>
public List<string> GetFirstXLines(string path, int amountOfLines, Encoding encoding = null)
{
    // if no encoding is set, try the default encoding (File Format)
    if (encoding == null) encoding = Encoding.Default;
    // create list which will be filled with the lines and returned later
    List<string> lines = new List<string>();
    // wrap streamreader around so it gets closed+disposed properly later
    using (StreamReader reader = new StreamReader(path, encoding))
    {
        // loop x times to get the first x lines
        for (int i = 0; i < amountOfLines; i++)
        {
            // read the next line
            string line = reader.ReadLine();
            // if the line is null, we are at the end of file, break out of the loop
            if (line == null) break;
            // if the line was not null, add it to the lines list
            lines.Add(line);
        }
    }
    // return the lines
    return lines;  
}

0
public void skip10Lines()
{ 
    StringBuilder lines=new StringBuilder();
    using(StreamReader sr = new StreamReader(path))
    {
     String line = "";
     int count=0;

      while((line= sr.ReadLine())!=null)
      {
         if(count==10)
           break;
         lines.Append(line+Environment.NewLine);
         count++;
      }
     }

 string myFileData=lines.ToString();
 }

或者

public void skip10Lines()
{ 
     int count=0;
     List<String> lines=new List<String>();
     foreach(var line in File.ReadLines(path))
     {
         if(count==10)
           break;
         lines.Add(line);
         count++;
     }
 }

1
这段代码无法编译(应该是ReadLine而不是readLine),并且在结尾没有关闭读取器。 - Jon Skeet

-1
在基于JVM的语言Groovy中,一种方法是:
def buf = new StringBuilder()

Iterator iter = new File(path).withReader{
    for( int cnt = 0;cnt < 9;cnt++){    
        buf << it.readLine()
    }
}

println buf

由于闭包中没有'break',所以循环嵌套在闭包内部,因此资源处理由Groovy运行时处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接