如何在Haskell中检查文本文件是否为空?

时间:2018-01-11 22:58:23

标签: haskell

如何在Haskell中检查文本文件是否为空?

我已经尝试过:

main = do
       contents <- getContents
       if null contents then do
       putStrLn "File was empty"
       return()
       else do
       putStrLn "File was not empty"
       return

2 个答案:

答案 0 :(得分:6)

问题实际上主要在于您的格式化,而不是您的逻辑!

Haskell中的空白很重要,请参阅this wiki page。遵循其规则,并在最后return语句中修复小错字(您需要返回单位,(),就像您之前所做的那样):

main = do
   contents <- getContents
   if null contents then do
       putStrLn "File was empty"
       return ()
   else do
       putStrLn "File was not empty"
       return ()

这应该是完美的。但是,它并不是最佳实践 - 您在do表达式的每个部分中都有if块,您正在构建一个新的monadic动作,这不是必要。鉴于putStrLn无论如何都会返回IO (),您可以这样做:

main = do
   contents <- getContents
   if null contents then
       putStrLn "File was empty"
   else
       putStrLn "File was not empty"

请记住,if ... then x else y表达式返回的值与xy的值相同 - 此处xy都有键入IO (),因此表达式返回IO (),这就是为什么它可以在此do块中使用。

请注意,这不会检查文件是否为空,它会检查标准输入是否为空:如果您将文件中的输入输入到此程序中,这是可以的。 s stdin,但如果你想真正阅读文件,你应该查看readFile - 你几乎不需要改变这个程序!像下面这样的东西可以解决这个问题:

main = do
   putStrLn "Enter the file path:"
   path <- getLine
   contents <- readFile path
   if null contents ...

答案 1 :(得分:0)

@ hnefatl的答案很好,可能就是您正在寻找的原始代码。但是,如果其他人在尝试弄清楚如何检查文件是否为空时遇到此问题,则会出现更高级(但首选)的答案。

真实&#34; Haskell代码,假设您正在尝试检查普通文件的大小,您可能使用getFileStatusfileSize中的帮助函数System.Posix,如这个问题:What is the best way to retrieve the size of a file in haskell?

具体来说,像下面这样的函数适用于Linux:

import System.Posix

isEmpty1 :: FilePath -> IO Bool
isEmpty1 fp = do
  stat <- getFileStatus fp
  return (fileSize stat == 0)

如果您需要Windows兼容性,则可以安装提供unix-compat跨平台版本的getFileStatus包,也可以使用hFileSize中的System.IO

import System.IO

isEmpty2 :: FilePath -> IO Bool
isEmpty2 fp = do
  sz <- withFile fp ReadMode hFileSize
  return (sz == 0)

上面isEmpty1的主要优点是getFileStatus应该非常高效,因为它只使用一次系统调用(stat调用)。如果你必须检查大量文件的大小,这将是首选的方法。 isEmpty2解决方案也没问题,但它涉及(至少)三个系统调用(open,然后fstat,然后close)并且需要打开文件句柄暂时,如果您并行检查大量文件,这可能是一个问题。

两者都会比readFile方法表现更好,因为它们不会导致读取任何文件数据。相反,readFile需要从磁盘读取至少一个数据块,以确定结果字符串是否为空。

感谢Haskell的懒惰I / O,它只是进行初始读取并且不必阅读整个文件,但这会导致另一个奇怪的怪癖。 readFile设计用于打开文件并懒惰地读取其内容的方式,结果是文件保持打开状态直到内容完成读取,并且没有其他方法可以强制关闭文件没有阅读完整的内容!因此,除非文件足够短以至于初始读取完全读取,否则文件句柄将无限期保持打开状态。所以,如果你有一个程序来检查一大堆文本文件是否为空,如果其中一些文件文件大于一个块,那么你可能最终会用完文件句柄。

一般情况下,除非(a)处理整个文件内容,否则不应使用readFile;或(b)在阅读所需的部分内容后,程序将很快终止。