我有一個二進制文件,其中包含X by X矩陣。文件本身是一系列單精度浮點數(小端)。我想要做的是解析它,並將其填入合理的clojure矩陣數據類型。解析一個little-endian二進制文件,填充到矩陣中
感謝this question,我看到我可以用光澤解析二進制文件。我現在看起來像這樣的代碼:
(ns foo.core
(:require gloss.core)
(:require gloss.io)
(:use [clojure.java.io])
(:use [clojure.math.numeric-tower]))
(gloss.core/defcodec mycodec
(gloss.core/repeated :float32 :prefix :none))
(def buffer (byte-array (* 1200 1200)))
(.read (input-stream "/path/to/binaryfile") buffer)
(gloss.io/decode mycodec buffer)
這需要一段時間才能運行,但最終會拋出一大串數字。不幸的是,這些數字都是錯誤的。經進一步調查,數字被視爲大端。
假設有一些方法可以將這些二進制文件作爲小端文件讀取,我想將結果填充到矩陣中。 This question似乎已經解決了使用Incanter並行Colt代表的問題,但是,這個問題是從'09,我希望堅持clojure 1.4和lein 2.在我瘋狂的谷歌搜索中,我看到了其他的建議jblas或mahout。這些天有沒有「最好」的clojure矩陣庫?
編輯:讀取二進制文件非常接近。由於這個方便nio wrapper,我能得到一個內存映射的字節緩衝區爲短的一行,甚至重新排序:
(ns foo.core
(:require [clojure.java.io :as io])
(:require [nio.core :as nio])
(:import [java.nio ByteOrder]))
(def buffer (nio/mmap "/path/to/binaryfile"))
(class buffer) ;; java.nio.DirectByteBuffer
(.order buffer java.nio.ByteOrder/LITTLE_ENDIAN)
;; #<DirectByteBuffer java.nio.DirectByteBuffer[pos=0 lim=5760000 cap=5760000]>
然而,重新排序而不做中間體(DEF)步,失敗:
(.order (nio/mmap f) java.nio.ByteOrder/LITTLE_ENDIAN)
;; clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: Unable to resolve classname: MappedByteBuffer, compiling:(/Users/peter/Developer/foo/src/foo/core.clj:12)
;; at clojure.lang.Compiler.analyzeSeq (Compiler.java:6462)
;; clojure.lang.Compiler.analyze (Compiler.java:6262)
;; etc...
我想能夠創建重新排序的字節緩衝這裏面的函數沒有定義一個全局變量,但現在它似乎不喜歡那樣。另外,一旦我把它重新排序,我不完全確定如何處理我的DirectByteBuffer,因爲它似乎不可迭代。也許對於閱讀這個緩衝區對象(進入JBLAS矩陣)的剩餘步驟,我會創建第二個問題。
編輯2:我在接受下面的答案,因爲我認爲我原來的問題結合了太多的東西。一旦我找出剩下的部分,我會嘗試用完整的代碼來更新這個問題,該代碼以這個ByteBuffer開始,並讀入JBLAS矩陣(這看起來是正確的數據結構)。
如果有人感興趣,我能夠創建一個返回正常有序的ByteBuffer如下功能:
;; This works!
(defn readf [^String file]
(.order
(.map
(.getChannel
(java.io.RandomAccessFile. file "r"))
java.nio.channels.FileChannel$MapMode/READ_ONLY 0 (* 1200 1200))
java.nio.ByteOrder/LITTLE_ENDIAN))
NIO的包裝,我發現長相簡化/美化這個相當多,但它會出現我要麼沒有正確使用它,要麼出現了問題。爲了與NIO包裝回顧一下我的發現:
;; this works
(def buffer (nio/mmap "/bin/file"))
(def buffer (.order buffer java.nio.ByteOrder/LITTLE_ENDIAN))
(def buffer (.asFloatBuffer buffer))
;; this fails
(def buffer
(.asFloatBuffer
(.order
(nio/mmap "/bin/file")
java.nio.ByteOrder/LITTLE_ENDIAN)))
可悲的是,這是另一天一個Clojure的奧祕,或者其他的StackOverflow問題。
至於以不同的順序調用它。我不知道。如果你不使用clojure nio包裝,你會得到嗎? – Bill