我想要一个看起来像文件句柄的东西,但实际上是由内存缓冲区支持的,用于I/O重定向。我该怎么做?
我刚刚写了一个相关的库,名为“knob” [hackage]。你可以使用它创建引用/修改ByteString
的Handle
:
import Data.ByteString (pack)
import Data.Knob
import System.IO
main = do
knob <- newKnob (pack [])
h <- newFileHandle knob "test.txt" WriteMode
hPutStrLn h "Hello world!"
hClose h
bytes <- Data.Knob.getContents knob
putStrLn ("Wrote bytes: " ++ show bytes)
实际上这是库设计上的一个缺陷,也让我很困扰。我看到两种方法可以做到您想要的事情,但都不是很理想。
创建一个新的类型类,使当前的句柄成为它的实例,编写另一个实例来处理内存中的数据,并更改所有需要使用此功能的程序。可能只需导入 System.SIO
(或您想要命名的其他名称)而不是 System.IO
就可以解决问题。但是如果您在诸如 Data.ByteString
等库中使用自定义 I/O 例程,则还需要做更多的工作。
重写 I/O 库以扩展其支持此功能。并不容易,需要大量的工作,但这并不是特别困难的工作。然而,这将会导致与没有此库的系统存在兼容性问题。
这可能是不可能的。至少,GHC 似乎需要一个操作系统文件描述符来执行所有读/写/搜索操作。
请参阅来自 GHC 源的 /libraries/base/IOBase.lhs
。
您可以通过寻求操作系统的帮助来实现相同的效果:创建一个临时文件,将句柄连接到该文件,然后为 I/O 重定向内存映射该文件。这样,所有句柄 I/O 就会在内存映射部分中变得可见。
createPipe :: IO (Handle, Handle)
https://www.stackage.org/haddock/lts-10.3/process-1.6.1.0/System-Process.html#v:createPipe
createPipe
的文档中说:“*创建一个用于进程间通信的管道[...]”。”这如何解决OP的问题? - runeks如果不修改编译器,这是不可能的。这是因为Handle是一个抽象数据类型,而不是一个类型类。