将 UTF-32 编码的字符串(C 风格)转换为 UTF-16(JSON 风格)编码的 Java/Clojure
Convert a UTF-32 encoded string (C style) in a UTF-16 (JSON style) encoded one in Java/Clojure
我从一个服务中收到一个字符串,该字符串显然使用 UTF-32 编码对其 unicode 字符进行编码,例如:\U0001B000
(C 风格的 unicode 编码)。但是,为了在 JSON 中序列化此信息,我必须将其编码为 UTF-16,例如:\uD82C\uDC00
.
但是,我不知道如何在 Java/Clojure 中读取这样的编码字符串,以及如何使用其他编码格式生成输出。
您可以使用以下方法从服务中读取接收到的字节:
(slurp received-bytes :encoding "UTF-32")
并使用以下方式编写字符串:
(spit destination string-to-encode :encoding "UTF-16")
如果你的意思是你有一个表示编码字符的二进制的字符串,那么你可以使用以下方法转换它:
(defn utf32->str [utf32-str]
(let [buf (java.nio.ByteBuffer/allocate 4)]
(.putInt buf (Integer/parseInt (subs utf32-str 2) 16))
(String. (.array buf) "UTF-32")))
(utf32->str "\U0001B000" )
然后使用以下方法将其转换为 UTF-16:
(defn str->utf16 [s]
(let [byte->str #(format "%02x" %)]
(apply str
(drop 1 (map #(str "\U" (byte->str (first %) ) (byte->str (second %) ))
(partition 2 (.getBytes s "UTF-16")))))))
这是一个示例 运行:
(str->utf16 (utf32->str "\U0001B000"))
;=> "\Ud82c\Udc00"
获得要替换的字符串后,以下函数将执行此操作:
(defn escape-utf16
[[_ _ a b c d]]
(format "\u%02X%02X\u%02X%02X" a b c d))
(defn replace-utf32
[^String s]
(let [n (Integer/parseInt (subs s 2) 16)]
(-> (->> (map #(bit-shift-right n %) [24 16 8 0])
(map #(bit-and % 0xFF))
(byte-array))
(String. "UTF-32")
(.getBytes "UTF-16")
(escape-utf16))))
(replace-utf32 "\U0001B000")
;; => "\uD82C\uDC00"
并且,对于有针对性的替换,使用正则表达式:
(require '[clojure.string :as string])
(string/replace
"this is a text \U0001B000."
#"\U[0-9A-F]{8}"
replace-utf32)
;; => "this is a text \uD82C\uDC00."
免责声明:我没有考虑过边缘(或提供的任何其他情况)案例。但我相信您可以以此为基础进行进一步探索。
我从一个服务中收到一个字符串,该字符串显然使用 UTF-32 编码对其 unicode 字符进行编码,例如:\U0001B000
(C 风格的 unicode 编码)。但是,为了在 JSON 中序列化此信息,我必须将其编码为 UTF-16,例如:\uD82C\uDC00
.
但是,我不知道如何在 Java/Clojure 中读取这样的编码字符串,以及如何使用其他编码格式生成输出。
您可以使用以下方法从服务中读取接收到的字节:
(slurp received-bytes :encoding "UTF-32")
并使用以下方式编写字符串:
(spit destination string-to-encode :encoding "UTF-16")
如果你的意思是你有一个表示编码字符的二进制的字符串,那么你可以使用以下方法转换它:
(defn utf32->str [utf32-str]
(let [buf (java.nio.ByteBuffer/allocate 4)]
(.putInt buf (Integer/parseInt (subs utf32-str 2) 16))
(String. (.array buf) "UTF-32")))
(utf32->str "\U0001B000" )
然后使用以下方法将其转换为 UTF-16:
(defn str->utf16 [s]
(let [byte->str #(format "%02x" %)]
(apply str
(drop 1 (map #(str "\U" (byte->str (first %) ) (byte->str (second %) ))
(partition 2 (.getBytes s "UTF-16")))))))
这是一个示例 运行:
(str->utf16 (utf32->str "\U0001B000"))
;=> "\Ud82c\Udc00"
获得要替换的字符串后,以下函数将执行此操作:
(defn escape-utf16
[[_ _ a b c d]]
(format "\u%02X%02X\u%02X%02X" a b c d))
(defn replace-utf32
[^String s]
(let [n (Integer/parseInt (subs s 2) 16)]
(-> (->> (map #(bit-shift-right n %) [24 16 8 0])
(map #(bit-and % 0xFF))
(byte-array))
(String. "UTF-32")
(.getBytes "UTF-16")
(escape-utf16))))
(replace-utf32 "\U0001B000")
;; => "\uD82C\uDC00"
并且,对于有针对性的替换,使用正则表达式:
(require '[clojure.string :as string])
(string/replace
"this is a text \U0001B000."
#"\U[0-9A-F]{8}"
replace-utf32)
;; => "this is a text \uD82C\uDC00."
免责声明:我没有考虑过边缘(或提供的任何其他情况)案例。但我相信您可以以此为基础进行进一步探索。