2013-11-02 3 views
1

EDIT: @Everyone Извините, я чувствую себя глупо, перепутавшись с размером int32. Вопрос может быть закрыт, но поскольку уже есть несколько ответов, я выбрал первый. Оригинальный вопрос ниже для справкиЧтение определенной строки из огромного текстового файла (C# 4.0)


Я ищу способ загрузки определенной строки из очень больших текстовых файлов, и я планировал на использовании File.ReadLines и метод Skip():

File.ReadLines(fileName).Skip(nbLines).Take(1).ToArray(); 

Проблема заключается в том, что Skip() принимает значение int, а значения int ограничены 2 миллионами или около того. Должно быть хорошо для большинства файлов, но Что делать, если файл содержит, скажем, 20 миллионов строк? Я пробовал использовать длинный, но без перегрузки Skip() принимает longs.

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

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

+2

примечание стороны: чтение 20 миллионов строк текста не может быть «очень быстро». Я не думаю, что это важно, какой код вы пишете, чтобы пропустить строки, поскольку большая часть времени будет потрачена на чтение с диска ... –

+4

Этот вопрос кажется не по теме, поскольку предпосылка этого вопроса ошибочна. Int32 достигает 2 миллиардов. – spender

+0

Linq также имеет метод 'ElementAtOrDefault', который пытается найти запись' N'th в последовательности. Но 'N' по-прежнему является' int' ('Int32'). Вы можете написать свой собственный метод расширения, где он является 'long' (' Int64'). –

ответ

5

Целые числа - это 32-разрядные номера, и поэтому ограничены 2 млрд. или около того.

Это означает, что если вам нужно прочитать случайную строку из файла, и все, что вы знаете, это то, что файл имеет линии, вам придется читать его по очереди, пока не достигнете нужной строки. Вы можете использовать некоторые буферы для облегчения ввода/вывода немного (они включены по умолчанию), но вы не получите лучшей производительности, чем это.

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

Ну, а не бесконечно, но много быстрее - от O (N) до почти O (1) (почти потому, что поиск случайного байта в файле не может быть операцией O (1) в зависимости от того, как это работает ОС).

2

Значения Int ограничены примерно 2 млрд. не два миллиона. Поэтому, если у вашего файла не будет больше, чем около 2,4 млрд. строк, все должно быть в порядке.

3

Я голосовал, чтобы закрыть ваш вопрос, потому что ваши помещения неверны. Однако, если бы это было реальной проблемой, нет ничего, чтобы остановить вас писать свой собственный метод Skip расширения, который принимает long вместо int:

public static class SkipEx 
{ 
    public static IEnumerable<T> LongSkip<T>(this IEnumerable<T> src, 
              long numToSkip) 
    { 
     long counter = 0L; 
     foreach(var item in src) 
     { 
      if(counter++ < numToSkip)continue; 
      yield return item; 
     } 
    } 
} 

так что теперь вы можете сделать такое сумасшествие, как

File.GetLines(filename).LongSkip(100000000000L) 

без проблем (и вернуться в следующем году ...). Тада!

1

Вы всегда можете использовать SkipWhile и TakeWhile, и писать свои собственные предикаты

+1

Спасибо. Не знал этого. – Sylverdrag

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