我必須將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'的結構可以防止添加一個完全符合你想要的功能,但是它再次不會受到黑客攻擊。看到一個過時的軟件包讓我不禁想知道:他們是否有接管廢棄項目的程序? –