我正在寻找一种有效的方法来从文本文件中读取数字而无需安装其他软件包。 Data.ByteString.Lazy.Char8.readInt
似乎可以解决整数问题。我已经读过ByteString
现在有一个readDouble
方法,但是当我写import Data.ByteString.Lex.Lazy.Double (readDouble)
时,编译器会抱怨:
Main.hs:4:7: Could not find module `Data.ByteString.Lex.Lazy.Double': locations searched: Data/ByteString/Lex/Lazy/Double.hs Data/ByteString/Lex/Lazy/Double.lhs
我的bytestring包版本是0.9.1.5。
那么,我做错了吗?或者可能有更好的解决方案?感谢。
更新:好的,似乎readDouble
在package bytestring-lexer中,默认情况下没有安装。还有其他想法吗?
答案 0 :(得分:5)
另一种解决方案:安装bytestring-lexing软件包,然后使用我为您优化的readDouble
。
cabal install bytestring-lexing
该包为浮点文字提供optimized parsing functions:
readDouble :: ByteString -> Maybe (Double, ByteString)
答案 1 :(得分:3)
我在关键路径上遇到解析双打的唯一一次,我使用了这个:
{-# LANGUAGE ForeignFunctionInterface #-}
import qualified Data.ByteString.Char8 as B
import Foreign.C.Types
import Foreign.C.String
import System.IO.Unsafe
foreign import ccall unsafe "stdlib.h atof" c_atof :: CString -> IO CDouble
unsafeReadDouble = unsafePerformIO . flip B.useAsCString c_atof
但是当时没有任何东西在字节字符串中看起来像readDouble
。如果它现在是标准的话,这可能是一个更好的解决方案。
答案 2 :(得分:2)
这就是我想出来的。
我使用了JB提供的功能,并添加了两个技巧,我从bytestring-lexing的源代码中学到了(感谢,sclv!)。第一个是这个功能:
strict = SB.concat . LB.toChunks
它有效地将一个惰性字节字符串转换为非惰性字节字符串。
第二个技巧是函数Data.ByteString.Internal.inlinePerformIO
,它是unsafePerformIO的一个更有效的变体。
这里有完整的代码,可以快速读取数字:
{-# LANGUAGE ForeignFunctionInterface #-}
import qualified Data.ByteString.Lazy.Char8 as LB
import qualified Data.ByteString as SB
import Data.ByteString.Internal (inlinePerformIO)
import Foreign.C.String (CString)
import Foreign.C (CDouble)
import Data.Maybe (fromJust)
foreign import ccall unsafe "stdlib.h atof" c_atof :: CString -> IO Double
unsafeReadDouble = inlinePerformIO . flip SB.useAsCString c_atof
{-# INLINE unsafeReadDouble #-}
readDouble = unsafeReadDouble . SB.concat . LB.toChunks
readInt = fst . fromJust . LB.readInt
一个示例程序,用于计算输入中所有数字的总和:
main = LB.getContents >>= (print . sum . map readDouble . LB.lines)
它在约0.5秒内处理一个11Mb文件(1M个数字)
我还found several links,其中讨论了更高效的readInt
版本。据推测,可以根据类似的想法构建readDouble
。但我想我现在会坚持使用现在的版本。