import qualified Data.ByteString.Lazy.Char8 as BS
stuff <- BS.readFile "stuff.txt"
如何从字节串中获取特定字符,然后更改其 ASCII,然后将其放回原处?我使用 readInt 还是什么?
例如: "aaaaa" ,"a" 是 97 所以减去 1 并且你有 "aa`aa"
import qualified Data.ByteString.Lazy.Char8 as BS
stuff <- BS.readFile "stuff.txt"
如何从字节串中获取特定字符,然后更改其 ASCII,然后将其放回原处?我使用 readInt 还是什么?
例如: "aaaaa" ,"a" 是 97 所以减去 1 并且你有 "aa`aa"
怎么样BS.map pred
?您还可以使用fromEnum
andtoEnum
转换为 / 从Int
s。
其他人已经解决了执行字节操作的问题,所以我将专注于您问题的另一半:选择和更新 a 中的特定字节ByteString
。让我们开始使用更熟悉的界面来实现普通列表的操作:
onNth :: Int -> (a -> a) -> ([a] -> [a])
onNth n f xs = case splitAt n xs of
(beginning, x:ending) -> beginning ++ f x : ending
_ -> xs -- happens when n is out-of-bounds
您可以等效地使用take
anddrop
而不是splitAt
. 现在,我们如何将其翻译为在ByteString
s 上工作?好吧,ByteString
界面提供take
, drop
, splitAt
, append
, 和cons
; 我们唯一没有得到的是我们在x:ending
上面部分中所做的模式匹配。幸运的是,ByteString
确实提供了类似的东西:
uncons :: ByteString -> Maybe (Word8, ByteString)
因此,使用它,我们可以编写一个适用于s的新onNth
函数:ByteString
second :: (b -> c) -> (a, b) -> (a, c)
second f (a, b) = (a, f b)
onNth :: Int -> (Word8 -> Word8) -> (ByteString -> ByteString)
onNth n f bs = case second uncons (splitAt n bs) of
(beginning, Just (x, ending)) -> append beginning (cons (f x) ending)
_ -> bs -- again, for out-of-bounds cases
最后,我们可以讨论应该使用什么函数作为上述f :: Word8 -> Word8
参数。尽管您在上面谈论文本,但我会指出您ByteString
无论如何都不应该使用文本(ByteString
s 是字节序列,而不是Char
s 序列)。因此,如果您选择使用ByteString
,那么您一定是在谈论字节,而不是文本。;-)
因此,您真的想问一个将字节减一的函数,大概是在边界上环绕。subtract 1
是一个完全可以做到这一点的函数,因此要转换pack [97, 97, 97, 97, 97]
为pack [97, 97, 96, 97, 97]
,您可以编写onNth 2 (subtract 1)
. 读起来几乎像英语!
使用 s将字节转换为Char
s 后BS.unpack
,您可以使用fromEnum :: Char -> Int
(或等效地,ord
from Data.Char
)将 a 转换Char
为其 ASCII 值,然后您可以像普通整数一样对其进行操作。要将 ASCII 值从 a 转换Int
为 a Char
,请使用toEnum
or Data.Char.chr
,Char
然后可以将 s 转换回 a ByteString
withBS.pack
或类似的值。