Как прочитать указанную строку в текстовом файле?

учитывая текстовый файл, как я буду читать произвольную строку и ничего больше в файле?

скажем, у меня есть файл test.формат txt. Как мне прочитать строку 15 в файле?

все, что я видел, это материал, включающий хранение всего текстового файла в виде массива строк, а затем использование значения номера строки в качестве номера строки для использования из массива... но есть некоторые осложнения: текстовый файл чрезвычайно огромен и машина, которая приложение, которое я кодирую, не совсем первоклассная система. Скорость не является главным приоритетом, но это определенно важная проблема.

есть ли какие-либо способы только читать определенную строку из текстового файла и сохранить результат в виде строки?

Спасибо за ваши ответы: Файл немного структурирован. У него есть 25 строк информации, а затем X строки чисел, но строка 17 из первых 25 имеет значение X.

но тогда, есть 1 пустая строка, и она повторяется во всем, как вторая запись в файле и X может иметь различное значение для каждой записи.

то, что я хочу сделать, это прочитать и сохранить первые 25 строк как независимые значения, а затем сохранить следующий X (обычно около 250) строк в виде массива. Затем я собираюсь сохранить его в базе данных SQL и повторить со следующей записью, пока не достигну Yth запись (количество записей в файле находится в линия 3)

Изменить 2: Хорошо, я думаю, что нашел решение, основанное на комбинации ваших ответов.

Я собираюсь прочитать первые 25 строк и сохранить его как массив. Я скопирую соответствующее содержимое массива в локальные переменные, затем удалю первые 25 строк. Затем я могу использовать информацию для хранения следующего X строки (значение элемента 13 в массиве) в виде массива, сериализовать его, сохранить его в базе данных, а затем удалить строки что я только что прочитал.

затем я мог бы повторить процесс для каждой последующей записи.

конечно, это зависит от одного предположения, которое я делаю, что, честно говоря, я не уверен, что это правда. Можно ли удалить первый n строки из текстового файла из C# без необходимости читать все это и переписывать его без первого n строки?

14 ответов


.NET 4.0 edit

начиная с .NET 4.0, можно получить доступ к одной строке файла напрямую. Например, для доступа к строке 15:

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

это вернет только требуемую строку


Так как вы не можете предсказать местоположение (вы можете?) из 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();
   }
}

Если каждая строка имеет фиксированную длину, вы можете открыть поток вокруг нее, искать (байты на строку) * 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();
    }
}

в качестве альтернативы вы можете просто использовать 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();
        }
    }
}

нет, к сожалению, нет. На уровне raw файлы не работают на основе номера строки. Вместо этого они работают на основе позиции / смещения. Корневая файловая система не имеет понятия строк. Это концепция, добавленная компонентами более высокого уровня.

таким образом, нет способа сообщить операционной системе, пожалуйста, откройте файл в строке blah. Вместо этого вам нужно открыть файл и пропустить подсчет новых строк, пока вы не передадите указанное число. Затем сохраните следующий набор байтов в время до следующей новой строке.


Если у вас нет фиксированного размера строк, вам нужно прочитать каждую строку, пока вы не достигнете нужной строки. Хотя вам не нужно хранить каждую строку, просто отбросьте ее, если это не та строка, которую вы хотите.

Edit:

Как уже упоминалось, также можно было бы искать в файле, если бы длины строк были предсказуемыми , то есть вы могли бы применить некоторую детерминированную функцию для преобразования номера строки в позицию файла.


Как сказал Мехрдад, вы не можете просто искать 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
    }

прочитайте пять строк каждый раз, просто поместите свое заявление в if statement, вот оно

        String str1 = @"C:\Users\TEMP\Desktop\StaN.txt";   

        System.IO.StreamReader file = new System.IO.StreamReader(str1);

        line = file.ReadLine();

        Int32 ctn=0;

        try
        {

            while ((line = file.ReadLine()) != null)
            {

                    if (Counter == ctn)
                    {
                        MessageBox.Show("I am here");
                        ctn=ctn+5;
                        continue;
                    }
                    else
                    {
                        Counter++;
                        //MessageBox.Show(Counter.ToString());
                        MessageBox.Show(line.ToString());
                    } 
                }

            file.Close();
        }
        catch (Exception er)
        {

        }

Если все линии имеют фиксированную длину, вы можете использовать метод поиска потока для перемещения в правильное начальное положение.

Если линии имеют переменную длину, ваши параметры более ограничены.

Если это файл, который вы будете использовать только один раз, а затем отбрасывать, то вам лучше всего прочитать его и работать с ним в memeory.

Если это файл, который вы будете хранить и будет читать больше, чем писать, вы можете создать пользовательский индексный файл, содержащий начальные позиции каждой строки. Затем используйте этот индекс, чтобы получить позицию поиска. Процесс создания индексного файла является ресурсоемким. Каждый раз, когда вы добавляете новую строку в файл, вам нужно будет обновить индекс, поэтому обслуживание становится нетривиальной проблемой.


вы можете читать строку за строкой, поэтому вам не нужно читать все сразу (возможно, вообще)

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

Если ваш файл содержит строки разной длины, и вам нужно часто читать строки, и вам нужно быстро прочитать его, вы можете сделать индекс файла, прочитав его один раз, сохраняя позицию каждой новой строки, а затем, когда вам нужно прочитать строку, вы просто ищете позицию строки в индексе, искать там, а затем вы читаете строку.

Если вы добавляете новые строки в файл, вы можете просто добавить индекс новых строк, и вам не нужно переиндексировать все это. Хотя, если ваш файл изменится где-то в строке, которую вы уже проиндексировали, вам нужно переиндексировать.


хотя вы не можете искать N-ю строку непосредственно в несимметричном файле без чтения данных в файле (потому что вам нужно подсчитать, сколько строк вы продвинулись в файл), вы можете подсчитать разрывы строк, пока не доберетесь до нужной строки, которая занимает наименьший объем памяти и, вероятно, имеет лучшую производительность.

это будет более эффективной памятью, чем чтение всего массива, так как он будет читать только в файл, пока не достигнет конца файла или номер строки (что наступит раньше). Он далек от совершенства, но, вероятно, удовлетворит ваши потребности:

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;
}

испытанный. Это так просто:

string line = File.ReadLines(filePath).ElementAt(actualLineNumber - 1);

пока у вас есть текстовый файл, это должно работать. Позже, в зависимости от того, какие данные вы ожидаете прочитать, вы можете соответственно отлить строку и использовать ее.


вариация. Выдает ошибку, если номер строки больше, чем количество строк.

string GetLine(string fileName, int lineNum)
{
    using (StreamReader sr = new StreamReader(fileName))
    {
        string line;
        int count = 1;
        while ((line = sr.ReadLine()) != null)
        {
            if(count == lineNum)
            {
                return line;
            }
            count++;
        }
    }
    return "line number is bigger than number of lines";  
}

        if (File.Exists(fpath))
        {

            var data = File.ReadLines(fpath);
            Console.WriteLine(data.ToArray()[14]);
        }

поздний ответ, но стоит того .

вам нужно загрузить строки в объект array или list, где каждая строка будет назначена индексу, а затем просто вызвать любой диапазон строк по их индексу в цикле for .

решение довольно хорошее, но между ними есть потребление памяти .

дать ему попробовать ...Его стоит