【发布时间】:2015-02-11 02:23:58
【问题描述】:
我想将 BSON 文件解码为 Clojure 映射。
这是我的代码:
(ns decode
(:require [clojure.java.io :as cji])
(:import [org.bson BasicBSONObject BasicBSONEncoder BasicBSONDecoder]))
(defonce encoder (BasicBSONEncoder.))
(defonce decoder (BasicBSONDecoder.))
(defn read-file [file-path]
(with-open [reader (cji/input-stream file-path)]
(let [length (.length (clojure.java.io/file file-path))
buffer (byte-array length)]
(.read reader buffer 0 length)
buffer)))
(defn bson2map [^Byte b]
(->> (.readObject decoder b) (.toMap) (into {})))
(defn read-bson
[path]
(clojure.walk/keywordize-keys (bson2map (read-file path))))
但是当我解码像 (r/read-bson "test.bson") 这样的 BSON 文件时,它只解码第一条记录,我想解码所有记录。 test.bson 太大了。如何分片解码?
然后我找到了一个名为LazyBSONDecoder的类,写了一些java代码,它可以工作,它可以解码所有记录。
import org.bson.LazyBSONDecoder;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Main {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream("./_Installation.bson");
LazyBSONDecoder decoder = new LazyBSONDecoder();
Object obj;
int count = 0;
try {
do {
obj = decoder.readObject(in);
System.out.println(obj);
count++;
} while (obj != null);
} catch (Exception e) {
// ignore
}
System.out.println(count);
}
}
所以我更改了 Clojure 代码,将 BasicBSONDecoder 替换为 LazyBSONDecoder,但它总是只解码第一条记录。
(defonce decoder (LazyBSONDecoder.))
(defn bson2map [^Byte b]
(do (print (.readObject decoder b))
(print (.readObject decoder b))
(print (.readObject decoder b))))
【问题讨论】:
-
Java 版本有一个
do/while循环,而您的Clojure 版本只调用一次readObject方法。 -
@myguidingstar 在最后一个示例中,有三个对
.readObject的调用,但根据 OP,所有这些调用都会返回第一条记录。 -
@ipaomian 能否提供一个示例 BSON 文件来检查问题所在?
-
@tolitius @juan.facoorro 谢谢你给我一些建议,我已经解决了问题,函数
bson2map参数应该是一个inputStream但没有字节数组。LazyBSONDecoder