2017-02-03 18 views
1

У меня есть ОГРОМНЫЙ файл, над которым мне нужно делать операции. Огромный, как прибл. полмиллиона слов.Как загрузить огромный файл в строку или список в Racket?

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

Также я знаю, что могу загрузить его в строку, используя file-> string ИЛИ использовать file-> list, file-> lines, но они, похоже, слишком долгое время.

Является ли это правильный путь, чтобы загрузить его в список ?:

(define my-list (with-input-from-file "myFile.txt" read)) 

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

+2

Вы, вероятно, должны читать его лениво. Вам действительно нужен весь файл в памяти сразу? – Carcigenicate

ответ

0

Я собираюсь предположить, что на полмиллиона слов вы означаете, что ваш файл составляет около 5 ГБ.

Если это так, вы действительно не хотите читать все это в памяти. Я имею в виду, конечно, все это будет технически вписываться в ОЗУ многих компьютеров (хотя, конечно, не все), но для этого также потребуется некоторое время. С SSD это займет около 10 секунд, что, я думаю, в порядке, в зависимости от вашего приложения, это может быть на 100% лучше, но это, конечно, не быстро для стандартного настольного приложения. Однако, если вы читаете его с жесткого диска, это займет 60 секунд. И это предполагает, что ваш жесткий диск не фрагментировал файл, если это так, он будет еще медленнее.

Обе ситуации являются идеальным минимумом, и на практике загрузка файла размером 5 ГБ полностью в ОЗУ будет в лучшем случае медленной. (Хотя в некоторых очень редких случаях это то, что вы хотите, как правило, когда вы делаете высокопроизводительные вычислительные материалы.)

Лучшая идея, как предлагалось @Carcigenicate, - это вместо этого потоковое перемещение файла в вашу программу лениво, вам не нужно иметь длительную паузу. Для этого я рекомендую либо in-input-port-bytes, либо in-bytes-lines. Они оба генерируют потоки, которые затем можно использовать для обработки ваших данных, где первый из них дает вам по одному байту за раз, а другой дает вам одну строку байтов за раз. И до тех пор, пока вы не достигнете EOF. Вы можете сделать это в for

(call-with-input-file "file.txt" 
    (lambda (f) 
    (for/fold ([counter 0]) 
       ([i (in-input-port-bytes f)]) 
     (+ counter 1)) 

Приведенный выше пример является медленным способом вычислить количество байтов в файле. Но это показывает, как вы можете использовать in-input-port-bytes.

Есть и другие функции, чтобы создать поток символов, а не байт из файла: in-lines, read-port и т.д.

+0

5GB? Это означает, что каждое слово имеет в среднем 10737,4 символов, включая промежуточное пространство. –

+0

Вордс, вы абсолютно правы. По какой-то причине мой мозг читал это как полмиллиарда. Но я, в половине иона, торгую, все это немного разумнее. –

0

У меня есть стойкое ощущение, что ваша проблема не является чтение строки в, но довольно печать.

В частности, чтение файла такого размера займет около 0,03 секунды.

Я создал файл с помощью этой программы:

#lang racket 

(define str 
    "Beebe a reeble to one niner big druppy bonker watz. ") 

(with-output-to-file "/tmp/foo.txt" 
    (λ() 
    (for ([i (in-range (/ 500000 10))]) 
     (displayln str))))  

Затем я прочитал его в так:

#lang racket 

(define a (time (file->string "/tmp/foo.txt"))) 

...и производил этот выход:

cpu time: 30 real time: 30 gc time: 17 

.... Показаны 30 миллисекунд.

Обратите внимание, что, потому что я обернул file->string в define, я не печати всего этого дела. Это займет много времени.

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

  • Нет связанных вопросов^_^