将字节串转换为 7 位字节列表
Converting a bytestring to a list of 7 bits bytes
我必须将 ByteString 转换为 7 位字节的列表。例如,具有 a、b、c、d 等位的字节:
abcdefgh ijklmnop qrstuvwx yz...
应转换为:
abcdefg hijklmn opqrstu vwxyz...
我使用 Binary-Bits 包来完成它。我的 convert8to7
函数是递归的,但 Binary-Bits 不提供任何方法来检查是否缺少位,而 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
我可以使用 Binary-Bits 进行这种转换还是应该寻找其他包?
更新
这是我基于 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
问题是您需要跟踪要解码的位数 - BitGet
monad 不知道何时到达输入末尾。
试试这个:
import Data.Word
import Data.Binary.Bits.Get
import Data.Binary.Get (runGet)
import Data.ByteString.Lazy.Char8
import qualified Data.ByteString.Lazy.Char8 as BS
convert87 :: Int -> BitGet [Word8]
convert87 n
| n < 7 = do bits <- getWord8 n
return [bits]
| otherwise = do bits <- getWord8 7
rest <- convert87 (n-7)
return $ bits : rest
main :: IO ()
main = do
let datas = pack "Hello world!"
len = fromIntegral $ BS.length datas * 8
print $ runGet (runBitGet (convert87 len)) datas
Update:这是在 Get
monad 中检测输入结束的方法(BitGet
monad 在其之上实现)。它依赖于 Get
的替代 class。函数 chunks7
将一个字节字符串分成 7 个块,剩余部分进入最后一个块。
据我所知,BitGet
没有实施备选方案 class - 虽然我确信它可以。
import Data.Word (Word8)
import Data.Binary.Get
import Data.ByteString.Lazy.Char8
import qualified Data.ByteString as BSW
import qualified Data.ByteString.Lazy as BSL
import Control.Applicative -- used for (<|>)
chunks7 :: Get [[Word8]]
chunks7 = do
b <- isEmpty
if b
then return []
else do chunk <- fmap BSW.unpack (getByteString 7)
<|> fmap BSL.unpack getRemainingLazyByteString
rest <- chunks7
return $ chunk : rest
main :: IO ()
main = do
let datas = pack "Hello world! This is a test"
print $ runGet chunks7 datas
我必须将 ByteString 转换为 7 位字节的列表。例如,具有 a、b、c、d 等位的字节:
abcdefgh ijklmnop qrstuvwx yz...
应转换为:
abcdefg hijklmn opqrstu vwxyz...
我使用 Binary-Bits 包来完成它。我的 convert8to7
函数是递归的,但 Binary-Bits 不提供任何方法来检查是否缺少位,而 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
我可以使用 Binary-Bits 进行这种转换还是应该寻找其他包?
更新
这是我基于 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
问题是您需要跟踪要解码的位数 - BitGet
monad 不知道何时到达输入末尾。
试试这个:
import Data.Word
import Data.Binary.Bits.Get
import Data.Binary.Get (runGet)
import Data.ByteString.Lazy.Char8
import qualified Data.ByteString.Lazy.Char8 as BS
convert87 :: Int -> BitGet [Word8]
convert87 n
| n < 7 = do bits <- getWord8 n
return [bits]
| otherwise = do bits <- getWord8 7
rest <- convert87 (n-7)
return $ bits : rest
main :: IO ()
main = do
let datas = pack "Hello world!"
len = fromIntegral $ BS.length datas * 8
print $ runGet (runBitGet (convert87 len)) datas
Update:这是在 Get
monad 中检测输入结束的方法(BitGet
monad 在其之上实现)。它依赖于 Get
的替代 class。函数 chunks7
将一个字节字符串分成 7 个块,剩余部分进入最后一个块。
据我所知,BitGet
没有实施备选方案 class - 虽然我确信它可以。
import Data.Word (Word8)
import Data.Binary.Get
import Data.ByteString.Lazy.Char8
import qualified Data.ByteString as BSW
import qualified Data.ByteString.Lazy as BSL
import Control.Applicative -- used for (<|>)
chunks7 :: Get [[Word8]]
chunks7 = do
b <- isEmpty
if b
then return []
else do chunk <- fmap BSW.unpack (getByteString 7)
<|> fmap BSL.unpack getRemainingLazyByteString
rest <- chunks7
return $ chunk : rest
main :: IO ()
main = do
let datas = pack "Hello world! This is a test"
print $ runGet chunks7 datas