java - Clojure/Java 的高效二进制序列化

标签 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

动机是我有一些包含大量二进制数据(在 Java 数组中)的大型数据结构,我想避免将这些全部转换为文本并再次转换回来的开销。此外,我试图保持格式紧凑,以尽量减少网络带宽的使用。

我希望拥有的具体功能:

  • 轻量级、纯 Java 实现
  • 支持所有 Clojure 的标准数据结构以及所有 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

有些值无法序列化,例如Java 流和 Clojure 原子/代理/ future ,但它应该适用于大多数普通值,包括 Java 原语和数组以及 Clojure 函数、集合和记录。

你是否真的保存任何东西取决于。在我对序列化为文本和二进制的小型数据集的有限测试中,似乎时间和空间大致相同。

但是对于大部分数据是 Java 基元数组的特殊情况,Java 序列化可以快几个数量级并节省大量空间。 (在笔记本电脑上快速测试,100k 随机字节:序列化 0.9 毫秒,100kB;文本 490 毫秒,700kB。)

请注意,(= new-data orig-data) 测试不适用于数组(它委托(delegate)给 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

关于java - Clojure/Java 的高效二进制序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7701634/

相关文章:

clojure - 如何将 Clojure -> 宏与内部函数一起使用

java - 过滤 Java 列表并创建整型常量数组

java - Play 2.5 和 Fluentlenium : how to turn HtmlUnit warnings off

c# - 如何在 MVC4 中将 Json 字符串输出为 JsonResult?

jquery表单序列化空字符串

c# - WCF:序列化为数组的通用列表

使用 lein uberjar 构建的 Clojure 应用无法启动

scala - Vert.x - Scala 缺少什么?

java - 在 Swing 中重新定位 GridLayout

java - QueryDSL 如何创建具有自己的联接的子查询?