JavaScript前端开发之实现二进制读写操作
关于javascript前端开发之实现二进制读写操作的相关介绍,请看以下内容详解,本文介绍的非常详细,具有参考价值。
由于种种原因,在浏览器中无法像nodejs那样操作二进制。
最近写了一个在浏览器端操作读写二进制的帮助类
!function(entrance){
"usestrict";
if("object"===typeofexports&&"undefined"!==typeofmodule){
module.exports=entrance();
}elseif("function"===typeofdefine&&define.amd){
define([],entrance());
}else{
varf;
if("undefined"!==typeofwindow){
f=window;
}else{
thrownewError('wrongexecutionenvironment');
}
f.TinyStream=entrance();
}
}(function(){
varbinaryPot={
/**
*初始化字节流,把-128至128的区间改为0-256的区间.便于计算
*@param{Array}array字节流数组
*@return{Array}转化好的字节流数组
*/
init:function(array){
for(vari=0;i<array.length;i++){
array[i]*=1;
if(array[i]<0){
array[i]+=256
}
if(array[i]>255){
thrownewError('不合法字节流')
}
}
returnarray;
},
/**
*把一段字符串按照utf8编码写到缓冲区中
*@param{String}str将要写入缓冲区的字符串
*@param{Boolean}isGetBytes是否只得到内容字节(不包括最开始的两位占位字节)
*@returns{Array}字节流
*/
writeUTF:function(str,isGetBytes){
varback=[],
byteSize=0;
for(vari=0;i<str.length;i++){
varcode=str.charCodeAt(i);
if(code>=0&&code<=127){
byteSize+=1;
back.push(code);
}elseif(code>=128&&code<=2047){
byteSize+=2;
back.push((192|(31&(code>>6))));
back.push((128|(63&code)))
}elseif(code>=2048&&code<=65535){
byteSize+=3;
back.push((224|(15&(code>>12))));
back.push((128|(63&(code>>6))));
back.push((128|(63&code)))
}
}
for(i=0;i<back.length;i++){
if(back[i]>255){
back[i]&=255
}
}
if(isGetBytes){
returnback
}
if(byteSize<=255){
return[0,byteSize].concat(back);
}else{
return[byteSize>>8,byteSize&255].concat(back);
}
},
/**
*把一串字节流按照utf8编码读取出来
*@paramarr字节流
*@returns{String}读取出来的字符串
*/
readUTF:function(arr){
if(Object.prototype.toString.call(arr)=="[objectString]"){
returnarr;
}
varUTF="",
_arr=this.init(arr);
for(vari=0;i<_arr.length;i++){
varone=_arr[i].toString(2),
v=one.match(/^1+?(?=0)/);
if(v&&one.length==8){
varbytesLength=v[0].length,
store=_arr[i].toString(2).slice(7-bytesLength);
for(varst=1;st<bytesLength;st++){
store+=_arr[st+i].toString(2).slice(2)
}
UTF+=String.fromCharCode(parseInt(store,2));
i+=bytesLength-1
}else{
UTF+=String.fromCharCode(_arr[i])
}
}
returnUTF
},
/**
*转换成Stream对象
*@paramx
*@returns{Stream}
*/
convertStream:function(x){
if(xinstanceofStream){
returnx
}else{
returnnewStream(x)
}
},
/**
*把一段字符串转为mqtt格式
*@paramstr
*@returns{*|Array}
*/
toMQttString:function(str){
returnthis.writeUTF(str)
}
};
/**
*读取指定长度的字节流到指定数组中
*@param{Stream}mStream实例
*@param{number}i读取的长度
*@param{Array}a存入的数组
*@returns{Array}存入的数组
*/
functionbaseRead(m,i,a){
vart=a?a:[];
for(varstart=0;start<i;start++){
t[start]=m.pool[m.position++]
}
returnt
}
/**
*判断浏览器是否支持ArrayBuffer
*/
varsupportArrayBuffer=(function(){
return!!window.ArrayBuffer;
})();
/**
*字节流处理实体类
*@param{String|Array}array初始化字节流,如果是字符串则按照UTF8的格式写入缓冲区
*@constructor
*/
functionStream(array){
if(!(thisinstanceofStream)){
returnnewStream(array);
}
/**
*字节流缓冲区
*@type{Array}
*/
this.pool=[];
if(Object.prototype.toString.call(array)==='[objectArray]'){
this.pool=binaryPot.init(array);
}elseif(Object.prototype.toString.call(array)=="[objectArrayBuffer]"){
vararr=newInt8Array(array);
this.pool=binaryPot.init([].slice.call(arr));
}elseif(typeofarray==='string'){
this.pool=binaryPot.writeUTF(array);
}
varself=this;
//当前流执行的起始位置
this.position=0;
//当前流写入的多少字节
this.writen=0;
//返回当前流执行的起始位置是否已经大于整个流的长度
this.check=function(){
returnself.position>=self.pool.length
};
}
/**
*强制转换为Stream对象
*@paramx
*@returns{*|Stream}
*/
Stream.parse=function(x){
returnbinaryPot.convertStream(x);
};
Stream.prototype={
/**
*从缓冲区读取4个字节的长度并转换为int值,position往后移4位
*@returns{Number}读取到的数字
*@description如果position大于等于缓冲区的长度则返回-1
*/
readInt:function(){
if(this.check()){
return-1
}
varend="";
for(vari=0;i<4;i++){
end+=this.pool[this.position++].toString(16)
}
returnparseInt(end,16);
},
/**
*从缓冲区读取1个字节,position往后移1位
*@returns{Number}
*@description如果position大于等于缓冲区的长度则返回-1
*/
readByte:function(){
if(this.check()){
return-1
}
varval=this.pool[this.position++];
if(val>255){
val&=255;
}
returnval;
},
/**
*从缓冲区读取1个字节,或读取指定长度的字节到传入的数组中,position往后移1或bytesArray.length位
*@param{Array|undefined}bytesArray
*@returns{Array|Number}
*/
read:function(bytesArray){
if(this.check()){
return-1
}
if(bytesArray){
returnbaseRead(this,bytesArray.length|0,bytesArray)
}else{
returnthis.readByte();
}
},
/**
*从缓冲区的position位置按UTF8的格式读取字符串,position往后移指定的长度
*@returns{String}读取的字符串
*/
readUTF:function(){
varbig=(this.readByte()<<8)|this.readByte();
returnbinaryPot.readUTF(this.pool.slice(this.position,this.position+=big));
},
/**
*把字节流写入缓冲区,writen往后移指定的位
*@param{Number|Array}_byte写入缓冲区的字节(流)
*@returns{Array}写入的字节流
*/
write:function(_byte){
varb=_byte;
if(Object.prototype.toString.call(b).toLowerCase()=="[objectarray]"){
[].push.apply(this.pool,b);
this.writen+=b.length;
}else{
if(+b==b){
if(b>255){
b&=255;
}
this.pool.push(b);
this.writen++
}
}
returnb
},
/**
*把参数当成char类型写入缓冲区,writen往后移2位
*@param{Number}v写入缓冲区的字节
*/
writeChar:function(v){
if(+v!=v){
thrownewError("writeChar:argumentstypeiserror")
}
this.write((v>>8)&255);
this.write(v&255);
this.writen+=2
},
/**
*把字符串按照UTF8的格式写入缓冲区,writen往后移指定的位
*@param{String}str字符串
*@return{Array}缓冲区
*/
writeUTF:function(str){
varval=binaryPot.writeUTF(str);
[].push.apply(this.pool,val);
this.writen+=val.length;
},
/**
*把缓冲区字节流的格式从0至256的区间改为-128至128的区间
*@returns{Array}转换后的字节流
*/
toComplements:function(){
var_tPool=this.pool;
for(vari=0;i<_tPool.length;i++){
if(_tPool[i]>128){
_tPool[i]-=256
}
}
return_tPool
},
/**
*获取整个缓冲区的字节
*@param{Boolean}isCom是否转换字节流区间
*@returns{Array}转换后的缓冲区
*/
getBytesArray:function(isCom){
if(isCom){
returnthis.toComplements()
}
returnthis.pool
},
/**
*把缓冲区的字节流转换为ArrayBuffer
*@returns{ArrayBuffer}
*@throw{Error}不支持ArrayBuffer
*/
toArrayBuffer:function(){
if(supportArrayBuffer){
returnnewArrayBuffer(this.getBytesArray());
}else{
thrownewError('notsupportarraybuffer');
}
},
clear:function(){
this.pool=[];
this.writen=this.position=0;
}
};
returnStream;
});
如何使用?
<scriptsrc="binary.js"></script>
<script>
varts=TinyStream('我叫张亚涛');
ts.writeUTF('你好');
console.log('获取缓冲区字节流:',ts.getBytesArray());
console.log('当前的缓冲区position为:',ts.position,'writen为:',ts.writen);
console.log('读取第一个utf8字节流:',ts.readUTF());
console.log('当前的缓冲区position为:',ts.position,'writen为:',ts.writen);
console.log('读取第二个utf8字节流:',ts.readUTF());
console.log('当前的缓冲区position为:',ts.position,'writen为:',ts.writen);
</script>
以后,我可以不用为浏览器段处理二进制而发愁了!!!希望本文分享对大家学习javascript二进制相关知识有所帮助。