Node.js + MongoDB + AngularJS - 5 在Node.js中处理数据I0-1

本章的重点是操纵JSON数据、管理二进制数据缓冲区,并实现可读取和可写入输入流及数据压缩/解压缩。

1. 处理JSON

实现Node.js Web应用程序和服务时你将最常使用的一种数据类型JSON(JavaScript Object Notation, Javascript对象符号)。JSON是一个非常轻量级的方法,它用来把Javascript对象和字符串的形式进行互相转换。当你需要序列化数据对象,以便将它们从客户端传递到服务器,从一个进程传递到另一个进程,从一个流传递到另一个流,或当你要将它们存储在数据库中时,使用JSON的效果很好。
相比XML的几个有点:
- JSON更高效,需要更少的字符
- 序列化/反序列化JSON要比序列化/反序列化XML快
- 从开发人员的角度来看,JSON更容易阅读,因为它的语法类似于Javascript

1.1 把JSON转换成Javascript对象

JSON.parse(string)
var accountStr = '{"name": "Jedi", "members": ["Yoda", "Obi Wan"], "number": 34512, "location": "A galaxy ' +
    'far, far away"}' ;
var accountObj = JSON.parse( accountStr ) ;

console.log( accountObj.name ) ;
console.log( accountObj.members ) ;

1.2 把Javascript对象转换为JSON

JSON.stringify()
var accountObj = {
    name: 'Baggins',
    number: 10645,
    members: ['Frodo, Bilbo'],
    location: 'Shire'
} ;

var accountStr = JSON.stringify( accountObj ) ;

console.log( accountStr ) ;

2. 使用Buffer模块缓冲数据

虽然Javascript可能是对Unicode是友好的,但是它不很擅长管理二进制数据。然而,在实施一些Web应用程序和服务时,二进制数据是非常有用的。
- 传输压缩文件
- 生成动态图像
- 发送序列化的二进制数据

2.1 了解缓冲数据

缓冲数据是由一系列的大端或小端格式字节组成的。这意味着它们比文本数据占用比较少的空间。
Node.js提供Buffer模块,它允许你在缓冲去结构中创建、读取、写入和操作二进制数据。Buffer模块是全局性的,所以不需要require()函数来访问它。
缓存数据被存储在正常V8堆之外的原始内存分配区中,因此,缓冲区不能调整大小。
缓冲区与字符串进行互相转换时,需要指定要使用的明确的编码方法。

方法 说明
utf8 多字节编码的Unicode字符,是大多数文档和网页中的标砖
utf16le 2个或4个字节小端编码的Unicode字符
usc2 2个或4个字节小端编码的Unicode字符
base64 Base-64字符串编码
Hex 每个字节编码为两个十六进制字符

2.2 创建缓冲区

Buffer对象实际上是原始的内存分配区。因此,你必须在创建时确定其大小。
使用new关键字创建Buffer对象有3中方法:

new Buffer(sizeInBytes)
new Buffer(octetArray)
new Buffer(string, [encoding])
var buf256 = new Buffer(256) ;
var bufOctet8 = new Buffer([0x6f, 0x63, 0x74, 0x65, 0x74, 0x73]) ;
var bufUTF8 = new Buffer('Some UTF8 Text \u00b6 \u30c6 \u20ac', 'utf8') ;

2.3 写入缓冲区

Buffer对象已经创建后,你不能扩展其大小,但可以把数据写到缓冲区中的任何位置。

方法 说明
buffer.write(string, [offset], [length], [encoding]) 使用encoding的编码从缓冲区内的offset(偏移量)索引开始。写入string中length数量的字节
buffer[offset] = value 将索引offset处的数据替换为指定的value
buffer.fill(value, [offset], [end]) 将value写到缓冲区中从offset索引处开始,并在end索引处结束的每一个字节
buf256 = new Buffer( 256 ) ;

buf256.fill( 0 ) ;
buf256.write( 'add some text' ) ;

console.log( buf256.toString() ) ;

buf256.write( 'more text', 9, 9 ) ;

console.log( buf256.toString() ) ;

buf256[ 18 ] = 43 ;

console.log( buf256.toString() ) ;

2.4 从缓冲区读取

方法 说明
buffer.toString([encoding], [start], [end]) 返回一个字符串,它包含了从缓冲区的start索引到end索引的字符,由encoding指定的编码解码。如果没有指定start或end,则toString()使用缓冲区的开始或结束
stringDecoder.write(buffer) 返回缓冲区的解码字符串版本
buffer[offset] 返回缓冲区在指定的offset字节的八进制值
var bufUTF8 = new Buffer('Some UTF8 Text \u00b6 \u30c6 \u20ac', 'utf8') ;
console.log(bufUTF8.toString()) ;
console.log(bufUTF8.toString('utf8', 5, 9)) ;
var StringDecoder = require('string_decoder').StringDecoder ;
var decoder = new StringDecoder('utf8') ;
console.log(decoder.write(bufUTF8)) ;
console.log(bufUTF8[18].toString(16)) ;
console.log(bufUTF8.readUInt32BE(18).toString(16)) ;

2.5 确定缓冲区长度

  • 在Buffer对象上调用.length来确定缓冲区的长度
  • 字符串在缓冲区中占用的字节长度,用Buffeer.byteLength(string, [encoding])
  • 缓冲区中字符串长度和字节长度之间的区别很重要
console.log('UTF8 text \u00b6'.length) ;
// 11
console.log(Buffer.byteLength('UTF8 text \u00b6', 'utf8')) ;
// 12
console.log(Buffer('UTF8 text \u00b6').length) ;
// 12

2.6 复制缓冲区

copy(targetBuffer, [targetStart], [sourceStart], [sourceIndex])

注意:若要从一个缓冲区复制字符串数据到另一个缓冲区,应确保两个缓冲区使用相同的编码。

/**
 * Created by 23782 on 2016/4/26.
 */
var alphabet = new Buffer('abcdefghigklmnopqrstuvwxyz') ;
console.log(alphabet.toString()) ;
// copy full buffer
var blank = new Buffer(26) ;
blank.fill() ;
console.log('Blank: ' + blank.toString()) ;
alphabet.copy(blank) ;
console.log('Blank: ' + blank.toString()) ;
// copy part of buffer
var dashes = new Buffer(26) ;
dashes.fill('-') ;
console.log('Dashes: ' + dashes.toString()) ;
alphabet.copy(dashes, 10, 10, 15) ;
console.log('Dashes: ' + dashes.toString()) ;
// copy to and from direct indexes of buffers
var dots = new Buffer('----------------------------') ;
dots.fill('.') ;
console.log('dots: ' + dots.toString()) ;
for(var i = 0; i < dots.length; i++) {
    if (i % 2) dots[i] = alphabet[i] ;
}
console.log('dots: ' + dots.toString()) ;

2.7 对缓冲区切块

处理缓冲区的另一个重要方面是将它们分成切片的功能。
切片(slice):是缓冲区的开始索引和结束索引之间的部分。对缓冲区切片可以让你操作一个特定的块。

slice([start], [end])

返回一个Buffer对象,其指向原缓冲区的start索引,并具有end - start的长度。
注意:切片和副本不同,如果你编辑一个副本,原来的缓冲区并没有改变。但是,如果你编辑一个切片,则原来的缓冲区确实会改变。

var numbers = new Buffer('123456789') ;
console.log(numbers.toString()) ;
var slice = numbers.slice(3, 6) ;
console.log(slice.toString()) ;
slice[0] = '#'.charCodeAt(0) ;
slice[slice.length - 1] = '#'.charCodeAt(0) ;
console.log(slice.toString()) ;
console.log(numbers.toString()) ;

2.8 拼接缓冲区

把两个或多个buffer对象拼接在一起,形成一个新的缓冲区。

concat(list, [totalLength])

该方法接受buffer对象的数组作为第一个参数,并把定义缓冲区最大字节数的totalLength作为可选的第二个参数。
如果不提供totalLength参数,cancat()就为你计算出总长度。这样选哦遍历列表,所以提供totalLength值执行的更快一点。

var af = new Buffer('African Swallow?') ;
var eu = new Buffer('European Swallow?') ;
var question = new Buffer('Air Speed Velocity of an ') ;
console.log(Buffer.concat([question, af]).toString()) ;
console.log(Buffer.concat([question, eu]).toString()) ;
原创文章 27 获赞 18 访问量 3万+

猜你喜欢

转载自blog.csdn.net/b635781894/article/details/51251924