5

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

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

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

我试图用 (bytes) 和/或 (into-array) 函数来转换我的序列,结果很沮丧,一个例子:

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 的 into-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))))
4

3 回答 3

6

还有字节数组功能。

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

于 2010-08-10T16:23:03.737 回答
3
(into-array Byte/TYPE (filter #(not (= % 13)) (.getBytes (slurp "e:/vpn.bat"))))

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

我认为问题在于(bytes)需要原始类型数组。如果你不指定这个(into-array),它会返回装箱的类型。

于 2010-08-10T17:11:46.617 回答
3

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


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

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

这是有道理的,因为从int[]to转换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

您必须从以下文件中读取with-open

(let [foo (byte-array
           (filter #(not= 13 %)
                   (to-byte-array some-file)))]
  (with-open [out (FileOutputStream. some-file)]
    (.write out foo)))
于 2010-08-10T17:34:52.160 回答