Haskell:hSetFileSize:无效参数(无效参数)

时间:2016-03-21 06:39:45

标签: file haskell io

有些人可以帮我解决我的程序出了什么问题。当我试图运行以下程序时,我收到以下错误消息:

  

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

2 个答案:

答案 0 :(得分:3)

您正在打开文件以供阅读;但截断是一种写操作。

你可以做的事情就像是

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            

答案 1 :(得分:2)

注意:这个答案写在有文化的Haskell中。以> import System.IO 作为扩展名保存,并在GHCi中试用或编译。

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非常重要,因为fopen会将文件截断为零字节!顺便说一句,这与C&#39 {s} > 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" 中的行为相同。

现在我们拥有完成任务所需的所有工具:

{{1}}