Get N Chars from Handle

There exists
hGetBuf :: Handle -> Ptr a -> Int -> IO Int
but why is there not
hGetNChars :: Handle -> Int -> IO String?

Can’t you do

hGetNChars h n = replicateM n (hGetChar h)

This is what I use for that purpose:

fdRead :: Fd
       -> ByteCount -- ^How many bytes to read
       -> IO ByteString -- ^The bytes read

https://hackage.haskell.org/package/unix-2.8.5.1/docs/System-Posix-IO-ByteString.html#v:fdRead

It’s POSIX only though.

@brandonchinn178 hGetChar has unbelievably bad performance.

@tomjaguarpaw Handle_ has a Char buffer seems like that could be used.

How many characters are you reading that you will notice this? And If performance matters, why read into a String at all?

If you want high performance, its probably better to use hGetSome on a bytestring

https://hackage.haskell.org/package/bytestring-0.12.1.0/docs/Data-ByteString.html#v:hGetSome

4 Likes

I don’t have byte data, I have to deal with character data with multiple encodings that handles already deal with.

hGetSome is just a wrapper around hGetBufSome which only deals with binary data and thus would only be compatible with utf8.

I’m writing a library so I need to support bytestring, text, and string.

You can do it as you prefer, of course, but if I were doing it I’d read raw binary data and deal with encodings myself, rather than trust Haskell’s base library to do it. That way is fraught with all sorts of awkward implicit behaviours configured by LC_*, and has always scared me.

1 Like

Thanks, I’ve worked with the raw and char buffers in the text package so I’ll do something similar in the optimized version.