如何在Clojure中将序列转换为byte []?

时间:2010-08-10 16:02:03

标签: clojure clojure-contrib

我需要将原始字节写入文件。我这样做:

(.write (FileOutputStream "/path") bytes)

...其中bytes必须是byte []类型。请注意它不能是字节[]。

我尝试用(字节)和/或(插入数组)函数转换我的序列并且感到沮丧,一个例子:

user=> (bytes (into-array (filter #(not (= % 13)) (to-byte-array (File. "e:/vpn.bat")))))
java.lang.ClassCastException: [Ljava.lang.Byte; cannot be cast to [B (NO_SOURCE_FILE:0)

续:

使用Byte / TYPE的in-array工作正常。但是,字节数组不会。该文件为空:

(import 'FileOutputStream)
(use 'clojure.contrib.io)

(defn remove-cr-from-file [file]
  (with-open [out (FileOutputStream. file)]
    (let [dirty-bytes (to-byte-array file)
          clean-seq   (filter #(not (= 13 %)) dirty-bytes)
          clean-bytes (byte-array clean-seq)]
      (.write out clean-bytes))))

3 个答案:

答案 0 :(得分:6)

还有字节数组函数。

如果需要打包字节数组,可以查看http://github.com/geoffsalmon/bytebuffer或直接使用底层的Java ByteBuffer。

答案 1 :(得分:3)

(into-array Byte/TYPE (filter #(not (= % 13)) (.getBytes (slurp "e:/vpn.bat"))))

如果您不介意将字符串作为中间人,我认为您可以将.getBytes部分替换为to-byte-array

我认为问题是(bytes)期望原始类型数组。如果你没有指定(into-array),它将返回盒装类型。

答案 2 :(得分:3)

更新:问题的新部分(“续”)将在最后回答。


只是为了说明这里实际发生了什么:

这个问题实际上说明了一个有趣的观点:数组强制转换函数 - bytesints,... - 不能也不能使用作为转换功能。它们只转换为目标类型,特别是bytes的输入必须已经是适当类型的数组。

这是有道理的,因为从int[]转换为long[]不是一个简单的问题,以不同的方式查看数字 - 您还必须为此分配不同的存储量数组 - 因此能够通过查看操作符来判断相关操作是转换还是转换是一件好事。

在Clojure等动态语言中使用强制转换的原因与效率有关(你可以使用类型提示和速度加速)和互操作(你经常需要一个恰当类型的东西)。编译器不能仅仅推断出正确的数组类型的原因是因为没有足够的信息来执行此操作(更不用说它甚至可能不清楚“正确”类型可能是什么)。

要修复相关代码段,可以使用Byte/TYPE(由Jieren建议)或跳过into-arraybytes并将filter包裹在{{而是(正如Brenton Ashworth所建议的那样)。


问题文本中新包含的代码的问题是,在读取其内容之前,它会在文件上打开bytes-array。打开FOS的行为已经清除了文件:

FileOutputStream

您必须阅读(with-open [out (FileOutputStream. some-file)] :foo) ; => :foo ; side effect: some-file is now empty 以外的文件:

with-open