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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1262965/
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-06 14:22:44  来源:igfitidea点击:

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

c#stringfile-ioinput

提问by ankushg

Given a text file, how would I go about reading an arbitrary line and nothing else in the file?

给定一个文本文件,我将如何读取文件中的任意行而没有其他内容?

Say, I have a file test.txt. How would I go about reading line number 15 in the file?

说,我有一个文件 test.txt。我将如何阅读文件中的第 15 行?

All I've seen is stuff involving storing the entire text file as a String array and then using the value of the line number as the number of the String to use from the array... but there are some complications: The text file is enormously huge and the machine that the application I'm coding isn't exactly a top-notch system. Speed isn't the top priority, but it is definitely a major issue.

我所看到的只是涉及将整个文本文件存储为字符串数组,然后使用行号的值作为要从数组中使用的字符串的编号……但有一些复杂情况:文本文件是非常庞大,我正在编写的应用程序的机器并不完全是一流的系统。速度不是首要任务,但绝对是一个主要问题。

Are there any ways to ONLYread a specific line of a text file and store the result as a string?

有什么方法可以读取文本文件的特定行并将结果存储为字符串?

Thanks for your responses: The file is KINDA structured. It's got 25 lines of info and then Xlines of numbers but line 17 of the first 25 has the value of X.

感谢您的回复:该文件的结构有点像。它有 25 行信息,然后是X行数字,但前 25 行的第 17 行的值为X

But then, there's 1 blank line and it repeats itself all over as a second record in the file and Xcan have a different value for each record.

但是,有 1 个空行,它作为文件中的第二条记录重复出现,并且X可以为每条记录使用不同的值。

What I want to do is read and store the first 25 lines as independent values and then store the next X(usually around 250) lines as an array. Then I'm going to store it in an SQL database and repeat with the NEXT record until I reach the Yth record (the number of records in the file is in line 3)

我想要做的是读取并存储前 25 行作为独立值,然后将下X 行(通常大约 250 行)存储为数组。然后我将它存储在一个 SQL 数据库中并重复 NEXT 记录,直到我到达第Y 条记录(文件中的记录数在第 3 行)

EDIT 2: Alright, I think I've gotten to a solution based on a combination of your alls' responses.

编辑 2:好的,我想我已经根据你们所有人的反应得到了一个解决方案。

I'm going to read the first 25 lines and store it as an array. I'll copy the pertinent contents of the array to local variables then I'll delete the first 25 lines. Then, I can use the info to store the next Xlines (the value of item 13 in the array) as an array, serialize it, store it in a database then delete the lines that I just read.

我将读取前 25 行并将其存储为数组。我会将数组的相关内容复制到局部变量,然后删除前 25 行。然后,我可以使用该信息将接下来的X行(数组中第 13 项的值)存储为一个数组,对其进行序列化,将其存储在数据库中,然后删除我刚刚读取的行。

I could then repeat the process for each subsequent record.

然后,我可以为每个后续记录重复该过程。

Of course, this relies on one assumption I'm making, which to be honest, I'm not sure is true. Is it possible to delete the first nlines from a text file from within C# without having to read the entire thing and re-write it without the first nlines?

当然,这取决于我所做的一个假设,说实话,我不确定这是真的。是否可以从 C# 中的文本文件中删除前n行而不必读取整个内容并在没有前n行的情况下重新编写它?

采纳答案by Mehrdad Afshari

.NET 4.0 edit

.NET 4.0 编辑

Since .NET 4.0, it is possible to access a single line of a file directly. For instance, to access line 15:

从 .NET 4.0 开始,可以直接访问文件的单行。例如,要访问第 15 行:

string line = File.ReadLines(FileName).Skip(14).Take(1).First();

This will return only the line required

这将只返回所需的行



Since you can't predict the location (can you?) of the i-th line in the file, you'll have to read all previous lines too. If the line number is small, this can be more efficient than the ReadAllLinesmethod.

由于您无法预测文件中第 i 行的位置(可以吗?),因此您也必须阅读所有先前的行。如果行号很小,这可能比该ReadAllLines方法更有效。

string GetLine(string fileName, int line)
{
   using (var sr = new StreamReader(fileName)) {
       for (int i = 1; i < line; i++)
          sr.ReadLine();
       return sr.ReadLine();
   }
}

回答by Ron Warholic

Unless you have fixed sized lines, you need to read every line until you reach the line you want. Although, you don't need to store each line, just discard it if it's not the line you desire.

除非您有固定大小的行,否则您需要阅读每一行,直到到达您想要的行。虽然,您不需要存储每一行​​,如果不是您想要的行,只需将其丢弃。

Edit:

编辑:

As mentioned, it would also be possible to seek in the file if the line lengths were predictable -- that is to say you could apply some deterministic function to transform a line number into a file position.

如前所述,如果行长度是可预测的,也可以在文件中查找——也就是说,您可以应用一些确定性函数将行号转换为文件位置。

回答by Samuel

You could read line by line so you don't have to read the entire all at once (probably at all)

您可以逐行阅读,因此您不必一次阅读全部内容(可能根本不需要)

int i=0
while(!stream.eof() && i!=lineNum)
    stream.readLine()
    i++
line = stream.readLine()

回答by JaredPar

No unfortunately there is not. At the raw level files do not work on a line number basis. Instead they work at a position / offset basis. The root filesystem has no concept of lines. It's a concept added by higher level components.

不,不幸的是没有。在原始级别文件不能在行号的基础上工作。相反,它们在位置/偏移基础上工作。根文件系统没有行的概念。它是由更高级别的组件添加的概念。

So there is no way to tell the operating system, please open file at line blah. Instead you have to open the file and skip around counting new lines until you've passed the specified number. Then store the next set of bytes into an array until you hit the next new line.

所以没有办法告诉操作系统,请在 blah 处打开文件。相反,您必须打开文件并跳过计算新行,直到您通过指定的数字。然后将下一组字节存储到数组中,直到遇到下一个新行。

回答by Dave Downs

If each line is a fixed length then you can open a Stream around it, seek (bytes per line) * n into the file and read your line from there.

如果每行都是固定长度,那么您可以围绕它打开一个 Stream,在文件中查找(每行字节数)* n 并从那里读取您的行。

using( Stream stream = File.Open(fileName, FileMode.Open) )
{
    stream.Seek(bytesPerLine * (myLine - 1), SeekOrigin.Begin);
    using( StreamReader reader = new StreamReader(stream) )
    {
        string line = reader.ReadLine();
    }
}

Alternatively you could just use the StreamReader to read lines until you found the one you wanted. That way's slower but still an improvement over reading every single line.

或者,您可以只使用 StreamReader 来读取行,直到找到您想要的行。这种方式较慢,但仍然比阅读每一行有所改进。

using( Stream stream = File.Open(fileName, FileMode.Open) )
{
    using( StreamReader reader = new StreamReader(fileStream) )
    {
        string line = null;
        for( int i = 0; i < myLineNumber; ++i )
        {
            line = reader.ReadLine();
        }
    }
}

回答by VladV

As Mehrdad said, you cannot just seek to the n-th line without reading the file. However, you don't need to store the entire file in memory - just discard the data you don't need.

正如 Mehrdad 所说,您不能在不阅读文件的情况下只查找第 n 行。但是,您不需要将整个文件存储在内存中——只需丢弃不需要的数据即可。

string line;
using (StreamReader sr = new StreamReader(path))
    for (int i = 0; i<15; i++)
    {
       line = sr.ReadLine();
       if (line==null) break; // there are less than 15 lines in the file
    }

回答by RB Davidson

If the lines are all of a fixed length you can use the Seek method of a stream to move to the correct starting positiion.

如果线条都是固定长度,您可以使用流的 Seek 方法移动到正确的起始位置。

If the lines are of a variable length your options are more limited.

如果线条长度可变,您的选择就更加有限。

If this is a file you will be only using once and then discarding, then you are best off reading it in and working with it in memeory.

如果这是一个您将只使用一次然后丢弃的文件,那么您最好阅读它并在内存中使用它。

If this is a file you will keeping and will be reading from more than writing to, you can create a custom index file that contains the starting positions of each line. Then use that index to get your Seek position. The process of creating the index file is resource intensive. Everytime you add a new line to the file you will need to update the index, so maintenance becomes a non-trivial issue.

如果这是一个您将保留的文件并且将读取多于写入的文件,您可以创建一个包含每行起始位置的自定义索引文件。然后使用该索引来获取您的搜索位置。创建索引文件的过程是资源密集型的。每次向文件中添加新行时,您都需要更新索引,因此维护变得非常重要。

回答by RB Davidson

If your file contains lines with different lengths and you need to read lines often and you need to read it quickly you can make an index of the file by reading it once, saving position of each new line and then when you need to read a line, you just lookup the position of the line in your index, seek there and then you read the line.

如果您的文件包含不同长度的行并且您需要经常读取行并且需要快速读取它,您可以通过读取一次来创建文件索引,保存每个新行的位置,然后当您需要读取一行时,您只需在索引中查找该行的位置,在那里查找,然后阅读该行。

If you add new lines to the file you can just add index of new lines and you don't need to reindex it all. Though if your file changes somewhere in a line you have already indexed then you have to reindex.

如果您向文件添加新行,您只需添加新行的索引,而无需全部重新索引。但是,如果您的文件在已编入索引的某行中的某处发生更改,则您必须重新编入索引。

回答by Mahdi Al Aradi

Late Answer but worth it .

迟到但值得。

You need to load the lines in array or list object where each line will be assign to an index ,then simply call any range of lines by their index in for loop .

您需要加载数组或列表对象中的行,其中每一行都将分配给一个索引,然后只需在 for 循环中通过索引调用任何范围的行。

Solution is pretty Good ,but there is a memory consumption in between .

解决方案非常好,但两者之间存在内存消耗。

give it try ...Its worth it

试一试……值得

回答by Dave

While you can't seek an N'th line directly in a non-symmetrical file without reading data in the file (because you need to count how many lines you have progressed into the file) you can count line breaks until you get to the line you want which takes the least amount of memory and probably has the best performance.

虽然您不能在不读取文件中的数据的情况下直接在非对称文件中查找第 N 行(因为您需要计算已进入文件的行数),但您可以计算换行符,直到到达您想要的行占用最少的内存并且可能具有最佳性能。

This is going to be more memory efficient than reading everything to an array, since it will only read into the file until it hits the end of the file or the line number (whichever comes first). It is far from perfect, but will probably suit your needs:

这将比将所有内容读取到数组中的内存效率更高,因为它只会读入文件,直到到达文件末尾或行号(以先到者为准)。它远非完美,但可能会满足您的需求:

string line15 = ReadLine(@"C:\File.csv", 15);

public string ReadLine(string FilePath, int LineNumber){
    string result = "";
    try{
    if( File.Exists(FilePath) ){
        using (StreamReader _StreamReader = new StreamReader(FilePath)){
        for (int a = 0; a < LineNumber; a++) {
            result = _StreamReader.ReadLine();
        }
        }
    }
    }catch{}
    return result;
}