mik*_*era 5 java serialization clojure
我正在寻找一种方法来有效地将Clojure对象序列化为二进制格式 - 即不仅仅是做经典的打印和读取文本序列化.
即我想做的事情:
(def orig-data {:name "Data Object"
:data (get-big-java-array)
:other (get-clojure-data-stuff)})
(def binary (serialize orig-data))
;; here "binary" is a raw binary form, e.g. a Java byte array
;; so it can be persisted in key/value store or sent over network etc.
;; now check it works!
(def new-data (deserialize binary))
(= new-data orig-data)
=> true
Run Code Online (Sandbox Code Playgroud)
我的动机是我有一些包含大量二进制数据的大型数据结构(在Java数组中),我想避免将这些全部转换为文本并重新转换回来的开销.此外,我正在尝试保持格式紧凑,以最大限度地减少网络带宽使用.
我想要的具体功能:
在Clojure中执行此操作的最佳/标准方法是什么?
我可能在这里遗漏了一些东西,但标准Java序列化有什么问题?太慢,太大,别的什么?
用于普通Java序列化的Clojure包装器可能是这样的:
(defn serializable? [v]
(instance? java.io.Serializable v))
(defn serialize
"Serializes value, returns a byte array"
[v]
(let [buff (java.io.ByteArrayOutputStream. 1024)]
(with-open [dos (java.io.ObjectOutputStream. buff)]
(.writeObject dos v))
(.toByteArray buff)))
(defn deserialize
"Accepts a byte array, returns deserialized value"
[bytes]
(with-open [dis (java.io.ObjectInputStream.
(java.io.ByteArrayInputStream. bytes))]
(.readObject dis)))
user> (= (range 10) (deserialize (serialize (range 10))))
true
Run Code Online (Sandbox Code Playgroud)
有些值无法序列化,例如Java流和Clojure atom/agent/future,但它应该适用于大多数普通值,包括Java原语和数组以及Clojure函数,集合和记录.
你是否真的保存了什么取决于.在我对小型数据集的有限测试中,序列化为文本和二进制似乎是大致相同的时间和空间.
但是对于大部分数据是Java基元数组的特殊情况,Java序列化可以快几个数量级并节省大量空间.(在笔记本电脑上快速测试,100k随机字节:序列化0.9毫秒,100kB;文本490毫秒,700kB.)
请注意,该(= new-data orig-data)测试不适用于数组(它委托给Java equals,对于数组只测试它是否是同一个对象),因此您可能需要/需要编写自己的相等函数来测试序列化.
user> (def a (range 10))
user> (= a (range 10))
true
user> (= (into-array a) (into-array a))
false
user> (.equals (into-array a) (into-array a))
false
user> (java.util.Arrays/equals (into-array a) (into-array a))
true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3586 次 |
| 最近记录: |