【问题标题】:Faster alternatives to hFileSize to retrieve the size of a file in Haskell?更快的替代 hFileSize 来检索 Haskell 中文件的大小?
【发布时间】:2011-08-02 23:35:01
【问题描述】:

我想知道如何以最少的开销在 haskell 中获取文件的大小。现在我有以下代码:

getFileSize :: FilePath -> IO Integer
getFileSize x = do
handle <- openFile x ReadMode
size <- hFileSize handle
hClose handle
return size

这似乎很慢。我在 System.Posix.Files 中偶然发现了 getFileStatus,但不知道它是如何工作的——至少我在 ghci 中使用它时只会出错。另外,我不确定这是否适用于 Windows(可能不会)。

所以重申一下:在 Haskell 中获取文件大小的最佳(和平台无关)方法是什么?

【问题讨论】:

  • 上述解决方案的另一个问题是,只有在可以读取的情况下才能获取文件的大小。
  • 没错。我是 Haskell 新手,这是我发现的第一个函数。当然,我也遇到了各种权限问题。
  • 将文件大小用于显示目的之外的任何事情都是脆弱的。如果您获得文件大小,然后将其用于对文件进行操作,则无法保证在您处理文件时文件具有相同的大小。
  • 顺便说一句,getFileStatus "your_file_path" &gt;&gt;= print . fileSize(来自 System.Posix.Files)应该为您提供 GHCi 的大小(即使您没有读取权限)。也许值得 Dan unix-compat 推荐的尝试(它应该在 Windows 上工作)。

标签: haskell filesystems io


【解决方案1】:

不知道有没有更好的办法。 RWH 为 hFileSize 提供自己的包装器:

getFileSize path = handle (\_ -> return Nothing) $
  bracket (openFile path ReadMode) hClose $ \h -> do
    size <- hFileSize h
    return (Just size)

它还指出,unix-compat 是可用的,它“提供了 unix 包部分的可移植实现。”

【讨论】:

  • withFile path ReadMode hFileSize怎么样
【解决方案2】:

你想要的确实是getFileStatusfileSize,它们都来自System.Posix(如果你使用unix-compat 包而不是unix,它们在Windows 下也可以正常工作)。用法如下,错误处理由你来处理:

getFileSize :: String -> IO Integer
getFileSize path = do
    stat <- getFileStatus path
    return $ fromIntegral (fileSize stat)

为了它的价值,虽然我认为它的可读性较差,但您可以将此表单缩短为:

getFileSize path = getFileStatus path >>= \s -> return $ fileSize s

【讨论】:

  • 您也可以将其缩短为getFileSize path = fileSize &lt;$&gt; getFileStatus path(如果您不使用Control.Applicative,请将&lt;$&gt; 替换为`fmap`;它们是同义词);函数组合由let (f &lt;.&gt; g) x = f &lt;$&gt; g x in (&lt;.&gt;) 定义,这是getFileSize = fileSize &lt;.&gt; getFileStatus。我认为这两种形式都具有可读性,并且具有简短的优点。
  • 感谢@Antal S-Z。你是对的,应用语法看起来更好看。在相关的注释中,我想假设一个新定理:在足够长的时间线上,所有与 Haskell 相关的互联网讨论都会演变成一轮高尔夫。
  • @chomp 你介意解释一下为什么 System.Posix 也适用于 Windows 吗?我认为 Posix 是一个典型的东西,除非你使用 cygwin 或其他东西,否则它不能在 Windows 上运行。
  • @Tarrasch,我确信这取决于(Haskell)库的实现,但微软的标准运行时库已经有相当长的一段时间(因为 NT、IIRC 的旧版本)提供了大多数的实现(全部?)POSIX.1,其中包括stat 和相关实用程序等。例如:msdn.microsoft.com/en-us/library/14h5k7ff(v=vs.80).aspx
  • 刚试过这个,在 Windows 8 上,“System.Posix”不起作用。
【解决方案3】:

似乎 System.Posix.Files 在 Windows 中不起作用(Cygwin 除外),您尝试过 unix-compat 吗?

https://hackage.haskell.org/package/unix-compat-0.4.1.4/docs/System-PosixCompat-Files.html

这在我的 Windows 10 机器上对我有用:

> cabal install unix-compat
Resolving dependencies...
... lots of output, plus I had to put Cygwin on my path to make it build ...
> ghci
Prelude> import System.PosixCompat.Files
Prelude System.PosixCompat.Files> getFileStatus ".bashrc">>= \s -> return $ fileSize s
5764

【讨论】:

    【解决方案4】:
    import System.Posix.Files
    import System.Posix.Types
    
    getFileSize :: FilePath -> IO FileOffset
    getFileSize path = fmap fileSize $ getFileStatus path
    

    【讨论】:

      【解决方案5】:
      猜你喜欢
      • 1970-01-01
      • 2012-04-28
      • 2023-02-16
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 2016-10-13
      • 1970-01-01
      • 2015-02-17
      相关资源
      最近更新 更多