我有一个函数试图将从JVM上可用的currentTimeMillis
方法获得的时间(以毫秒为单位)转换为带符号字节的向量。它在大多数情况下看起来很好,除了一个小问题 - 在达到前8位的最大字节值后,并不总是正确地增加第n个字节位置。这是一个示例字节序列:
[0 0 1 69 74 87 123 56]
[0 0 1 69 74 87 123 56]
[0 0 1 69 74 87 123 56]
[0 0 1 69 74 87 123 56]
[0 0 1 69 74 87 123 57]
[0 0 1 69 74 87 123 57]
[0 0 1 69 74 87 123 57]
[0 0 1 69 74 87 123 57]
[0 0 1 69 74 87 123 57]
[0 0 1 69 74 87 123 57]
[0 0 1 69 74 87 1 64]
[0 0 1 69 74 87 1 64]
[0 0 1 69 74 87 1 64]
[0 0 1 69 74 87 1 64]
[0 0 1 69 74 87 1 65]
[0 0 1 69 74 87 1 65]
[0 0 1 69 74 87 1 65]
[0 0 1 69 74 87 1 65]
[0 0 1 69 74 87 1 65]
[0 0 1 69 74 87 1 66]
[0 0 1 69 74 87 1 66]
糟糕。正如您所看到的,右边的第六个字节没有增加到88.这似乎并不是一直发生 - 有时它会正确地增加字节。这将是一个问题,因为我将此值发送到服务器,该服务器要求将时间间隔作为必须不断递增的字节值序列。
以下是我用来生成此代码的代码:
(def max-signed-bytes 128)
(defn byte-at
"Shifts x by a given number of bits"
[x offset]
(mod (bit-shift-right x offset) max-signed-bytes))
(defn Long->bytes
"Convert a 64-bit integer into a byte vector"
[^Long x]
(conj []
(byte-at x 56)
(byte-at x 48)
(byte-at x 40)
(byte-at x 32)
(byte-at x 24)
(byte-at x 16)
(byte-at x 8)
(mod x max-signed-bytes)))
(defn time->bytes
"Returns the current time in milliseconds as a byte vector"
[]
(Long->bytes (System/currentTimeMillis)))
我尝试使用256对无符号字节值进行修改,但它似乎不会遇到此问题。但是,我需要一个带符号的字节值才能将内容填充到字节数组中,因为我最终需要使用DataOutputStream
的{{1}}方法编写一个字节数组。
答案 0 :(得分:3)
从long获取字节数组的最简单方法可能是
(defn num->bytes [n] (.toByteArray (biginteger n)))
但是,由于您的修改指定您使用的是DataOutputStream
,因此请直接使用writeLong method。
so.core=>(def buffer (java.io.ByteArrayOutputStream.))
#'so.core/buffer
so.core=> (def data-stream (java.io.DataOutputStream. buffer))
#'so.core/data-stream
so.core=> (.writeLong data-stream 257)
nil
so.core=> (.toByteArray buffer)
#<byte[] [B@6ea4b78b>
so.core=> (vec *1)
[0 0 0 0 0 0 1 1]
您的代码问题与您在编辑中诊断出的一样。您需要模数超过可能的字节值数256,而不是最大有符号值128.否则,您将两个字节值映射到相同的数字(= (mod 127 128) (mod -1 128)) ;=> true
。转换为字节将签名(.byteValue (mod 255 256)) ;=> -1
。