nodejs redis 文件 二進制存取

nodejs websocket 收發二進制數據

ws模塊可以很方便的完成websocket的收發功能,npm上的說明如下:

ws is a simple to use WebSocket implementation, up-to-date against RFC-6455, and probably the fastest WebSocket library for node.js.

server端代碼:

'use strict';

var WebSocketServer = require('ws').Server
var wss    = new WebSocketServer({ port: 5505 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(data, flags) {
    console.log('flags.binary: '+flags.binary+', flags.mask: '+flags.mask);
    console.log('data:'+ typeof data);
    console.log(data);
  });
});

client端代碼;

'use strict';

var WebSocket = require('ws');
var ws = new WebSocket('ws://127.0.0.1:5505/');

ws.on('open', function open() {
  var array = new Uint8Array(4);
  array[0] = parseInt(Math.random()*0xFF);
  array[1] = parseInt(Math.random()*0xFF);
  array[2] = parseInt(Math.random()*0xFF);
  array[3] = parseInt(Math.random()*0xFF);

  console.log(array);
  ws.send(array, {binary: true, mask: true});
});

其中一次的輸出分別如下:

// client端
Uint8Array { '0': 47, '1': 2, '2': 236, '3': 92 }

// server端
flags.binary: true, flags.mask: undefined
data:object
<Buffer 2f 02 ec 5c>

注意:如果client端直接發送字符串,則server端則會自動判斷是string還是object:

// client端的代碼
  ws.send('1234');

// server端的輸出
data:string
1234

nodejs 文件 讀寫二進制數據

fs模塊是nodejs的內建模塊,使用該模塊可以方便的進行各種文件操作。官方說明如下:

File I/O is provided by simple wrappers around standard POSIX functions. To use this module do require(‘fs’). All the methods have asynchronous and synchronous forms.

其中讀寫二進制文件的代碼如下:

'use strict';

var fs   = require('fs');

var array = new Uint8Array(4);
array[0] = parseInt(Math.random()*0xFF);
array[1] = parseInt(Math.random()*0xFF);
array[2] = parseInt(Math.random()*0xFF);
array[3] = parseInt(Math.random()*0xFF);
console.log(array);

var buf = new Buffer(array);
console.log(buf);

fs.writeFile('test.bin', buf, function (err) {
  console.log('writeFile OK');
});

fs.readFile('test.bin', function (err, data) {
    console.log('readFile OK');
    console.log(data);
});

某次的輸出結果如下:

$ node fileWithBinary.js 
Uint8Array { '0': 125, '1': 98, '2': 225, '3': 250 }
<Buffer 7d 62 e1 fa>
writeFile OK
readFile OK
<Buffer 7d 62 e1 fa>
$ hexdump test.bin -C
00000000  7d 62 e1 fa                                       |}b..|
00000004

從輸出結果來看,能夠正確的寫入二進制數據到文件中,再讀取出來也是相同的數據。

nodejs redis 讀寫二進制數據

通過nodejs-redis模塊我們可以很方便的操作redis,npm上的說明如下:

This is a complete Redis client for node.js. It supports all Redis commands and focuses on performance.

redis是支持二進制數據的,通過nodejs寫入二進制數據的代碼如下:

'use strict';

var redis  = require("redis")

var client = redis.createClient();

var array = new Uint8Array(4);
array[0] = parseInt(Math.random()*0xFF);
array[1] = parseInt(Math.random()*0xFF);
array[2] = parseInt(Math.random()*0xFF);
array[3] = parseInt(Math.random()*0xFF);
console.log(array);

var buf = new Buffer(array);
console.log(buf);

client.set('test', buf, function(err, response) {
    console.log('set OK, response:' + response);
});

上面代碼的輸出以及通過redis-cli讀取的結果分別如下:

$ node redisWithBinary.js 
Uint8Array { '0': 74, '1': 245, '2': 237, '3': 116 }
<Buffer 4a f5 ed 74>
set OK, response:OK
$ redis-cli get test
"J\xf5\xedt"

注意: redis-cli對於可打印內容和不可打印的字符分別使用字符和十六進制轉義進行顯示。

使用nodejs讀取redis中的二進制數據,代碼如下:

client.get('test', function(err, res) {
    console.log('res typeof:'+ typeof res);
    console.log('res:' + res);
    var buf = new Buffer(res);
    console.log(buf);
});

輸出結果:

res typeof:string
res:J��t
<Buffer 4a ef bf bd ef bf bd 74>

問題出現了:
1. 通過get讀取出來的數據類型是string,並不是raw data
2. 將該string轉爲Buffer後,對於不認識的字符直接轉換爲ef bf bd,通過測試,在設置了encoding格式爲ascii和binary後,輸出都是,同樣是轉爲了固定的一個值fd

對於res字符串中的內容,我們可以通過下述代碼進行仔細確認:

client.get('test', function(err, res) {
    console.log('res typeof:'+ typeof res);
    console.log('res:' + res);

    for (var i =0; i < res.length; i++) {
        console.log('res.charCodeAt(i): 0x'+res.charCodeAt(i).toString(16));
    }
});

輸出結果:

res typeof:string
res:J��t
res.charCodeAt(i): 0x4a
res.charCodeAt(i): 0xfffd
res.charCodeAt(i): 0xfffd
res.charCodeAt(i): 0x74

到這裏,我們就確認了,redis本身是支持二進制的讀寫的,但是nodejs-redis在進行回調的時候已經對二進制數據進行了解碼,當遇到無法識別的字符直接轉換成了0xFFFD對應的字符,WTF。

總結

nodejs/redis在二進制的支持上還是有很多問題,目前不建議使用二進制進行存取。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章