Domanda

Voglio qualcosa che assomigli a un handle di file ma che sia in realtà supportato da un buffer in memoria da utilizzare per i reindirizzamenti I/O.Come posso fare questo?

È stato utile?

Soluzione

Non è possibile senza modificare il compilatore.Questo perché Handle è un tipo di dati astratto, non una classe di tipi.

Altri suggerimenti

Ho appena scritto una libreria che fornisce questo, chiamata "knob" [hacking].Puoi usarlo per creare Handles che fanno riferimento/modifica a ByteString:

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)

Se riesci a esprimere ciò che vuoi fare in termini di C o chiamate di sistema, potresti utilizzare la Foreign Function Interface (FFI) di Haskell.Ho iniziato a suggerire di utilizzare mmap, ma ripensandoci penso che mmap potrebbe essere una mappatura nel modo sbagliato anche se la usi con l'opzione anonima.

Puoi trovare ulteriori informazioni sulla FFI Haskell sul wiki haskell.org.

Questo potrebbe non essere possibile. GHC, almeno, sembra richiedere un handle per avere un descrittore di file del sistema operativo utilizzato per tutte le operazioni di lettura/scrittura/ricerca.

Vedere /libraries/base/IOBase.lhs dalle fonti GHC.

Potresti riuscire a ottenere lo stesso effetto avvalendoti dell'aiuto del sistema operativo:creare un file temporaneo, collegarvi l'handle e quindi mappare in memoria il file per i reindirizzamenti I/O.In questo modo, tutti gli I/O dell'handle diventerebbero visibili nella sezione mappata in memoria.

In realtà si tratta di un bug nella progettazione della libreria e che ha infastidito anche me.Vedo due approcci per fare ciò che vuoi, nessuno dei quali è terribilmente attraente.

  1. Crea una nuova classe di tipo, rendi l'handle corrente un'istanza di essa, scrivi un'altra istanza per eseguire i dati in memoria e modifica tutti i tuoi programmi che devono utilizzare questa funzionalità.Forse questo è semplice come importare System.SIO (o come vuoi chiamarlo) invece di System.IO.Ma se usi le routine I/O personalizzate in librerie come Data.ByteString, c'è ancora molto lavoro da fare lì.

  2. Riscrivere le librerie I/O per estenderle per supportare questo.Non banale e richiede molto lavoro, ma non sarebbe un lavoro particolarmente difficile da svolgere.Tuttavia, hai un problema di compatibilità con i sistemi che non dispongono di questa libreria.

Per aggiungere una risposta moderna a questa domanda, potresti usare createPipe da System.Process:

createPipe :: IO (Handle, Handle)

https://www.stackage.org/haddock/lts-10.3/process-1.6.1.0/System-Process.html#v:createPipe

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top