在R中,我试图将二进制数据转换为整数值,但不是将1个值存储在1个字节中,而是在字节内和跨字节存储多个值。
我知道在64位(8字节)中存储了12个整数值。 12个整数具有以下位数:5,6,5,5,4,7,5,6,5,5,4,7 在以下代码之后:
time <- readBin(fid,integer(),size=1,n=8,signed='FALSE')
回报是:
[1] 25 156 113 63 214 158 113 63
正确的数据应该是:
25 32 19 17 11 31 22 54 19 17 11 31
我尝试过使用bitAnd和bitShiftL(包bitops),但没有取得真正的成功。非常感谢帮助。
答案 0 :(得分:2)
请注意,对每个4字节整数的操作是相同的(模式重复两次)。因此,足以解决4字节整数的问题,并循环文件中的4字节整数(通过readBin
检索)。这比逐字节考虑问题简单得多。
# length(x) should be 1
bitint <- function(x, bitlens) {
result <- integer(length(bitlens))
for (i in seq_along(bitlens)) {
result[i] <- bitwAnd(x, (2^bitlens[i])-1)
x <- bitwShiftR(x, bitlens[i])
}
return(result)
}
bitlens <- c(5,6,5,5,4,7)
x <- c(1064410137L, 1064410838L)
c(sapply(x, function(i) bitint(i, bitlens)))
## [1] 25 32 19 17 11 31 22 54 19 17 11 31
答案 1 :(得分:1)
我不知道使用标准数据读取基本函数执行此操作的干净优雅方式(像redBin
这样的函数似乎一次不少于一个字节)。所以我创建了一个函数来执行一些混乱的计算,从字节中提取位并将它们转换为数字。我最终使用了基数R中的按位运算符(参见?bitwAnd
)这里的函数
bitints <- function(bytes, bitlengths) {
stopifnot(sum(bitlengths) <= 8*length(bytes))
stopifnot(all(bitlengths <= 8))
bytebits <- rep.int(8, length(bytes))
masks <- c(1L,3L,7L,15L,31L,63L,127L, 255L)
outs <- numeric(length(bitlengths))
for(i in seq_along(bitlengths)) {
need <- bitlengths[i]
got <- 0
r <- 0
while(need>0) {
j <- which(bytebits>0)[1]
bitget <- min(need, bytebits[j])
r <- r + bitwShiftL(bitwAnd(bytes[j],masks[bitget]), got)
bytebits[j] = bytebits[j]-bitget
bytes[j] = bitwShiftR(bytes[j], bitget)
need <- need - bitget
got <- got + bitget
}
outs[i] <- r
}
outs
}
您只需传入字节值数组和位数组,即可获得所需的值。以下是使用您的数据的示例。
bytes <- c(25L, 156L, 113L, 63L, 214L, 158L, 113L, 63L)
bitlens <- c(5,6,5,5,4,7,5,6,5,5,4,7)
bitints( bytes, c(5,6,5,5,4,7,5,6,5,5,4,7) )
# [1] 25 32 19 17 11 31 22 54 19 17 11 31
请注意,我必须更改一些位长才能获得您期望的值。您可能需要仔细检查您是否具有正确的预期输出或者您的位长度是否正确。