JS 整数 转 4个长度的 bety[]数组

JavaScript013

JS 整数 转 4个长度的 bety[]数组,第1张

function numToByte(num) {  

        var bytes = new Array()  

        var len, c  

        var str = String(num)

        len = str.length  

        for(var i = 0 i < len i++) {  

            c = str.charCodeAt(i)  

            if(c >= 0x010000 && c <= 0x10FFFF) {  

                bytes.push(((c >> 18) & 0x07) | 0xF0)  

                bytes.push(((c >> 12) & 0x3F) | 0x80)  

                bytes.push(((c >> 6) & 0x3F) | 0x80)  

                bytes.push((c & 0x3F) | 0x80)  

            } else if(c >= 0x000800 && c <= 0x00FFFF) {  

                bytes.push(((c >> 12) & 0x0F) | 0xE0)  

                bytes.push(((c >> 6) & 0x3F) | 0x80)  

                bytes.push((c & 0x3F) | 0x80)  

            } else if(c >= 0x000080 && c <= 0x0007FF) {  

                bytes.push(((c >> 6) & 0x1F) | 0xC0)  

                bytes.push((c & 0x3F) | 0x80)  

            } else {  

                bytes.push(c & 0xFF)  

            }  

        }  

        return bytes  

    }

    

var bytes = numToByte(12)

console.log(bytes)

TCP/IP开发中,出现需要自己编码的情况,这种情况需要将变量拓展为自己需要的byte[]表现形式。

假设我们需要编码格式如下:

1111 1111 ... 1111 1111 1111 1111 ...

第一个8位,表示文件名的长度,紧接着是文件名,然后用一个32位表示文件的长度,最后是文件数据。

这里用js中的Int8Array完成编码。Int8Array是一种TypedArray,本质上是一个数组,特点是每个元素的长度为8位(一个byte)。

假设filenameArr为文件名数组,fileArr为文件数组:

那么可以想到,4个字节的数组在java中相当于一个int,它可以表示的最大值就是2,147,483,647。我们这里就需要手动计算每个字节的值,不足32位的,需要将高位全部置成0。

采取的方法是从高到低,每次计算8位,然后放入数组

fileLengthArr[0] = fileArr.length >>24 &0xFF

这里的计算方式是先把要放入的值右移24位,再截取后8位,得到其高8位的值,比如文件长度是1,895,825,407个字节,那么其二进制表示就是

01110000111111111111111111111111

右移24位得到

0000 0000 0000 0000 0000 0000 1000 1111

跟0xFF,也就是1111 1111 做与运算,就得到

1000 1111

再比如文件长度是16,777,215个字节,那么其二进制表示就是

1111 1111 1111 1111 1111 1111

只用了24位就表示完了,那么右移24位,我们会得到

0000 0000 0000 0000 0000 0000 0000 0000

做与运算,得到

0000 0000

可以看到符合我们的需求,也就是不足32位的,高位用0补齐。

依次类推,依次计算每个8位的值:

再把这个数组拼接到结果中:

result = result.concat(fileLengthArr).concat(fileArr)

如果要用WebSocket传输,那么要将这个array转换成ArrayBuffer:

var resultBuffer =new Int8Array(result).buffer

用上面的例子,如果文件名长度是255,文件长度是65535,那么result应该是这样的:

[255, ...(255个元素)...0,0,255,255,...(65535个元素)]

解码时,先取一个字节(8位),作为文件名的长度,然后向后取255个元素,转换成文件名,再取4个字节,作为文件的长度,再向后取65535个字节,存储成文件。

总结:

这里学到了几个基本概念,首先一个byte[],字节数组,里面的每个元素都是8位,刚好对应一个字节,方便存取。其次是位移的概念,右移24位相当于取一个32位的值的高8位,&0xFF运算相当于只保留这个值的低8位(一个F(hex)=1111(bin))。这里用到的编码格式是一种较为粗糙的格式,长度位能表现的最大值固定,且位数固定,效率不是最高的。但基本理念要厘清,就是在编码时,我们是按照每8位依次计算并存入数组的。

什么意思?你是要把数组反转吧

var arr = ["f","e","i","e","s","o","f","t"]

document.writeln(arr.join()) // 输出:f,e,i,e,s,o,f,t

//反转

arr.reverse()

document.writeln(arr.join()) // 输出:t,f,o,s,e,i,e,f