2016-03-21 48 views
1

Bazı bedenler programımda neyin yanlış olduğunu anlayabilir.Haskell: hSetFileSize: geçersiz bağımsız değişken (Geçersiz bağımsız değişken)

hSetFileSize: i aşağıdaki program yürütmeye çalışırsa, ben aşağıdaki hata iletisi alıyorum geçersiz argüman (Geçersiz değişken) Sadece okumak için dosyayı açıyoruz

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 

cevap

3

; ama kısaltma bir yazma işlemidir.

Bunun yerine ne yapabilirsiniz

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

Ek sözler:

Şimdi görevi tamamlamak için gerekli tüm araçlara sahip çoklu okuyucu veya tek bir yazar. Dosyayı iki kez açmak (boyutu almak ve içeriği okumak için bir kez, daha sonra kırpmak için) daha makul görünüyor. – Zeta

+0

@Zeta: iyi bir nokta, cevabı, ilk önce "ReadMode" işlemlerini yaptıktan sonra 'WriteMode 'olanları içeren olası bir çözümü göstermek için güncelledim. – Cactus

+2

Ayrıca, daha önce dosyayı okumak için bazı ısmarlama sıkı IO işlevlerini ([bunlar] gibi (https://hackage.haskell.org/package/strict/docs/System-IO-Strict.html)) kullanmayı tercih ederim. kesilmesiyle; standart IO fonksiyonları maalesef tembeldir. – Cactus

2

Not gibi bir şey: Bu cevap okuryazar Haskell yazılmıştır. Uzatma olarak .lhs ile kaydedin ve GHCi'de deneyin ya da derleyin. Bir dosya değiştirme

> import System.IO 

salt okunur bir işlem değildir. Yazmak için dosyayı açmanız gerekir. Ancak, bu sadece sorunlara yol açacaktır, çünkü sadece tek bir yazara veya birden fazla okura sahip olabilirsiniz. readFile'u kullandığınız için, dosyayı açmak için açtığınız için, sadece açık modu değiştiremezsiniz.

Kodunuzu yeniden düzenlersek daha kolay olur. Hemen tekrar etmemenin iki ihlalini görebiliriz, yani boyutu almak ve içeriği söylemek. Yani bunu düzeltelim:

> 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 bizim kolu kapalı olup ayrıca eylemlerle vida olamaz emin olur. Şimdi bir kolu kullanmadan bir dosyanın boyutunu değiştirmek için başka bir fonksiyon yazalım: Sıfır bayt dosya keser WriteMode beri burada ReadWriteMode ve değilWriteMode kullanılması önemlidir

> setFileSize :: FileName -> Integer -> IO() 
> setFileSize fn s = withFile fn ReadWriteMode $ \handle -> 
>  hSetFileSize handle s 

! Bu arada C'nin fopen'daki ile aynı davranış. readFile fileName`, ghc en çalışma zamanı sadece ya izin verdiği -

> 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" 
İlgili konular