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

qer*_*oip 5 clojure clojure-contrib

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

(.write (FileOutputStream "/path") bytes)
Run Code Online (Sandbox Code Playgroud)

...其中bytes必须是byte []类型.请注意它不能是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)
Run Code Online (Sandbox Code Playgroud)

继续:

带字节/ 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))))
Run Code Online (Sandbox Code Playgroud)

小智 6

还有字节数组函数.

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


Mic*_*zyk 3

更新:问题的新部分(“继续”)在最后得到了回答。


只是为了弄清楚这里实际发生了什么:

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

这是有道理的,因为从int[]到 的转换long[]并不是从不同角度查看数字的简单问题 - 您还必须为数组分配不同的存储量 - 因此只需查看运算符所讨论的操作是转换还是强制转换是一件好事。

强制转换在 Clojure 等动态语言中有用的原因与效率(您可以将强制转换与类型提示一起使用来加快速度)和互操作(您通常需要正确类型的东西)有关。编译器不能仅仅推断出正确的数组类型的原因是因为并不总是有足够的信息来这样做(更不用说甚至可能不清楚“正确”的类型可能是什么)。

要修复有问题的代码片段,可以使用其中之一Byte/TYPE(按照 Jieren 的建议)或跳过into-arrayandbytes并将其换filterbytes-array(按照 Brenton Ashworth 的建议)。


问题文本中新包含的代码的问题在于,它在FileOutputStream读取文件内容之前打开了文件。打开 FOS 的行为已经清除了文件:

(with-open [out (FileOutputStream. some-file)]
  :foo)

; => :foo
; side effect: some-file is now empty
Run Code Online (Sandbox Code Playgroud)

您必须从以下位置之外的文件中读取with-open

(let [foo (byte-array
           (filter #(not= 13 %)
                   (to-byte-array some-file)))]
  (with-open [out (FileOutputStream. some-file)]
    (.write out foo)))
Run Code Online (Sandbox Code Playgroud)