gpt4 book ai didi

clojure - 如何在 Clojure 中处理大型二进制数据?

转载 作者:行者123 更新时间:2023-12-04 15:04:36 24 4
gpt4 key购买 nike

如何在 Clojure 中处理大型二进制数据文件?让我们假设数据/文件大约 50MB - 小到可以在内存中处理(但不是简单的实现)。

下面的代码正确地从小文件中删除了 ^M 但它抛出了 OutOfMemoryError对于较大的文件(如 6MB):

(defn read-bin-file [file]
(to-byte-array (as-file file)))

(defn remove-cr-from-file [file]
(let [dirty-bytes (read-bin-file file)
clean-bytes (filter #(not (= 13 %)) dirty-bytes)
changed? (< (count clean-bytes) (alength dirty-bytes))] ; OutOfMemoryError
(if changed?
(write-bin-file file clean-bytes)))) ; writing works fine

看来 Java 字节数组不能被视为 seq 因为它非常低效。

另一方面,使用 aset 的解决方案, agetareduce臃肿、丑陋和命令式,因为你不能真正使用 Clojure 序列库。

我错过了什么? 如何在 Clojure 中处理大型二进制数据文件?

最佳答案

我个人可能会在这里使用 aget/aset/areduce - 它们可能是必不可少的,但在处理数组时它们是有用的工具,而且我不觉得它们特别难看。如果您想将它们包装在一个不错的函数中,那么您当然可以:-)

如果您决定使用序列,那么您的问题将出在 seq 的构造和遍历中,因为这将需要为数组中的每个字节创建和存储一个新的 seq 对象。对于每个数组字节,这可能是 ~24 个字节......

所以诀窍是让它懒惰地工作,在这种情况下,较早的对象将在到达数组末尾之前被垃圾收集。但是,要使这项工作起作用,您必须避免在遍历序列时(例如使用计数)持有对 seq 头部的任何引用。

以下可能有效(未经测试),但将取决于以惰性友好方式实现的 write-bin-file:

(defn remove-cr-from-file [file]
(let [dirty-bytes (read-bin-file file)
clean-bytes (filter #(not (= 13 %)) dirty-bytes)
changed-bytes (count (filter #(not (= 13 %)) dirty-bytes))
changed? (< changed-bytes (alength dirty-bytes))]
(if changed?
(write-bin-file file clean-bytes))))

请注意,这与您的代码基本相同,但构造了一个单独的惰性序列来计算更改的字节数。

关于clojure - 如何在 Clojure 中处理大型二进制数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3538834/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com