C# 在特定行读取文本文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15786612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 17:57:26  来源:igfitidea点击:

Read text file at specific line

c#

提问by asdfkjasdfjk

I have a text file which has more than 3000 lines. I am finding the number of lines using

我有一个超过 3000 行的文本文件。我正在使用

string[] lines = File.ReadAllLines(myPath);
var lineCount = lines.Length; 

Then I am generating a random number

然后我生成一个随机数

Random rand = new Random();
var lineToRead = rand.Next(1, lineCount);

Now I need to read the specific line that is generated by random number. I can do this using

现在我需要读取由随机数生成的特定行。我可以使用

string requiredLine = lines[lineToRead];

Because my file is big I don't think creating such a big array is efficient. Is there a more efficient or easier way to do this?

因为我的文件很大,所以我认为创建这么大的数组效率不高。有没有更有效或更简单的方法来做到这一点?

采纳答案by Sergey Berezovskiy

Here is a solution which iterates the file twice (first time to count lines, next time to select line). The benefit is that you don't need to create an array of 3000 strings in memory. But, as mentioned above, it will possiblybe slower. Why possibly? - because File.ReadAllLinescreates a list of strings inside and that list will be resized many times while filling it with 3000 items. (Initial capacity will be 4. When the inner array is completely filled, then the new array of doubled size will be created and all strings will be copied there).

这是一个迭代文件两次的解决方案(第一次计算行,下次选择行)。好处是您不需要在内存中创建 3000 个字符串的数组。但是,如上所述,它可能会更慢。为什么可能?- 因为在其中File.ReadAllLines创建了一个字符串列表,该列表将在填充 3000 个项目时多次调整大小。(初始容量为4。当内部数组完全填满时,将创建双倍大小的新数组,并将所有字符串复制到那里)。

So, the solution uses File.ReadLinesmethod which returns IEnumerable<string>with lines and skip lines you don't need:

因此,该解决方案使用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, internally File.ReadLinesuses SteamReaderwhich reads file line by line.

顺便说一句,内部File.ReadLines使用SteamReader它逐行读取文件。

回答by alex

You can wrap your stream into StreamReader and call ReadLine as many times as needed to go to your target line. That way you don't need to hold the whole file contents in memory.

您可以将流包装到 StreamReader 中,并根据需要多次调用 ReadLine 以转到目标行。这样您就不需要将整个文件内容保存在内存中。

However, this is only feasible if you do that rarely and file is quite big.

但是,这仅在您很少这样做并且文件非常大时才可行。

回答by Hiren Pandya

Below will help you in reading at specific line in a file..

下面将帮助您阅读文件中的特定行。

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/4dbd68f6-61f5-4d36-bfa0-5c909101874b

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/4dbd68f6-61f5-4d36-bfa0-5c909101874b

A code 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();
    }
}
}

These can also be helpful..

这些也有帮助..

http://www.tek-tips.com/viewthread.cfm?qid=1460456

http://www.tek-tips.com/viewthread.cfm?qid=1460456

How do I read a specified line in a text file?

如何读取文本文件中的指定行?

And below is for editing

下面是编辑

Edit a specific Line of a Text File in C#

在 C# 中编辑文本文件的特定行

Hope it helps...

希望能帮助到你...

回答by Pandian

you can try like below... it can not create any big array but get a particular line...

你可以像下面那样尝试......它不能创建任何大数组但得到一个特定的行......

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());

回答by Matthew Watson

Use Reservtheitroad Samplingto solve this in in a single pass

使用Reservtheitroad Sampling一次性解决这个问题

If you want to randomly choose one or more items from a list of items where the length of that list is not known in advance, you can use Reservtheitroad Sampling.

如果您想从事先不知道该列表长度的项目列表中随机选择一个或多个项目,您可以使用Reservtheitroad Sampling

We can take advantage of that, along with the File.ReadLines()method (which avoids buffering all the lines in memory) to write a single-pass algorithm that will read each line just once, without buffering.

我们可以利用这一点以及File.ReadLines()方法(避免缓冲内存中的所有行)来编写单遍算法,该算法将只读取每行一次,而无需缓冲。

The sample code below shows a generalised solution that lets you randomly select any number of lines. For your case, N = 1.

下面的示例代码显示了一个通用的解决方案,可以让您随机选择任意数量的行。对于您的情况,N = 1。

The sample code also includes a test program to prove that the lines are chosen randomly with a uniform distribution.

示例代码还包括一个测试程序,以证明这些线是随机选择的,分布均匀。

(To see how this code works, see the Wiki article I linked above.)

(要了解此代码的工作原理,请参阅我上面链接的 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);
            }
        }
    }
}

回答by Du D.

What you can do is parse the file to find the index of each line and then at a later time you can go back to a certain line by using Stream.Position to get the content. Using this method you don't need to keep anything in memory and it is reasonably fast. I tested this on a file that is 20K lines and 1MB in size. It took 7ms to index the file and 0.3to get the line.

您可以做的是解析文件以找到每一行的索引,然后您可以在稍后使用 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();
        }
    }