Haskell 字节串更改 ASCII?

发布于 2024-11-29 18:51:31 字数 217 浏览 5 评论 0原文

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"

How do take a specific character from a bytestring then change its ASCII and then put it back?
Do I use readInt or something?

Ex: "aaaaa" ,"a" is 97 so minus 1 and you have "aa`aa"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

对你再特殊 2024-12-06 18:51:31

其他人已经解决了执行字节操作的问题,因此我将重点讨论问题的另一半:选择和更新 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

您可以使用 takedrop 而不是 splitAt 来实现此操作。现在,我们如何将其转换为在 ByteString 上工作?那么,ByteString 接口提供了 take、drop、splitAt、append 和缺点;我们唯一还没有完全可用的是我们在上面的 x:ending 部分中所做的模式匹配。幸运的是,ByteString 确实提供了类似的功能:

uncons :: ByteString -> Maybe (Word8, ByteString)

因此,使用它,我们可以编写一个适用于 ByteString 的新 onNth 函数:

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 是字节序列,而不是 序列)字符)。因此,如果您选择使用ByteString,那么您必须谈论的是字节,而不是文本。 ;-)

因此,您实际上是想询问一个将字节减一的函数,大概是在边界上环绕。 subtract 1 正是执行此操作的函数,因此要将 pack [97, 97, 97, 97, 97] 转换为 pack [97, 97, 96 , 97, 97],你可以写onNth 2 (subtract 1)。读起来几乎像英语!

Others have addressed the problem of doing the byte operations, so I will focus on the other half of your question: selecting and updating a particular byte within a ByteString. Let's start with implementing the operation for plain lists, using a more familiar interface:

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

You might equivalently implement this using take and drop instead of splitAt. Now, how can we translate this to work on ByteStrings? Well, the ByteString interface offers take, drop, splitAt, append, and cons; the only thing we haven't quite got available is the pattern matching that we did in the x:ending part above. Luckily, ByteString does offer something similar:

uncons :: ByteString -> Maybe (Word8, ByteString)

So, using that, we can write a new onNth function that works for ByteStrings:

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

Finally, we can discuss what function we should use as the f :: Word8 -> Word8 argument above. Although you talk about text above, I will point out that you shouldn't be using ByteString for text anyway (ByteStrings are sequences of bytes, not sequences of Chars). Therefore, if you have chosen to use ByteString, you must be talking about bytes, not text. ;-)

Therefore, you really meant to ask about a function which decreases a byte by one, presumably wrapping around on a boundary. subtract 1 is a function that does exactly that, so to convert pack [97, 97, 97, 97, 97] to pack [97, 97, 96, 97, 97], you might write onNth 2 (subtract 1). Reads almost like English!

余生共白头 2024-12-06 18:51:31

BS.map pred 怎么样?您还可以使用 fromEnumtoEnum 来进行与 Int 之间的转换。

How about BS.map pred? You can also use fromEnum and toEnum to make convert to / from Ints.

转角预定愛 2024-12-06 18:51:31

使用 BS.unpack 将字节转换为 Char 后,您可以使用 fromEnum :: Char -> Int(或者等效地,来自 Data.Charord)将 Char 转换为其 ASCII 值,然后您可以像普通整数一样进行操作。要将 ASCII 值从 Int 转换回 Char,请使用 toEnumData.Char.chr,然后可以使用 BS.pack 或类似方法将 Char 转换回 ByteString

Once you've converted the bytes to Chars with BS.unpack, you can use fromEnum :: Char -> Int (or, equivalently, ord from Data.Char) to convert a Char to its ASCII value, which you can then manipulate like a normal integer. To convert an ASCII value from an Int back to a Char, use toEnum or Data.Char.chr, and the Chars can then be converted back to a ByteString with BS.pack or similar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文