-
Notifications
You must be signed in to change notification settings - Fork 88
输入输出——BytesIO
JavaScript 中提供了 ArrayBuffer
和 Uint8Array
等 TypedArray
可以对二进制数据进行操作。而 Node.js 中还提供了一个 Buffer
类用于二进制数据的操作。但这些对象没有自动伸缩性,不方便流式操作,相互转换也比较麻烦。
为方便操作二进制数据,hprose 提供了一个 BytesIO
对象。BytesIO
是一个可自动伸缩的,可流式读写数据的工具类。
该工具类还可以对 String
、ArrayBuffer
、Uint8Array
、Buffer
进行快速的相互转换。
new BytesIO();
new BytesIO(data);
new BytesIO(capacity);
new BytesIO(data[, byteOffset[, length]]);
不带参数的构造器创建一个空的 BytesIO
对象。空的 BytesIO
对象可以进行写操作。
带 1 个参数的构造器,其中 data
参数可以是 String
、BytesIO
、Uint8Array
、ArrayBuffer
、Buffer
、其它 TypedArray
类型的对象或是元素是纯整数且数字范围是 0-255 的普通数组。
如果参数为 1 个整数值 capacity
,则表示预分配 capacity
个字节的空间,当写入比较大量的数据时,预分配合适的空间将会有效的提高运行效率。
带 2-3 个参数的构造器,其中 data
参数为 ArrayBuffer
类型的对象,byteOffset
为起始偏移量,length
为数据长度。
BytesIO.toString(data);
该方法的功能是将 data
转换为字符串返回,data
本身不会被修改。
其中,data
参数可以为:String
、Buffer
、BytesIO
、ArrayBuffer
、Uint8Array
类型的对象或保存有 charcode 的数字数组。
如果是 String
类型的对象,则直接返回该对象。
如果是 Buffer
、BytesIO
、ArrayBuffer
、Uint8Array
类型的对象,则按照 UTF-8 编码对其中的二进制数据进行解析并返回解析后的 String
对象。
如果这些二进制数据不能按照 UTF-8
编码解析成字符串,会抛出异常。
如果是保存有 charcode 的数字数组,则按照 UTF-16 编码进行解析,并返回解析后的 String
对象。
BytesIO.toBuffer(data);
该方法的功能是将 data
转换为 Buffer
类型的对象返回,data
本身不会被修改。
其中,data
参数可以为:Buffer
、String
、BytesIO
、ArrayBuffer
、Uint8Array
类型的对象,或是元素是纯整数且数字范围是 0-255 的普通数组。
如果是 Buffer
类型的对象,则直接返回该对象。
如果是 String
类型的对象,则返回 UTF-8 编码的 Buffer
对象。
如果是 BytesIO
、ArrayBuffer
、Uint8Array
类型的对象,或是元素是纯整数且数字范围是 0-255 的普通数组,则将其中的二进制数据转换为 Buffer
对象返回。
下面我们用 bytesIO
这个变量名来指代 BytesIO
的实例对象。
bytesIO.length;
只读属性,返回当前 bytesIO
对象的长度。
bytesIO.capacity;
只读属性,返回当前 bytesIO
对象的容量,当写入数据超过该容量时,bytesIO
对象会自动扩容,capacity
的数值也会相应改变。
bytesIO.position;
只读属性,该属性表示在对 bytesIO
对象进行读取操作时的当前位置。当 position
为 0 时,表示位于数据的开头,当 position
与 length
相同时,表示已没有可读取的数据。
bytesIO.bytes;
只读属性,该属性返回 bytesIO
对象内部二进制数据的一个 Uint8Array
的共享视图。因为没有数据复制操作,所以返回该属性非常快速。注意对该属性所返回的数据进行写操作是不安全的,它会连同 bytesIO
对象内部的数据一起修改。
下面我们同样用 bytesIO
这个变量名来指代 BytesIO
的实例对象。
bytesIO.mark();
保存当前的读写位置。如果对该方法进行多次调用,则只有最后一次保存的读写位置可以被恢复。
无返回值。
bytesIO.reset();
恢复由 mark
方法保存的读写位置。
无返回值。
bytesIO.reset();
清空 bytesIO
对象,并将读写位置归零。
无返回值。
bytesIO.writeByte(byte);
往 bytesIO
对象的末尾写入一个字节。
byte 的范围是 0-255 的整数。
执行成功后,bytesIO
对象的 length
属性将会相应加 1。如果容量不足,将会自动扩容。
无返回值。
bytesIO.writeInt32BE(int32);
往 bytesIO
对象的末尾按照 BigEndian 方式写入一个32位有符号整数(4个字节)。
int32
的范围是从 -2147483648 到 2147483647,超出范围会抛出 TypeError('value is out of bounds')
的异常。
执行成功后,bytesIO
对象的 length
属性将会相应加 4。如果容量不足,将会自动扩容。
无返回值。
bytesIO.writeUInt32BE(uint32);
往 bytesIO
对象的末尾按照 BigEndian 方式写入一个32位无符号整数(4个字节)。
uint32
的范围是从 0 到 4294967295,超出范围会抛出 TypeError('value is out of bounds')
的异常。
执行成功后,bytesIO
对象的 length
属性将会相应加 4。如果容量不足,将会自动扩容。
无返回值。
bytesIO.writeInt32LE(int32);
往 bytesIO
对象的末尾按照 LittleEndian 方式写入一个32位有符号整数(4个字节)。
int32
的范围是从 -2147483648 到 2147483647,超出范围会抛出 TypeError('value is out of bounds')
的异常。
执行成功后,bytesIO
对象的 length
属性将会相应加 4。如果容量不足,将会自动扩容。
无返回值。
bytesIO.writeUInt32LE(uint32);
往 bytesIO
对象的末尾按照 LittleEndian 方式写入一个32位无符号整数(4个字节)。
uint32
的范围是从 0 到 4294967295,超出范围会抛出 TypeError('value is out of bounds')
的异常。
执行成功后,bytesIO
对象的 length
属性将会相应加 4。如果容量不足,将会自动扩容。
无返回值。
bytesIO.write(data);
往 bytesIO
对象的末尾写入二进制数据 data
。
其中 data
可以是 ArrayBuffer
、Uint8Array
、BytesIO
、Buffer
类型的对象,或元素是纯整数且数字范围是 0-255 的普通数组。
执行成功后,bytesIO
对象的 length
属性将会增加相应的长度。如果容量不足,将会自动扩容。
无返回值。
bytesIO.writeAsciiString(str);
往 bytesIO
对象的末尾写入 ASCII 编码的字符串数据 str
。
其中 str
中的每个字符的 charcode 编码范围为 0-255。
执行成功后,bytesIO
对象的 length
属性将会增加相应的长度。如果容量不足,将会自动扩容。
无返回值。
bytesIO.writeString(str);
往 bytesIO
对象的末尾按照 UTF-8 编码的方式写入字符串数据 str
。
执行成功后,bytesIO
对象的 length
属性将会增加相应的长度。如果容量不足,将会自动扩容。
无返回值。
bytesIO.readByte();
从 bytesIO
对象的当前位置读取一个字节,并返回。
执行成功后,bytesIO
对象的 position
属性将会相应加 1。
如果当前位置已在结尾,则返回 -1。
bytesIO.readInt32BE();
从 bytesIO
对象的当前位置读取 4 个字节,按照 BigEndian 编码方式转换为一个 32 位有符号整型数,并返回。
执行成功后,bytesIO
对象的 position
属性将会相应加 4。
如果当前位置到结尾不足 4 个字节,则抛出 Error('EOF')
异常。
bytesIO.readUInt32BE();
从 bytesIO
对象的当前位置读取 4 个字节,按照 BigEndian 编码方式转换为一个 32 位无符号整型数,并返回。
执行成功后,bytesIO
对象的 position
属性将会相应加 4。
如果当前位置到结尾不足 4 个字节,则抛出 Error('EOF')
异常。
bytesIO.readInt32LE();
从 bytesIO
对象的当前位置读取 4 个字节,按照 LittleEndian 编码方式转换为一个 32 位有符号整型数,并返回。
执行成功后,bytesIO
对象的 position
属性将会相应加 4。
如果当前位置到结尾不足 4 个字节,则抛出 Error('EOF')
异常。
bytesIO.readUInt32LE();
从 bytesIO
对象的当前位置读取 4 个字节,按照 LittleEndian 编码方式转换为一个 32 位无符号整型数,并返回。
执行成功后,bytesIO
对象的 position
属性将会相应加 4。
如果当前位置到结尾不足 4 个字节,则抛出 Error('EOF')
异常。
bytesIO.read(n);
从 bytesIO
对象的当前位置读取 n
个字节,并返回。返回结果是一个 Uint8Array 类型的共享视图。
执行成功后,bytesIO
对象的 position
属性将会相应加 n
。
如果当前位置到结尾不足 n
个字节,则读取全部剩余字节并返回,bytesIO
对象的 position
属性将被设置为与 length
相同。
因为返回结果是 bytesIO
对象内部数据的一部分的共享视图,因此该操作速度很快。但是对读取结果进行写操作是不安全的,它会影响 bytesIO
的内部数据。因此,如果需要对返回结果进行写操作,最好是使用 new Uint8Array(data)
来获取一个数据副本,在该副本上进行写操作,其中 data
表示返回数据。
bytesIO.skip(n);
从 bytesIO
对象的当前位置略过 n
个字节,并返回实际略过的字节数。
执行成功后,bytesIO
对象的 position
属性将会相应加 n。
如果当前位置到结尾不足 n
个字节,则略过全部剩余字节并返回略过的剩余字节数,bytesIO
对象的 position
属性将被设置为与 length
相同。
bytesIO.readBytes(tag);
从 bytesIO
对象的当前位置开始读取,直到遇到与 tag
相同的字节为止,并以 Uint8Array
类型的对象返回读取到的二进制数据。
执行成功后,bytesIO
对象的 position
属性将会相应增加读取到的字节数。
读取到的二进制数据中包含有最后的 tag
字节。
如果读取到结尾仍然没有遇到与 tag
相同的字节,则返回所有剩余的字节,bytesIO
对象的 position
属性将被设置为与 length
相同。
返回结果是 bytesIO
对象内部数据的一部分的共享视图,因此该操作速度很快。但是对读取结果进行写操作是不安全的,它会影响 bytesIO
的内部数据。因此,如果需要对返回结果进行写操作,最好是使用 new Uint8Array(data)
来获取一个数据副本,在该副本上进行写操作,其中 data
表示返回数据。
bytesIO.readUntil(tag);
从 bytesIO
对象的当前位置开始读取,直到遇到与 tag
相同的字节为止,并将读取到的二进制数据按照 UTF-8 编码解析为字符串返回。
执行成功后,bytesIO
对象的 position
属性将会相应增加读取到的字节数。
读取到的数据中不包含有最后的 tag
字节。但在位置计算上会算上 tag
字节。
如果读取到结尾仍然没有遇到与 tag
相同的字节,则所有剩余的数据按照 UTF-8 编码解析为字符串返回。bytesIO
对象的 position
属性将被设置为与 length
相同。
bytesIO.readAsciiString(n);
读取 n
个字节,并按照 ASCII 编码方式解析为字符串返回。
执行成功后,bytesIO
对象的 position
属性将会相应增加读取到的字节数。
如果当前位置到结尾不足 n
个字节,则读取全部剩余字节并按照 ASCII 编码方式解析为字符串返回,bytesIO
对象的 position
属性将被设置为与 length
相同。
bytesIO.readString(n);
读取 n
个字符,并按照 UTF-8 编码方式解析为字符串返回。这里的 n
指的是最后读取到的字符串的 length
长度,而不是读取的字节数。
执行成功后,bytesIO
对象的 position
属性将会相应增加读取到的字节数。
如果当前位置到结尾不足 n
个字符,则读取全部剩余字节并按照 UTF-8 编码方式解析为字符串返回,bytesIO
对象的 position
属性将被设置为与 length
相同。
如果读取到的二进制数据不能按照 UTF-8
编码解析成字符串,会抛出异常。
bytesIO.readStringAsBytes(n);
该功能与上面的 readString
方法类似,但是返回的结果是 UTF-8 编码的 Uint8Array
实例对象,同 readString
方法相比,因为减少了解码过程,所以该方法速度要明显快于 readString
方法。
另外要注意,本方法的返回结果是 bytesIO
对象内部数据的一部分的共享视图,因此对读取结果进行写操作是不安全的,它会影响 bytesIO
的内部数据。如果需要对返回结果进行写操作,最好是使用 new Uint8Array(data)
来获取一个数据副本,在该副本上进行写操作,其中 data
表示返回数据。
bytesIO.takeBytes();
该方法的返回值跟 bytes
属性返回值相同。区别是该方法在返回值后,bytesIO
中的数据会被清空。因此返回的数据可以安全进行写操作。
bytesIO.toBytes();
该方法的返回值是 bytes
属性返回值的副本。因此返回的数据可以安全进行写操作。但因为要创建副本,因此,速度上要比使用 bytes
属性慢一些。
bytesIO.toBuffer();
该方法返回一个 Buffer
类型的对象,其中的数据跟 bytesIO
对象中的二进制数据相同。
bytesIO.toString();
该方法将对 bytesIO
对象中的所有二进制数据按照 UTF-8 编码进行解析并返回字符串。
如果 bytesIO
对象中的二进制数据不能按照 UTF-8
编码解析成字符串,会抛出异常。
bytesIO.clone();
返回 bytesIO
对象的副本。
bytesIO.trunc();
对 bytesIO
对象中已经读取的数据部分进行截断处理,只保留未读取的数据,读取偏移量将归零,数据长度将变为剩余数据的长度。如果之前执行过 mark
方法,mark
方法保存的位置信息也会被归零。