2016-08-13 28 views
5

UstawianieW jaki sposób przejdziesz katalog i wykonasz jakąś funkcję na wszystkich plikach i połączysz dane wyjściowe w sposób efektywny w pamięci?

muszę przemierzać katalog ponad 100+ plików .txt, otwarty każdy i zrobić kilka funkcji na każdym, a następnie połączyć wyniki. Te pliki są ogromne, rzędu 10 GB. Niektóre wspólne działanie w psuedocode może być:

foldr concatFile mempty $ openFile <$> [filePath1, ..., filePathn] 
foldr countStuff 0  $ openFile <$> [filePath1, ..., filePathn] 

Sztuką jest, aby upewnić się, że wszystkie pliki nie istnieją w pamięci w tym samym czasie, mój poprzedni rozwiązanie naiwny stworzył wszystkie rodzaje plików typu swap na moim mac. Ponadto, jeśli jedna z właściwości filePath jest nieprawidłowa, chciałbym po prostu pominąć i kontynuować program.

moje rozwiązanie

Obecnie używam przewodu i chciałby znaleźć rozwiązanie za pomocą przewodu, jeśli to możliwe. Ale jeśli nie jest to właściwe narzędzie, nie mam nic przeciwko używaniu czegoś innego.

Odpowiedz

3

Można wykonanie gniazdo przewód tak:

{-# LANGUAGE OverloadedStrings #-} 

import Conduit 
import qualified Data.ByteString as BS 

-- Process a single file 
processFile :: FilePath -> IO() 
processFile path = runResourceT (sourceFile path =$= mapC BS.length $$ sumC) >>= print 

-- Run processFile for directory in a tree  
doit :: FilePath -> IO() 
doit top = runResourceT $ sourceDirectoryDeep False top $$ mapM_C (liftIO . processFile) 

Wymień processFile o co chcesz zrobić - tym ignorując plik. Rozumiem, że producent sourceFile wydajnie porcjuje zawartość pliku.

I, zgodnie z this Yesod article, sourceDirectoryDeep powinien skutecznie przejść przez strukturę katalogów.

Rzecz, której najwyraźniej nie można zrobić z sourceDirectoryDeep, to katalogi przycinania .

+1

O ile katalog nie ma naprawdę olbrzymiej liczby plików, wymyślna maszyna brzmi jak przesada. A może właśnie czytasz katalog, a następnie używasz 'foldM' do przetwarzania każdego, łącząc wyniki po drodze? – dfeuer

+0

Nie wiem, czy OP tego potrzebuje, ale 'sourceDirectoryDeep' wykonuje rekursywne przejście. Ale tak, większa wydajność będzie pochodzić z przetwarzania zawartości każdego pliku w sposób porowaty. – ErikR

+2

@eveuer conduit (or pipes) 'foldM' is * nawet nie jest * trochę bardziej skomplikowany niż' Control.Monad.foldM'. Zdumiewająca liczba katastrof, które mogą wystąpić w wyniku pracy z listą filtrów leniwie opracowanych z przeglądania katalogów, była jednym z oryginalnych dzieci plakatu do przesyłania strumieniowego io. To * po prostu nie jest prostsze * i nie powinno być zalecane. 'import Conduit' jest krótszy niż' import Control.Monad', a po jego wpisaniu masz do dyspozycji zarówno drzewo katalogów, jak i poprawną funkcję składania. – Michael

Powiązane problemy