Clojureでシーケンスをbyte []に​​変換する方法は?

clojure clojure-contrib
Clojureでシーケンスをbyte []に​​変換する方法は?

生のバイトをファイルに書き込む必要があります。 私はそれをします:

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

…​where bytes must be of type byte[]. Please note it cannot be Byte[].

私は(バイト)および/または(配列への)関数の両方でシーケンスを変換しようとしましたが、イライラしました、1つの例:

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))))

  5  3


ベストアンサー

バイト配列関数もあります。

バイト配列をパックする必要がある場合は、http://github.com/geoffsalmon/bytebufferをチェックアウトするか、基礎となるJava ByteBufferを直接使用できます。

6


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

文字列を仲介として使用してもかまわない場合は、 .getBytes`の部分を to-byte-array`に置き換えることができると思いますが

問題は `(bytes)`がプリミティブ型の配列を期待していることだと思います。 これを `(into-array)`に指定しない場合、ボックス化された型を返します。

3


更新:質問の新しい部分(「続き」)が最後に回答されます。

” ” ‘

ここで実際に何が起こるかを明確にするために:

この質問は実際に興味深い点を示しています:配列キャスト関数bytes、` ints`、…​ –変換関数として使用することはできません。 それらはターゲットタイプにのみキャストします。つまり、特に「バイト」への入力は適切なタイプの配列でなければなりません。

これは理にかなっています。なぜなら、 `int []`から `long []`に変換することは、異なる観点から数字を見るだけの簡単な問題ではないからです-配列に異なる量のストレージを割り当てる必要があります-そのため、問題の操作が変換であるかキャストであるかを演算子で確認するだけで判断できます。

Clojureなどの動的言語でキャストが有用な理由は、効率(タイプヒントと一緒にキャストを使用して速度を上げることができます)と相互運用性(適切なタイプのものが必要な場合が多い)に関係しています。 コンパイラが正しい配列型を推測できないのは、そうするための情報が常に十分ではないためです(言うまでもなく、「正しい」型が何であるかさえ明確ではないかもしれません)。

問題のスニペットを修正するには、「Byte / TYPE」(Jierenが提案)を使用するか、「into-array」と「bytes」をスキップして、代わりに「bytes-array」に「filter」をラップします(推奨)ブレントン・アッシュワース)。

” ” ‘

質問テキストに新たに含まれるコードの問題は、その内容を読み取る前にファイルの `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)))

3


タイトルとURLをコピーしました