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对象


1
2
1JSON.parse(string)
2

1
2
3
4
5
6
7
1var accountStr = '{"name": "Jedi", "members": ["Yoda", "Obi Wan"], "number": 34512, "location": "A galaxy ' +
2    'far, far away"}' ;
3var accountObj = JSON.parse( accountStr ) ;
4
5console.log( accountObj.name ) ;
6console.log( accountObj.members ) ;
7

1.2 把Javascript对象转换为JSON


1
2
1JSON.stringify()
2

1
2
3
4
5
6
7
8
9
10
11
1var accountObj = {
2    name: 'Baggins',
3    number: 10645,
4    members: ['Frodo, Bilbo'],
5    location: 'Shire'
6} ;
7
8var accountStr = JSON.stringify( accountObj ) ;
9
10console.log( accountStr ) ;
11

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中方法:


1
2
3
4
1new Buffer(sizeInBytes)
2new Buffer(octetArray)
3new Buffer(string, [encoding])
4

1
2
3
4
1var buf256 = new Buffer(256) ;
2var bufOctet8 = new Buffer([0x6f, 0x63, 0x74, 0x65, 0x74, 0x73]) ;
3var bufUTF8 = new Buffer('Some UTF8 Text \u00b6 \u30c6 \u20ac', 'utf8') ;
4

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索引处结束的每一个字节


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1buf256 = new Buffer( 256 ) ;
2
3buf256.fill( 0 ) ;
4buf256.write( 'add some text' ) ;
5
6console.log( buf256.toString() ) ;
7
8buf256.write( 'more text', 9, 9 ) ;
9
10console.log( buf256.toString() ) ;
11
12buf256[ 18 ] = 43 ;
13
14console.log( buf256.toString() ) ;
15
16

2.4 从缓冲区读取

buffer.toString([encoding], [start], [end])
返回一个字符串,它包含了从缓冲区的start索引到end索引的字符,由encoding指定的编码解码。如果没有指定start或end,则toString()使用缓冲区的开始或结束
stringDecoder.write(buffer)
返回缓冲区的解码字符串版本
buffer[offset]
返回缓冲区在指定的offset字节的八进制值


1
2
3
4
5
6
7
8
9
1var bufUTF8 = new Buffer('Some UTF8 Text \u00b6 \u30c6 \u20ac', 'utf8') ;
2console.log(bufUTF8.toString()) ;
3console.log(bufUTF8.toString('utf8', 5, 9)) ;
4var StringDecoder = require('string_decoder').StringDecoder ;
5var decoder = new StringDecoder('utf8') ;
6console.log(decoder.write(bufUTF8)) ;
7console.log(bufUTF8[18].toString(16)) ;
8console.log(bufUTF8.readUInt32BE(18).toString(16)) ;
9

2.5 确定缓冲区长度

  • 在Buffer对象上调用.length来确定缓冲区的长度

  • 字符串在缓冲区中占用的字节长度,用Buffeer.byteLength(string, [encoding])

  • 缓冲区中字符串长度和字节长度之间的区别很重要


1
2
3
4
5
6
7
1console.log('UTF8 text \u00b6'.length) ;
2// 11
3console.log(Buffer.byteLength('UTF8 text \u00b6', 'utf8')) ;
4// 12
5console.log(Buffer('UTF8 text \u00b6').length) ;
6// 12
7

2.6 复制缓冲区


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

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1/**
2 * Created by 23782 on 2016/4/26.
3 */
4var alphabet = new Buffer('abcdefghigklmnopqrstuvwxyz') ;
5console.log(alphabet.toString()) ;
6// copy full buffer
7var blank = new Buffer(26) ;
8blank.fill() ;
9console.log('Blank: ' + blank.toString()) ;
10alphabet.copy(blank) ;
11console.log('Blank: ' + blank.toString()) ;
12// copy part of buffer
13var dashes = new Buffer(26) ;
14dashes.fill('-') ;
15console.log('Dashes: ' + dashes.toString()) ;
16alphabet.copy(dashes, 10, 10, 15) ;
17console.log('Dashes: ' + dashes.toString()) ;
18// copy to and from direct indexes of buffers
19var dots = new Buffer('----------------------------') ;
20dots.fill('.') ;
21console.log('dots: ' + dots.toString()) ;
22for(var i = 0; i < dots.length; i++) {
23    if (i % 2) dots[i] = alphabet[i] ;
24}
25console.log('dots: ' + dots.toString()) ;
26

2.7 对缓冲区切块

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


1
2
1slice([start], [end])
2

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


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

2.8 拼接缓冲区

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


1
2
1concat(list, [totalLength])
2

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


1
2
3
4
5
6
1var af = new Buffer('African Swallow?') ;
2var eu = new Buffer('European Swallow?') ;
3var question = new Buffer('Air Speed Velocity of an ') ;
4console.log(Buffer.concat([question, af]).toString()) ;
5console.log(Buffer.concat([question, eu]).toString()) ;
6

给TA打赏
共{{data.count}}人
人已打赏
安全技术

AES 加密解密 (javascript, java,php,c#)

2021-8-18 16:36:11

安全技术

C++ 高性能服务器网络框架设计细节

2022-1-11 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索