有人可以帮助我我的程序出了什么问题吗?当我尝试运行以下程序时,我收到以下错误消息:
hSetFileSize
:无效参数(无效参数)
import System.IO
main = do
putStrLn "Enter file name (Including full path) to read"
fileName <- getLine
handle <- openFile fileName ReadMode
sizeBeforeTrunc <- hFileSize handle
content <- readFile fileName
putStrLn $ "Size of the file Before truncation is " ++ (show sizeBeforeTrunc) ++ " bytes"
putStrLn $ "Content of the file is " ++ content
putStrLn "**************************************"
let n = sizeBeforeTrunc `div` 2
putStrLn $ "Truncating file to " ++ (show n) ++ " bytes"
info1 <- hSetFileSize handle (toInteger 10)
putStrLn $ show info1
sizeAfterTrunc <- hFileSize handle
putStrLn $ "Size of the file After truncation is " ++ (show sizeAfterTrunc) ++ " bytes"
putStrLn $ "Content of the file is " ++ content
hClose handle
您打开的文件仅用于读取;但截断是一种写入操作。
相反,您可以做的是类似
main = do
putStrLn "Enter file name (Including full path) to read"
fileName <- getLine
sizeBeforeTrunc <- withFile fileName ReadMode $ h -> do
sizeBeforeTrunc <- hFileSize h
content <- hGetContents h
putStrLn $ "Size of the file Before truncation is " ++ (show sizeBeforeTrunc) ++ " bytes"
putStrLn $ "Content of the file is " ++ content
putStrLn "**************************************"
let n = sizeBeforeTrunc `div` 2
putStrLn $ "Truncating file to " ++ (show n) ++ " bytes"
sizeAfterTrunc <- withFile fileName WriteMode $ h -> do
info1 <- hSetFileSize h (toInteger 10)
putStrLn $ show info1
hFileSize h
putStrLn $ "Size of the file After truncation is " ++ (show sizeAfterTrunc) ++ " bytes"
putStrLn $ "Content of the file is " ++ content
注意:这个答案是用识字的哈斯克尔写的。使用.lhs
保存它作为扩展,并在GHCi中尝试或编译它。
> import System.IO
更改文件不是只读操作。您需要打开文件进行写入。但是,这会导致问题,因为您可能只有一个编写器或多个读取器。由于您使用readFile
打开文件进行读取,因此不能简单地更改打开模式。
如果我们重构您的代码,它会变得更容易。我们可以立即看到两个违反"不要重复自己"的行为,即获取大小和告诉内容。因此,让我们解决这个问题:
> putAndCount :: FileName -> String -> IO Int
> putAndCount fn msg = withFile fn ReadMode $ handle -> do
> size <- hFileSize handle
> content <- hGetContents handle
> putStrLn $ "Size of the file " ++ msg ++ " is " ++ show size ++ " bytes"
> putStrLn $ "Content of the file is " ++ content
> return size
withFile
确保我们的手柄已关闭,并且不会因进一步的操作而拧紧。现在让我们编写另一个函数来更改文件的大小,而无需使用句柄:
> setFileSize :: FileName -> Integer -> IO ()
> setFileSize fn s = withFile fn ReadWriteMode $ handle ->
> hSetFileSize handle s
在这里使用 ReadWriteMode
而不是WriteMode
很重要,因为WriteMode
会将文件截断为零字节!顺便说一下,这与 C fopen
中的行为相同。
现在我们有了完成任务所需的所有工具:
> main :: IO ()
> main = do
> putStrLn "Enter file name (Including full path) to read"
> fileName <- getLine
>
> sizeBeforeTrunc <- putAndCount fileName "Before truncation"
> putStrLn "**************************************"
>
> let n = sizeBeforeTrunc `div` 2
> putStrLn $ "Truncating file to " ++ (show n) ++ " bytes"
> setFileSize fileName n
> putAndCount fileName "After truncation"