如何在 Clojure 中将序列转换为 byte[]?
我需要将原始字节写入文件。我这样做的是:
(.write (FileOutputStream "/path") 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)
继续:
带有 Byte/TYPE 的到数组工作正常。然而,字节数组却没有。文件变空:
(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))))
I need to write raw bytes to the file. I do it with:
(.write (FileOutputStream "/path") bytes)
...where bytes must be of type byte[]. Please note it cannot be Byte[].
I tried to convert my sequence with both (bytes) and/or (into-array) functions and got frustrated, one example:
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)
CONTINUED:
The into-array with Byte/TYPE works fine. However, the byte-array does not. The file gets empty:
(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))))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
还有字节数组函数。
如果需要打包字节数组,您可以查看 http://github.com/geoffsalmon/bytebuffer 或者直接使用底层的 Java ByteBuffer 东西。
There is also the byte-array function.
If need to get into packing the byte array you can check out http://github.com/geoffsalmon/bytebuffer or use the underlying Java ByteBuffer stuff directly.
更新:问题的新部分(“继续”)在最后得到了回答。
只是为了弄清楚这里实际发生了什么:
这个问题实际上说明了一个有趣的点:数组转换函数 --
字节
、整数
、... -- 不是也不能用作转换函数。它们仅转换为目标类型,这特别意味着bytes
的输入必须已经是适当类型的数组。这是有道理的,因为从
int[]
转换为long[]
并不是从不同角度查看数字的简单问题 - 您还必须分配数组的存储量不同——因此,只需查看运算符即可判断所讨论的操作是转换还是强制转换,这是一件好事。强制转换在 Clojure 等动态语言中有用的原因与效率(您可以将强制转换与类型提示一起使用来加快速度)和互操作(您通常需要正确类型的东西)有关。编译器不能仅仅推断出正确的数组类型的原因是因为并不总是有足够的信息来这样做(更不用说甚至可能不清楚“正确”的类型可能是什么)。
要修复有问题的代码片段,可以使用
Byte/TYPE
(如 Jieren 建议的那样)或跳过into-array
和bytes
和将filter
包装在bytes-array
中(按照 Brenton Ashworth 的建议)。问题文本中新包含的代码的问题在于,它在读取文件内容之前在文件上打开一个
FileOutputStream
。打开 FOS 的行为已经清除了文件:您必须从
with-open
之外的文件中读取:Update: the new part of the question ("CONTINUED") is answered towards the end.
Just to make it clear what actually happens here:
This question actually illustrates an interesting point: the array cast functions --
bytes
,ints
, ... -- are not and cannot be used as conversion functions. They only cast to the target type, meaning in particular that the input tobytes
must already be an array of appropriate type.This makes sense, since converting from
int[]
tolong[]
is not a simple matter of viewing the numbers in a different light -- you'd also have to allocate a different amount of storage for the array -- so being able to tell just by looking at the operator whether the operation in question is a conversion or a cast is a Good Thing.The reason why casts are useful in a dynamic language such as Clojure has to do with efficiency (you can use casting alongside type hints to speed things up) and interop (where you often need a thing of just the right type). The reason why the compiler can't just infer the correct array type is because there is not always enough information to do so (not to mention it might not even be clear what the "correct" type might be).
To fix the snippet in question, one could use either
Byte/TYPE
(as suggested by Jieren) or skip theinto-array
andbytes
and wrap thefilter
inbytes-array
instead (as suggested by Brenton Ashworth).The problem with the code newly included in the question text is that it opens a
FileOutputStream
on the file prior to reading its contents. The act of opening the FOS already clears the file:You'll have to read from the file outside the
with-open
:如果您不介意使用字符串作为中介,尽管我认为您可以将
.getBytes
部分替换为to-byte-array
我认为问题在于
(bytes)
需要原始类型数组。如果您没有将其指定为(into-array)
,它将返回装箱类型。If you don't mind having a string as an intermediary, although I think you can replace the
.getBytes
part with yourto-byte-array
I think the problem is that
(bytes)
expects the primitive type array. If you don't specify this to(into-array)
, it's going to return the boxed type.