为什么redis返回[239,191,189]响应缓冲区?

时间:2017-05-11 14:18:39

标签: javascript node.js redis

我使用redis存储位域数据,并在每个偏移量上设置u4值。
我需要在Nodejs服务器中获取缓冲区 对于 0-7 ,redis返回正确的缓冲区 但是当设置 8-15 值时。它会返回一个奇怪的缓冲区.Uint8Array视图进入缓冲区并显示 [239,191,189] ,表示凌乱的代码。 这是复制到运行的测试代码 btw问题ocurrs with resoponse buffer.Trying得到#0值是好的。

const http = require('http');
const url = require('url');
const fs = require('fs');
const redis = require('redis'),
      RDS_PORT = 6379,
      RDS_HOST = '139.199.33.69',//139.199.33.69
      RDS_OPTS = {detect_buffers: true},
      client = redis.createClient(RDS_PORT, RDS_HOST, RDS_OPTS);
console.log('redis ready')
const canvas_name = 'canvas-bitfield';
client.del(canvas_name)
client.send_command("bitfield",[canvas_name,'SET','u4','#0',10,'OVERFLOW','FAIL'])

client.send_command('bitfield',[canvas_name,'GET','u4',0],redis.print) //reply:10

client.get(canvas_name,function(err, reply){
    if(err){console.log(err)}
    const buff = Buffer.from(reply.toString());
    const view8 = new Uint8Array(buff); 
    console.log(view8) //Uint8Array(3) [239, 191, 189]
})

1 个答案:

答案 0 :(得分:2)

  

为什么redis返回[239,191,189]响应缓冲区?

请注意,replyString而不是Buffer为什么?您正在使用detect_buffers: true。从redis包的文档中,将此选项设置为true,reply的类型取决于传递给client.get()的第一个参数的类型。由于你传递了一个 String canvas_name是一个String),所以reply的值也是 String

client.get(canvas_name,function(err, reply){
    console.log(typeof reply) // => String
    // ...

为了实现这一点,redisinternally进行函数调用:Buffer.toString()将您的<Buffer a0>缓冲区转换为字符串,然后传递给它字符串回调;绑定到reply。问题是Buffer.toString()没有传递任何参数,将尝试使用UTF-8解码缓冲区,但<Buffer a0>不是有效的UTF-8字符串!在这种情况下,{。{3}}的Node.js返回U + FFFD REPLACEMENT CHARACTER。因此reply是一个只包含一个U + FFFD或65533字符的字符串。

client.get(canvas_name,function(err, reply){
    console.log(reply.length); // 1
    console.log(reply.charCodeAt(0)) // => 65533
    // ...

此数字(65533)来自 redis(Node.js)无法将您的缓冲区解析为UTF-8字符串!从那里,您将65533放入缓冲区并创建一个[239, 191, 189]的Uint8Array:

console.log(Buffer.from("\uFFFD")) // => <Buffer ef bf bd>
console.log(new Uint8Array(Buffer.from("\uFFFD"))); // => Uint8Array(3) [239, 191, 189] 

要快速解决问题,您需要告诉redis包不要转换 缓冲区到String。而是直接获取缓冲区:

client.get(new Buffer(canvas_name), function(err, reply) {
    console.log(typeof reply) // => Buffer
    console.log(reply) // => <Buffer a0>
    if(err){console.log(err)}
    const view8 = new Uint8Array(reply);
    console.log(view8) // => Uint8Array(3) [160]
});

注意:具有0-7范围内十进制值的缓冲区将成功解码为UTF-8字符串,这就是您巧合地获得正确缓冲区的原因。