【问题标题】:Can't write to a Handle无法写入句柄
【发布时间】:2015-05-26 09:48:21
【问题描述】:

我正在用 Haskell 编写一个聊天服务器。我的可执行文件有以下代码:

data Client = Client {idx :: Int, hClient :: Handle} deriving (Show, Eq)

tellClient :: String -> Client -> IO ()
tellClient = flip $ hPutStrLn . hClient

askClient :: Client -> IO (String)
askClient = hGetLine . hClient

我希望能够使用它来写入和读取文件。我正在使用 HSpec 编写针对此代码的测试。我有以下函数来构建临时 Client 对象(依赖于“临时”)库:

withTempClient :: Int -> (Client -> IO a) -> IO a
withTempClient cIdx f = withTempFile "tests/generated" "clientFile.tmp" axn
  where axn _ handle = f $ Client cIdx handle

我用这个来测试上面的代码如下:

main = hspec $  do
  describe "client IO" $ do
    it "can ask and tell" $ withTempClient 1 $ \c -> do
      tellClient "hello" c
      hFlush $ hClient c
      askClient c `shouldReturn` "hello"

但测试失败并出现以下错误:

   uncaught exception: IOException of type EOF (test/generated
   /clientFile11587.tmp: hGetLine: end of file)

我想可能是我在withTempClient做错了什么,所以我添加了以下测试用例:

it "opens a handle corectly" $ withTempClient 1 $ \(Client _ h) -> do
  hIsOpen h `shouldReturn` True
  hIsWritable h `shouldReturn` True

但这已经过去了,所以我不确定问题可能是什么。我错过了什么?

【问题讨论】:

    标签: haskell io handle


    【解决方案1】:

    当您写入文件时,操作系统会跟踪您在所述文件中的位置。你得到一个EOF 错误,因为你在文件的末尾(开始是空的,你写的所有东西都在之前当前位置)。

    要解决这个问题,您需要使用 hSeek 将自己重新定位在文件的开头,如下所示:

    hSeek (hClient c) AbsoluteSeek 0
    

    有关寻找的更多详细信息,请参阅。这一点real world haskell

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 2013-10-18
      相关资源
      最近更新 更多