1
import qualified Data.ByteString.Lazy.Char8 as BS

stuff <- BS.readFile "stuff.txt"

如何从字节串中获取特定字符,然后更改其 ASCII,然后将其放回原处?我使用 readInt 还是什么?

例如: "aaaaa" ,"a" 是 97 所以减去 1 并且你有 "aa`aa"

4

3 回答 3

2

怎么样BS.map pred?您还可以使用fromEnumandtoEnum转换为 / 从Ints。

于 2011-08-16T19:21:45.920 回答
2

其他人已经解决了执行字节操作的问题,所以我将专注于您问题的另一半:选择和更新 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

您可以等效地使用takeanddrop而不是splitAt. 现在,我们如何将其翻译为在ByteStrings 上工作?好吧,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无论如何都不应该使用文本(ByteStrings 是字节序列,而不是Chars 序列)。因此,如果您选择使用ByteString,那么您一定是在谈论字节,而不是文本。;-)

因此,您真的想问一个将字节减一的函数,大概是在边界上环绕。subtract 1是一个完全可以做到这一点的函数,因此要转换pack [97, 97, 97, 97, 97]pack [97, 97, 96, 97, 97],您可以编写onNth 2 (subtract 1). 读起来几乎像英语!

于 2011-08-16T19:47:45.473 回答
1

使用 s将字节转换为Chars 后BS.unpack,您可以使用fromEnum :: Char -> Int(或等效地,ordfrom Data.Char)将 a 转换Char为其 ASCII 值,然后您可以像普通整数一样对其进行操作。要将 ASCII 值从 a 转换Int为 a Char,请使用toEnumor Data.Char.chrChar然后可以将 s 转换回 a ByteStringwithBS.pack或类似的值。

于 2011-08-16T19:21:27.863 回答