2013-10-14 2 views
1

У меня есть один CLJ файл:получать именно равные Clojure/clojurescript строки в UTF-8

;; 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 в его эквивалентный массив байтов. Похоже, что я использую UTF-8 для обеих сторон clojure и clojurescript, но они не генерируют одинаковые массивы байтов (они не имеют одинаковой длины). Как создать точные массивы байтов для любых двух эквивалентных строк в 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

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) для примера строки в обоих случаях.

 Смежные вопросы

  • Нет связанных вопросов^_^