2011-12-07 10 views
9

bytestringをニブル単位で扱い、その16進(0-F)表現をきれいに印刷する慣用方法は何ですか?バイト文字列から16進数のニフティに細かい印刷

putStrLn . show . B.unpack 
-- [1,126] 

どの、さらなる作業の際に

putStrLn . show . map (\x -> N.showIntAtBase 16 (DC.intToDigit) x "") . B.unpack 
["1","7e"] 

しかし、私が本当にしたいことはまだ

["1","7","e"] 

かそれ以上である

['1','7','e'] 

私は[ "1" をアップのmungeことができ、 "7e"]しかしその文字列の操作むしろ数値操作を行う。数値をシフトしてマスキングする必要がありますか?

答えて

10

私はオーバー複雑だと思うこれは、(私がupvotedしていること)最大taldykinの答えについて詳しく説明したいと思います。 NoMonomorphismRestriction,printfまたはData.Listの必要はありません。

import qualified Data.ByteString as B 
import Numeric (showHex) 

prettyPrint :: B.ByteString -> String 
prettyPrint = concat . map (flip showHex "") . B.unpack 

main :: IO() 
main = putStrLn . prettyPrint . B.pack $ [102, 117, 110] 
+1

+1、ちょうどその 'concat。 map' == 'concatMap' –

+8

' showHex'が2にならないので、ここで結果を乱すでしょう。 – Peaker

+0

@Peakerが正しいです、この解決方法は間違いです。それは先頭の0を切り捨てます。下のcrockeeaの答えは正しいです。 –

3

あなたは["1","7e"] :: [文字列] concat ["1", "7e"]は[シャア]に等しいと['1','7','e'] :: [Char]に等しい"17e" :: Stringである持っています。あなたが粉々にその文字列を分割しているよりも

:このような

> Data.List.Split.splitEvery 1 . concat $ ["1", "7e"] 
["1","7","e"] 
it :: [[Char]] 
+5

'Data.List.Split.splitEvery 1' ==' map(:[]) ' –

4

Somethig:

{-# LANGUAGE NoMonomorphismRestriction #-} 

import qualified Data.ByteString as B 
import Text.Printf 
import Data.List 
import Numeric 

hex = foldr showHex "" . B.unpack 
list = printf "[%s]" . concat . intersperse "," . map show 

テスト:

> let x = B.pack [102,117,110] 
> list . hex $ x 
"['6','6','7','5','6','e']" 

UPDああ、愚かなメモリがありますリーク:もちろんfoldrをに置き換える必要があります(怠惰はここでは必要とされていないため):

hex = foldl' (flip showHex) "" . B.unpack 
+0

もちろん、' foldl''バージョンでは、バイトを逆順に、 "リトルエンディアン"スタイルで出力します。 – crockeea

5

あなたは今Data.ByteString.Builderを使用することができます。

は、ここに私のバージョンです。その進同等にByteStringを印刷する(正しい順序でバイトごとに二桁の数字で、かつ効率的に)、単に使用するには:

toLazyByteString . byteStringHex 

または

toLazyByteString . lazyByteStringHex 

をあなたByteStringのどの味に応じて、入力として持っています。

関連する問題