我有一个用C生成的二进制文件。 该文件的固定记录长度为26000双,并包含1067条没有分隔符的记录。我需要在spark中读取它并获得double值。 我还有一个Python代码,它获取双打的值,并在spark-shell中使用来自java的Files.readAllBytes我也得到了这些值,所以根据Python输出我希望第一个记录的前1000个双打有值-3509.580466022612。 取自火花壳:
import java.nio.ByteBuffer
import java.nio.ByteOrder
val doubleByteSize = 8
val recordLength = 1000 * 26 * doubleByteSize
val bytesRdd = sc.binaryRecords("file:///myBinaryFile.val", recordLength)
val arrayOfRecords = bytesRdd.collect
val firstRecord = arrayOfRecords(0)
// group 8 bytes together to transform them to doubles
val listOfDoubles = firstRecord.grouped(doubleByteSize).toList
// I get 1000 times the same double but isn't -3509.580466022612 it's 1.1848107264484659E181
val result = listOfDoubles.map(arrayOfBytes => ByteBuffer.wrap(arrayOfBytes).getDouble)
// try with little endian and it is wrong again -6.045003065652023E-27
val result2 = listOfDoubles.map(arrayOfBytes => ByteBuffer.wrap(arrayOfBytes).order(ByteOrder.LITTLE_ENDIAN).getDouble)
记录数看起来正确(arrayOfRecords.length = 1068),每条记录的字节数对我来说看起来不错(firstRecord.length = 208000),前1000个双打包含相同的值,所有内容都符合预期但是双值(1.1848107264484659E181)不是预期值(-3509.580466022612)。我试图把它改成小端,但数字仍然是错误的(-6.045003065652023E-27)。 Python代码:
def str_all(data):
ret_str = ""
for d in data:
ret_str+= " " + str(d)
return ret_str
def main():
num_sim = 1000
num_ts = 26
record_index = 0
deal_data = array('d')
with open("/myBinaryFile.val","rb") as data_file:
data_file.seek(SIZEOFDOUBLE*record_index*num_sim*num_ts)
deal_data.fromfile(data_file,num_sim*num_ts)
ts_index = 0
deal_range = slice(ts_index*num_sim,(ts_index+1)*num_sim)
# it prints 1000 times -3509.580466022612
print(str_all(deal_data[deal_range]))
读取二进制文件(来自spark-shell)的简单java代码获得预期值:
val byteArray = Files.readAllBytes(Paths.get("/mybinaryFile.val"))
// gets the correct value -3509.580466022612
ByteBuffer.wrap(byteArray).order(ByteOrder.LITTLE_ENDIAN).getDouble
任何人都知道这里发生了什么?
提前致谢。
Spark版本1.6.0,使用Scala版本2.10.5(Java HotSpot(TM)64位服务器VM,Java 1.7.0_67) Python版本2.6
答案 0 :(得分:0)
当我这样做时,问题与二进制数据本身无关:
val arrayOfRecords = bytesRdd.collect
val firstRecord = arrayOfRecords(0)
我没有订购数组,更改解决了这个问题:
val firstRecord = bytesRdd.first
看起来像collect不保留订单。感谢Archetypal Paul的时间和帮助。