我有一个超过3000行的文本文件。我找到了使用
的行数string[] lines = File.ReadAllLines(myPath);
var lineCount = lines.Length;
然后我生成一个随机数
Random rand = new Random();
var lineToRead = rand.Next(1, lineCount);
现在我需要读取由随机数生成的特定行。我可以使用
来做到这一点string requiredLine = lines[lineToRead];
因为我的文件很大,我不认为创建如此大的数组是有效的。有更有效或更简单的方法吗?
答案 0 :(得分:9)
这是一个迭代文件两次的解决方案(第一次计算行,下次选择行)。好处是您不需要在内存中创建3000个字符串的数组。但是,如上所述,可能会慢一些。为什么可能? - 因为File.ReadAllLines
在其中创建了一个字符串列表,并且该列表将在填充3000个项目时多次调整大小。 (初始容量为4
。当内部数组完全填充时,将创建新的双倍大小数组,并在那里复制所有字符串。
因此,该解决方案使用File.ReadLines
方法返回IEnumerable<string>
行和跳过您不需要的行:
IEnumerable<string> lines = File.ReadLines(myPath);
var lineToRead = rand.Next(1, lines.Count());
var line = lines.Skip(lineToRead - 1).First();
BTW,内部File.ReadLines
使用SteamReader
逐行读取文件。
答案 1 :(得分:1)
您可以做的是解析文件以查找每行的索引,然后稍后您可以使用Stream.Position返回到某一行以获取内容。使用此方法,您无需在内存中保留任何内容,而且速度相当快。 我在一个20K行和1MB大小的文件上测试了这个。索引文件需要7毫秒,获得该行需要0.3。
// Parse the file
var indexes = new List<long>();
using (var fs = File.OpenRead("text.txt"))
{
indexes.Add(fs.Position);
int chr;
while ((chr = fs.ReadByte()) != -1)
{
if (chr == '\n')
{
indexes.Add(fs.Position);
}
}
}
int lineCount = indexes.Count;
int randLineNum = new Random().Next(0, lineCount - 1);
string lineContent = "";
// Read the random line
using (var fs = File.OpenRead("text.txt"))
{
fs.Position = indexes[randLineNum];
using (var sr = new StreamReader(fs))
{
lineContent = sr.ReadLine();
}
}
答案 2 :(得分:0)
您可以将流包装到StreamReader中并根据需要多次调用ReadLine以转到目标行。这样您就不需要将整个文件内容保存在内存中。
但是,这只有在你很少这样做并且文件非常大的情况下才可行。
答案 3 :(得分:0)
使用水库采样一次性解决此问题
如果您想从事先不知道该列表长度的项目列表中随机选择一个或多个项目,您可以使用Reservoir Sampling。
我们可以利用这一点,以及File.ReadLines()
方法(避免缓冲内存中的所有行)来编写单遍算法,该算法只读取每一行,而不进行缓冲。
下面的示例代码显示了一个通用解决方案,可让您随机选择任意数量的行。对于您的情况,N = 1。
示例代码还包括一个测试程序,用于证明线条是随机选择的,具有均匀分布。
(要了解此代码的工作原理,请参阅我上面链接的Wiki文章。)
using System;
using System.IO;
using System.Collections.Generic;
namespace Demo
{
internal class Program
{
public static List<string> RandomlyChooseLinesFromFile(string filename, int n, Random rng)
{
var result = new List<string>(n);
int index = 0;
foreach (var line in File.ReadLines(filename))
{
if (index < n)
{
result.Add(line);
}
else
{
int r = rng.Next(0, index + 1);
if (r < n)
result[r] = line;
}
++index;
}
return result;
}
// Test RandomlyChooseLinesFromFile()
private static void Main(string[] args)
{
Directory.CreateDirectory("C:\\TEST");
string testfile = "C:\\TEST\\TESTFILE.TXT";
File.WriteAllText(testfile, "0\n1\n2\n3\n4\n5\n6\n7\n8\n9");
var rng = new Random();
int trials = 100000;
var counts = new int[10];
for (int i = 0; i < trials; ++i)
{
string line = RandomlyChooseLinesFromFile(testfile, 1, rng)[0];
int index = int.Parse(line);
++counts[index];
}
// If this algorithm is correct, each line should be chosen
// approximately 10% of the times.
Console.WriteLine("% times each line was chosen:\n");
for (int i = 0; i < 10; ++i)
{
Console.WriteLine("{0} = {1}%", i, 100*counts[i]/(double)trials);
}
}
}
}
答案 4 :(得分:-1)
下面将帮助您阅读文件中的特定行..
代码snipet
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace ReadLine
{
class Program
{
static void Main(string[] args)
{
//Load our text file
TextReader tr = new StreamReader("\\test.txt");
//How many lines should be loaded?
int NumberOfLines = 15;
//Make our array for each line
string[] ListLines = new string[NumberOfLines];
//Read the number of lines and put them in the array
for (int i = 1; i < NumberOfLines; i++)
{
ListLines[i] = tr.ReadLine();
}
//This will write the 5th line into the console
Console.WriteLine(ListLines[5]);
//This will write the 1st line into the console
Console.WriteLine(ListLines[1]);
Console.ReadLine();
// close the stream
tr.Close();
}
}
}
这些也很有用..
http://www.tek-tips.com/viewthread.cfm?qid=1460456
How do I read a specified line in a text file?
以下是编辑
Edit a specific Line of a Text File in C#
希望它有所帮助...
答案 5 :(得分:-1)
你可以尝试如下......它不能创建任何大阵列但是得到一条特定的线......
string path = "D:\\Software.txt";
int lines = File.ReadAllLines(path).Length;
Random rand = new Random();
var lineToRead = rand.Next(1, lines);
var requiredLine = System.IO.File.ReadLines(path).Skip(lineToRead - 1).First();
Console.WriteLine(requiredLine.ToString());