在UTF-8中获得完全相同的clojure / clojurescript字符串

时间:2013-10-14 06:18:30

标签: clojure clojurescript

我有一个clj文件:

;; stringparity.clj ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ns stringparity)

    (defn get-java-string [input]
      (.getBytes input "UTF-8"))

一个cljs文件:

;;; stringparity.cljs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(ns stringparity
  (:import goog.crypt))    

    (defn get-js-string [input]
      (goog.crypt.stringToUtf8ByteArray input))

以下代码不可执行,因为get-js-string仅适用于javascript,get-java-string适用于java;我只是假装你可以在同一台机器上运行它们来说明出了什么问题。使用“简单”字符串时,这两个函数都可以正常工作,但在使用""这样的“复杂”字符串时会失败。我希望能够在clojure或clojurescript上散列任何字符串,并使它们的散列相同。为了做到这一点,我需要能够将javascript或java字符串转换为其等效的字节数组。似乎我在clojure和clojurescript方面都使用UTF-8,但是它们不会生成相同的字节数组(它们甚至不是相同的长度)。如何为clojure和clojurescript中的任何两个等效字符串生成完全相同的字节数组。

(= (seq (get-js-string "hello"))  [104, 101, 108, 108, 111]
   (seq (get-java-string "hello") [104, 101, 108, 108, 111]))


(= (seq (get-js-string ""))
   ;; when in cljs, get-js-string evaluates to the following
   [237 160 180 237 188 134]
   (seq (get-java-string ""))
   ;; when in clj, get-java-string evaluates to the following
   [-16 -99 -116 -122])

2 个答案:

答案 0 :(得分:4)

答案 1 :(得分:3)

goog.crypt.stringToUtf8ByteArray无法处理在Javascript字符串中表示为“代理对”的字符(例如您的“”示例)并产生不正确的结果。

如果您不需要UTF-8但只需要一系列字节值来生成散列,则可以选择在两种情况下将字符编码为UTF-16字节序列:

cljs:

(defn to-byte [n] (if (>= n 128) (- n 256) n))

(defn get-js-string [input]
  (map to-byte
    (mapcat
      #(let [u (.charCodeAt input %)]
         [(-> (bit-and u 0xFF00) (bit-shift-right 8)) (bit-and u 0xFF)]) 
      (range (.-length input)))))

CLJ:

(defn get-java-string [input]
  (.getBytes input "UTF-16BE"))

在这两种情况下,这应该为您的示例字符串提供序列(-40 52 -33 6)