如何在Haskell中检查文本文件是否为空?
我已经尝试过:
main = do
contents <- getContents
if null contents then do
putStrLn "File was empty"
return()
else do
putStrLn "File was not empty"
return
答案 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
表达式返回的值与x
和y
的值相同 - 此处x
和y
都有键入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代码,假设您正在尝试检查普通文件的大小,您可能使用getFileStatus
和fileSize
中的帮助函数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)在阅读所需的部分内容后,程序将很快终止。