簡體   English   中英

防止“getCurrentDirectory:資源耗盡(打開文件太多)”錯誤

[英]Preventing “getCurrentDirectory: resource exhausted (Too many open files)” error

我試圖在一大堆小文件上運行Parsec解析器,並收到錯誤說我有太多打開的文件。 我知道我需要使用嚴格的IO,但我不知道該怎么做。 這是有問題的代碼:

files = getDirectoryContents historyFolder

hands :: IO [Either ParseError [Hand]]
hands = join $ sequence <$> parseFromFile (many hand) <<$>> files

注意:我的<<$>>函數是這樣的:

(<<$>>) :: (Functor f1, Functor f2) => (a -> b) -> f1 (f2 a) -> f1 (f2 b)
a <<$>> b = (a <$>) <$> b

我不知道你的parseFromFile函數現在看起來是什么樣的(在問題中包含它可能是一個好主意),但我猜你正在使用Prelude.readFile ,正如@ Markus1189指出的那樣包括懶惰的I / O 。 要獲得嚴格的I / O,您只需要一個嚴格的readFile ,例如Data.Text.IO.readFile

pipesconduit這樣的流數據庫可以讓你避免一次將整個文件讀入內存,但據我所知,parsec沒有提供允許這種情況發生的流式接口。 另一方面,attoparsec確實包括這樣的流接口,並且管道和管道都具有attoparsec適配器庫(例如, Data.Conduit.Attoparsec )。

tl; dr:您可能只需要以下輔助函數:

import qualified Data.Text as T
import qualified Data.Text.IO as TIO

readFileStrict :: FilePath -> IO String
readFileStrict = fmap T.unpack . TIO.readFile

您可以使用BangPatterns語言擴展來強制執行IO操作的嚴格性,在本例中為parseFromFile 例如,可以在以下位置更改功能hands

hands :: [String] → IO [Either ParseError [Hand]]
hands [] = return []
hands (f:fs) = do
  !res ← parseFromFile hand f
  others ← hands fs
  return (res:others)

在移動到列表中的下一個文件之前,此版本的手等待每次調用parseFromFile的結果。 一旦你有了這個,問題就會消失。 一個完整的玩具示例是:

{-# LANGUAGE BangPatterns #-}
import Control.Monad
import Control.Applicative hiding (many)
import Data.Char (isDigit)
import System.Directory (getDirectoryContents)
import System.FilePath ((</>))
import Text.ParserCombinators.Parsec

data Hand = Hand Int deriving Show

hand :: GenParser Char st [Hand]
hand = do
  string "I'm file "
  num ← many digit
  newline
  eof
  return [Hand $ read num]

files :: IO [String]
files = map ("manyfiles" </>)
      ∘ filter (all isDigit) <$> getDirectoryContents "manyfiles"

hands :: [String] → IO [Either ParseError [Hand]]
hands [] = return []
hands (f:fs) = do
  !res ← parseFromFile hand f
  others ← hands fs
  return (res:others)

main :: IO 𐌏
main = do
  results ← files >≥ hands
  print results

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM