javascript 类型数组读取二进制数据
先建一个文件,按UTF-16大端 BOM 格式保存一个字符串:hi aleck,
使用 file API 把他按二进制方式读取到浏览器。
文件读取方法在这里:
http://hi.baidu.com/ecalf830/item/e3b2d2c9b1003222a0b50a39
简单介绍一下 file api 的相关用法
1、在浏览器中打开文件
<input type="file" id="f" multiple="multiple"/>
当 file 控件 有 mutiple 属性时,可以上传多个文件,文件打开后保存在 file 控件的 files 属性,这个例子中只打开一个文件,获取的文件的方式是 :
var file = document.getElementById("f").files[0];
2、Blob 与文件读取类 FileReader
二进制大对象 Blob (binary large object) 用于存储二进制字节数据,
创建一个 blob 对象: var blob = new Blob(); 该对象的size属性表示文件的字节数,类似于数组的length,slice 可以从文件中复制出一段二进制数据,用法类似于数组的 silce,复制得到的数据也是 Blob 对象。
FileReader 类用于读取 Blob 数据对象。
创建一个文件读取 对象 :var reader = new FileReader();
浏览器打开的文件 file 继承于 Blob (thefile instanceof Blob == true),因此可以使用 FileReader 打开 file 对象。
FileReader 对象的属性、方法及在打开Blob数据过程中可以使用的回调函数(试在 firebug 下查看 FileReader 的属性和方法 console.log(new FileReader())):
error: nullonabort: nullonerror: nullonload: null //读取成功调用 onloadend: function(){...} //读取完毕调用,即使读取失败也会调用 onloadstart: null //开始打开文件时调用 onprogress: null //文件打开过程中,反复调用直至文件读取完毕 readyState: 2result: "þÿhi aleck" //文件读取结果得到的字符串 __proto__: FileReaderDONE: 2EMPTY: 0LOADING: 1abort: function abort() { [native code] }addEventListener: function addEventListener() { [native code] }constructor: function FileReader() { [native code] }dispatchEvent: function dispatchEvent() { [native code] }readAsArrayBuffer: function readAsArrayBuffer() { [native code] } //读取为二进制字节缓冲 readAsBinaryString: function readAsBinaryString() { [native code] } //读取为二进制数据 readAsDataURL: function readAsDataURL() { [native code] } //读取为base64数据 readAsText: function readAsText() { [native code] } //读取为普通字符串 removeEventListener: function removeEventListener() { [native code] }__proto__: Object
可以在 onloadend 事件内绑定处理打开的文件数据的回调函数,然后打开文件,
这里将文件以二进制方式打开:reader.readAsBinaryString();
查 看 reader.result 可以看到读取结果。由于javascript 没有二进制数据类型,因此,二进制数据按每个字节的8位二进制数对应 的 unicode 编码的字符显示出来,因此二进制数据实际被显示为一串 ascii 字符,如果要读取的文件是英文格式的, 那么这个二进制数据看起 来跟实际的字符串很相似。
本例中 UTF-16 BOM 大端格式的 字符串 "hi aleck" 打开为二进制后得到:
reader.result = "þÿhi aleck" //注意 reader.result.length 为 18, 这其中包含了空字符 \0 和标记字节流存储顺序的“零宽空格”
每个字节的8位二进制转为二位十六进制为:
reader.result.split('').map(function(v){ return ('0'+v.charCodeAt(0).toString(16)).slice(-2); })
得到:
["fe", "ff", "00", "68", "00", "69", "00", "20", "00", "61", "00", "6c", "00", "65", "00", "63", "00", "6b"]
由于是UTF-16编码,每个字符占二字节,feff 是用于字节序标记的字符"零宽空格",其余字符编码由于只需要一个字节,高位字节用 0 补足,unicode 编码为0 的字符为空字符 \0 。
例如 0068 是字母 h 的 2 字节(16位二进制转4位16进制)编码格式:
String.fromCharCode(parseInt('0068',16)) //h
3、字节数组缓冲 ArrayBuffer 和 类型数组
ArrayBuffer 类的对象指向一段定长的内存空间,其属性 byteLength 表示对象的字节长度,slice 对象类似于 Blob 和数组的 slice 用于拷贝出一定字节长度的缓冲数据并创建成新的 ArrayBuffer 对象。
ArrayBuffer 缓冲字节数据对象只是一段内存空间,不能直接访问,需要通过 DataView 对象(DataView 有点类似一个混合类型数组的元素组成的 list,其元素可以是几种类型数组中的任一种,这里不细述)或类型数组访问内存的数据,他们的关系有点像 Blob 与 FileReader .
其中 javascript 类型数组有下面几种:
Float32Array Float64Array Int8ArrayInt16Array Int32Array Uint8Array Uint16Array Uint32Array Uint8ClampedArray
可以访问下面的网站了解这些数据类型
http://www.javascripture.com/DataView
本例中使用存储无符号整数的 Uint8Array、 Uint16Array、 Uint32Array
Uint8Array 每个元素为一字节,表达范围为 0-255,Uint16Array 每元素 2字节,Uint32Array 每个元素4字节。
如果想要将 缓冲字节 ArrayBuffer 对象读入到类型数组中,比如可以这样
var buff = new ArrayBuffer(16); //创建一段16字节大小的内存缓冲空间var u8 = new Uint8Array(buff,8); //创建一个8位无符号整形类型数组,并指向 buff 对象的前 8 个字节。var u16 = new Uint16Array(buff,8); //16 位类型数组var u32 = new Uint32Array(buff,8); //32为类型数组
组要注意的是,类型数组并没有拷贝出 ArrayBuffer 对象的内容,而是指向对应的内存空间,因此 u8、u16、u32 这几个数组访问的是同一块内存,这意味着通过 u8 修改了内容后,u16 和 u32 将访问到改变后的内容。
现在 u8、u16 、u32 指向同一块 8 字节长度的内存,因此 u8 有8 个元素,u16 有4个元素,u32 则只有2个元素。
将上面打开文件得到的字节的前8个通过u8数组逐个存入 buff 内
["fe","ff","00","68","00","69","00","20"].forEach(function(v,i){ u8[i] = parseInt(v,16);});
有:
u8 = [254, 255, 0, 104, 0, 105, 0, 32]u16 = [65534, 26624, 26880, 8192]u32 = [1744895998, 536897792]
('00'+u8[0].toString(16)).slice(-2) // "fe" ('00'+u8[1].toString(16)).slice(-2) // "ff" ('00'+u8[2].toString(16)).slice(-2) // "00" ('00'+u8[3].toString(16)).slice(-2) // "68" ('00'+u8[4].toString(16)).slice(-2) // "00" ('00'+u8[5].toString(16)).slice(-2) // "69" ('00'+u8[6].toString(16)).slice(-2) // "00" ('00'+u8[7].toString(16)).slice(-2) // "20" ('0000'+u16[0].toString(16)).slice(-4) // "fffe" ('0000'+u16[1].toString(16)).slice(-4) // "6800" ('0000'+u16[2].toString(16)).slice(-4) // "6900" ('0000'+u16[3].toString(16)).slice(-4) // "2000" ('00000000'+u32[0].toString(16)).slice(-8) // "6800fffe" ('00000000'+u32[1].toString(16)).slice(-8) // "20006900"
可以看到,读取 Blob 对象时,在多字节类型数组中( u16 2字节的元素 和 u32 4字节的元素), 元素的字节是按低位在前的顺序存储的,即小端方式。
我们也可以直接把通过 FileReader 的 readAsArrayBuffer() 方法将 Blob 对象读取到 ArrayBuffer 对象中,然后在 类型数组中访问字节:
reader.readAsArrayBuffer(blob);var u16 = new Uint16Array(reader.result); u16 为 [65534, 26624, 26880, 8192, 24832, 27648, 25856, 25344, 27392]
类型数组的数据溢出问题:
因 为数组元素类型决定其在内存中占据的字节长度,其数值表达范围是按不同类型是不同的,如果存储的数值超出其表达范围便发生溢出,例 如, Uint8Array 类型的数组元素只占据一个字节,元素值的表达范围是 8位2进制, 即 0~255 ,如果试图存储 257 将发生溢出, 实际会得到取模后的值
var uint8 = new Uint8Array(10); uint8[0] //0 uint8[0]=257; uint8[0]; //1 257%256 = 1 uint8[0] = -1; uint8[0]; //255 -1+256=255 uint8[0] = x; 则 uint8[0] == (x%256+256)%256 ; //true Uint8ClampedArray 跟 Uint8Array 不同,如果给 Uint8ClampedArray 类型的数组元素赋值超出范围,则取最靠近所赋值的合法的值,这个数组可以用于处理图像的颜色数据,例如 canvas 的 image.data
var context = document.createElement("canvas").getContext("2d");var imageData = context.createImageData(16, 16);console.log(imageData); //ImageData {height: 16, width: 16, data: Uint8ClampedArray[1024]} console.log(imageData.data instanceof Uint8ClampedArray)//true
var cint8 = new Uint8ClampedArray(10); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] cint8[0]=257; // [255, 0, 0, 0, 0, 0, 0, 0, 0, 0] cint8[0]= -2; //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] cint8[0] = x;则 cint8[0] == Math.min(Math.max(0,x),255)
转载于:https://www.cnblogs.com/ecalf/archive/2012/11/25/2787219.html
javascript 类型数组读取二进制数据相关推荐
- 微软字节javascript 类型数组读取二进制数据 -java教程
每日一贴,今天的内容关键字为微软字节 先建一个文件,按UTF-16大端 BOM 格式存保一个符字串:hi aleck, 用使 file API 把他按二进制方法取读到浏览器. 文件取读方法在这里: h ...
- matlab 十六进制数组,【MATLAB】MATLAB中读取二进制数据文件并加入到矩阵中
MATLAB中读取二进制数据文件并加入到矩阵中的应用如下: 如果对c语言十分熟悉的话,应该对fopen,fclose,ftell,fseek,fread,fwrite,feof 这些函数非常熟悉了,在 ...
- python 读取二进制数据到可变缓冲区中
想直接读取二进制数据到一个可变缓冲区中,而不需要做任何的中间复制操作.或者你想原地修改数据并将它写回到一个文件中去. 为了读取数据到一个可变数组中,使用文件对象的readinto() 方法.比如 im ...
- SQLite数据库如何存储和读取二进制数据
1. 存储二进制数据 SQLite提供的绑定二进制参数接口函数为: int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n ...
- 前端读取文件图片信息流;js读取图片不同信息流;js读取图片;前端就js读取二进制数据;前端js读取文件流使用FileReader对象的readAsDataURL方法来读取图像文件;
原文链接 FileReader来把文件读入内存,并且读取文件中的数据. readAsDataURL方法可以在浏览器主线程中异步访问文件系统,读取文件中的数据,且读取后 result 为 DataURL ...
- 《Python Cookbook 3rd》笔记(5.9):读取二进制数据到可变缓冲区中
读取二进制数据到可变缓冲区中 问题 你想直接读取二进制数据到一个可变缓冲区中,而不需要做任何的中间复制操作.或者你想原地修改数据并将它写回到一个文件中去. 解法 为了读取数据到一个可变数组中,使用文件 ...
- Matlab读取二进制数据文件
第一步:函数fopen打开文件 fid=fopen('文件名',读取方式) fid:句柄值 小于0表示打开失败:大于0表示打开成功 文件名:字符串,使用单引号(本文例子'savedata.dat') ...
- [JavaScript]为JS处理二进制数据提供可能性的WEB API
写这篇博客的起源是在div.io上的一篇文章<你所不知道的JavaScript数组>by 小胡子哥下的评论中的讨论. 因为随着XHR2和现代浏览器的普及,在浏览器当中处理二进制不再向过去那 ...
- 用数组存储二进制数据
有时候程序引用了多个资源文件,但是希望交付给用户的是单个可执行文件,那么就需要把资源文件打包到可执行文件中,一个简单的做法是这样的. 使用 xxd 工具将二进制文件转换成 unsigned char ...
最新文章
- K项目轶事之开工第一天
- 3星|《数据思维:从数据分析到商业价值》:有趣的数据分析案例
- 海贼王热血航线正在连接服务器,航海王热血航线连接服务器失败?解决方法一览...
- js改变select下拉框默认选择的option
- 前端学习(2623):Vuex初步识别
- 后台窗口截图_万人拥捧的截图软件来啦!让你的工作效率提升不止一倍!
- php查到的内容追加到html,javascript - 请问php中如何将查询出来的结果数组转化成自己想要的格式,并在前台利用js输出到html中...
- VirtualBox中,WIN虚拟机与WIN共享文件夹
- 从0到1构建数据生态系列(二):拆解架构蓝图
- linux 卸载opera,Ubuntu中安装Opera 55 浏览器
- RayData学习总结
- Python Scrapy爬虫框架详解
- 微信小程序超链接跳转页面
- 中小企业如何选择OA协同办公产品?最全的对比都在这里了
- 计算机exo乐谱,History钢琴简谱-数字双手-EXO
- 2021-08-02彻底解决Typora+PicGo-Core+SMMS图床的问题
- 必备工具!程序员高效率工作工具推荐
- 基于Sentinel-1的干涉相干性特征生成
- 团队八种角色缺乏_缺乏信任会对团队造成什么影响
- Auto.js视频笔记
热门文章
- 1.初识Abp(模板初始化)
- LeetCode - 环形链表
- ABAQUS盾构隧道开挖对既有桥梁桩基的影响
- Android开发之短信验证码示例
- OA,PM,KM,CRM,ERP分别是什么
- R语言 大视角看R及R初探(一)
- GEE学习笔记一 利用GEE获取Sentinel-2 1C与2A级影像
- 快来珍藏这款10MB尺寸的Photoshop7.0绿色版(亲测Win10可运行,附下载链接)
- 模拟键盘、鼠标 mouse_event keybd_event
- 基于 Koa 的微服务 Node.js 框架设计思路与简单实现