Clojure等价于Python的编码('十六进制')和解码('十六进制')
有没有一种在Clojure中以十六进制编码和解码字符串的习惯用法?从Python的例子:Clojure等价于Python的编码('十六进制')和解码('十六进制')
'Clojure'.encode('hex')
# ⇒ '436c6f6a757265'
'436c6f6a757265'.decode('hex')
# ⇒ 'Clojure'
为了表示对我而言一些努力:
(defn hexify [s]
(apply str
(map #(format "%02x" (int %)) s)))
(defn unhexify [hex]
(apply str
(map
(fn [[x y]] (char (Integer/parseInt (str x y) 16)))
(partition 2 hex))))
(hexify "Clojure")
;; ⇒ "436c6f6a757265"
(unhexify "436c6f6a757265")
;; ⇒ "Clojure"
我相信你unhexify
功能是地道的,因为它可以。然而,hexify
可以写成一个简单的方法:
(defn hexify [s]
(format "%x" (new java.math.BigInteger (.getBytes s))))
好的,谢谢,如果没有内置的处理方法,我会使用你的建议 – 2012-04-10 06:54:11
这种格式的字节数组的第一位是1,为“负数”。 – 2015-03-22 18:44:55
我也习惯使用这种方法,直到我意识到前导零被移除。 – mattias 2017-05-23 07:09:40
你的实现(S)不用于非ASCII字符工作,
(defn hexify [s]
(apply str
(map #(format "%02x" (int %)) s)))
(defn unhexify [hex]
(apply str
(map
(fn [[x y]] (char (Integer/parseInt (str x y) 16)))
(partition 2 hex))))
(= "\u2195" (unhexify(hexify "\u2195")))
false ; should be true
为了克服这一点,你需要序列化的字节该字符串使用所需的字符编码,每个字符可以是多字节。
这有几个“问题”。
- 请记住,所有数字类型都在JVM中签名。
- 没有无符号字节。
在惯用的java中,你会使用一个整数的低位字节并将它掩盖起来,就像你使用它的地方一样。
int intValue = 0x80;
byte byteValue = (byte)(intValue & 0xff); -- use only low byte
System.out.println("int:\t" + intValue);
System.out.println("byte:\t" + byteValue);
-- output:
-- int: 128
-- byte: -128
clojure有(unchecked-byte)
有效地做同样的事情。
例如,使用UTF-8,你可以这样做:
(defn hexify [s]
(apply str (map #(format "%02x" %) (.getBytes s "UTF-8"))))
(defn unhexify [s]
(let [bytes (into-array Byte/TYPE
(map (fn [[x y]]
(unchecked-byte (Integer/parseInt (str x y) 16)))
(partition 2 s)))]
(String. bytes "UTF-8")))
; with the above implementation:
;=> (hexify "\u2195")
"e28695"
;=> (unhexify "e28695")
"↕"
;=> (= "\u2195" (unhexify (hexify "\u2195")))
true
只要性能没有问题,所有这一切都很好 - 我敢打赌,Python示例将在任何更长的字符串上超过这些解决方案。如果你需要表现,还有很多工作要做。 – 2012-04-10 13:35:18
由于所有发布的解决方案有一些缺陷,我分享我自己:
(defn hexify "Convert byte sequence to hex string" [coll]
(let [hex [\0 \1 \2 \3 \4 \5 \6 \7 \8 \9 \a \b \c \d \e \f]]
(letfn [(hexify-byte [b]
(let [v (bit-and b 0xFF)]
[(hex (bit-shift-right v 4)) (hex (bit-and v 0x0F))]))]
(apply str (mapcat hexify-byte coll)))))
(defn hexify-str [s]
(hexify (.getBytes s)))
和
(defn unhexify "Convert hex string to byte sequence" [s]
(letfn [(unhexify-2 [c1 c2]
(unchecked-byte
(+ (bit-shift-left (Character/digit c1 16) 4)
(Character/digit c2 16))))]
(map #(apply unhexify-2 %) (partition 2 s))))
(defn unhexify-str [s]
(apply str (map char (unhexify s))))
优点:
- 高性能
- 通用的字节流< - >字符串转换有专门的包装
- 处理以十六进制结果
使用Java库前导零? – Marcin 2012-04-08 13:02:30
你已经拥有它 – Ankur 2012-04-08 14:30:17
@Ankur:显然不是sw1nn的答案显示 - 这就是为什么我想要一个现有的功能,如果可能的话。 – 2012-04-15 18:30:54