2009-08-11 7 views
44

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

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

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

Есть ли способы для ТОЛЬКО читает определенную строку текстового файла и сохраняет результат в виде строки?

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

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

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

EDIT 2: Хорошо, я думаю, что я пришел к решению, основанному на сочетании ваших ответов.

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

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

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

+0

Являются ли сами линии фиксированной длиной (в байтах) или нет. Это делает большой разброс по типам доступных решений. –

+0

«У нас есть 25 строк информации»: я думаю, это противоречит предположениям фиксированной линии, упомянутым ниже, вам просто нужно прочитать все строки и получить то, что вы хотите по пути. –

+0

Что вам действительно нужно, это не система для непосредственного получения i-й строки. Вам просто нужно обработать файл в один проход и выполнить некоторые операции на этом пути. Вы можете использовать фрагмент кода в моем ответе (метод ReadLine) для чтения по одной строке за раз. –

ответ

84

.NET 4.0 редактировать

С .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(); 
    } 
} 
+3

Если ваш текстовый файл не структурирован с фиксированной длиной линии. –

+11

... фиксированный в * байтах *, а не только символы ... –

+6

Не обязательно фиксированный, также работает, если он * предсказуем *. –

3

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

Edit:

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

+0

+1, но, как заметил Джон Скит, вам нужен фиксированный размер в байтах, что подразумевает кодировку ASCII. –

+3

Хенк: Как исходит в байтах, подразумевается ASCII? –

+0

Действительно: UTF-32 помнит, или даже такие вещи, как ISO-8859-1. –

0

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

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

Вопрос отмечен C#. –

+0

Проблема с чтением строки за строкой заключается в том, что вы будете иметь латентность и искать с каждым чтением. Если файл имеет много строк, производительность будет проходить через пол. Чтение больших блоков (скажем, 64 кбайта или более) данных и поиск разрывов строк в памяти будет иметь более высокую производительность. –

+0

RB Davidson: Если поток буферизуется, это будет не проблема. –

4

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

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

13

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

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

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

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

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

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

0

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

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

-3

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

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

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

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

0

В то время как вы не можете искать строку непосредственно в 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; 
} 
2

READ ПЯТЬ ЛИНИЙ Каждый раз просто положить ваше заявление, если заявление, вот это

 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) 
     { 

     } 
-1
 if (File.Exists(fpath)) 
     { 

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

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

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

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

+0

Ожидается, что вы предоставите некоторое объяснение, а не только часть кода, которому следует доверять вслепую. – Ivan

Смежные вопросы