我必须将ByteString转换为7位字节的列表。例如,字节与A,B,C,d等位:将字节串转换为7位字节列表
abcdefgh ijklmnop qrstuvwx yz...
应转换为:
abcdefg hijklmn opqrstu vwxyz...
我使用二进制位包,以便做到这一点。我的convert8to7
功能是递归的,但二进制位没有提供任何意义来检查缺少位,而Get
monad确实具有isEmpty
或remaining
函数。
这里是我的代码:
import Data.Word
import Data.Binary.Bits.Get
import Data.Binary.Get (runGet)
import Data.ByteString.Lazy.Char8
convert8to7 :: BitGet [Word8]
convert8to7 = do
bits <- getWord8 7
rest <- convert8to7
return (bits : rest)
main :: IO()
main = do
let datas = pack "Hello world!"
print $ runGet (runBitGet convert8to7) datas
当我运行这段代码,它在逻辑上说:
Data.Binary.Get.runGet at position 12: demandInput: not enough bytes
我能做到这一点,转换与二进制位或我应该找一个其他的包?
更新
这里是基于user5402回答我的代码:
import Data.Word
import Data.Bits
import Data.Binary.Bits.Get
import Data.Binary.Get (runGet)
import qualified Data.ByteString.Lazy.Char8 as BS
convert87 :: Int -> BitGet [Word8]
convert87 n
| n == 0 = return []
| n < 7 = do bits <- getWord8 n
return [shiftL bits (7 - n)]
| otherwise = do bits <- getWord8 7
rest <- convert87 (n-7)
return $ bits : rest
to87 :: BS.ByteString -> [Word8]
to87 datas = runGet (runBitGet (convert87 len)) datas
where len = fromIntegral $ BS.length datas * 8
main :: IO()
main = do
let datas = BS.pack "Hello world!"
print $ to87 datas
hackage上的Binary-Bits版本已过时。 Github上的那个自2003年4月1日以来已经有了'isEmpty :: BitGet Bool'。 –
虽然已经过时了,但我会坚持使用hackage提供的版本。首先它会更容易维护,其次'isEmpty'函数不允许我处理没有足够的位形成7位字节的情况。谢谢 – zigazou
不够公平。没有任何关于'BitGet'的结构可以防止添加一个完全符合你想要的功能,但是它再次不会受到黑客攻击。看到一个过时的软件包让我不禁想知道:他们是否有接管废弃项目的程序? –