国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js對(duì)文件和二進(jìn)制操作的一些方法匯總

fjcgreat / 474人閱讀

摘要:最近接手了一個(gè)項(xiàng)目接觸到一些對(duì)文件操作的業(yè)務(wù)所以在這邊整理一下日常用到的處理方式當(dāng)學(xué)習(xí)筆記吧有不對(duì)的地方歡迎指正哈首先我們來(lái)看一下這個(gè)萬(wàn)能的對(duì)象就如同它的名字一樣就是個(gè)文件讀取器之所以說(shuō)它是個(gè)萬(wàn)能的對(duì)象是因?yàn)樗梢宰x取任意格式的內(nèi)容最近我嘗

最近接手了一個(gè)項(xiàng)目,接觸到一些對(duì)文件操作的業(yè)務(wù).所以在這邊整理一下日常用到的處理方式,當(dāng)學(xué)習(xí)筆記吧,有不對(duì)的地方,歡迎指正哈

FileReader

首先我們來(lái)看一下 FileReader 這個(gè)萬(wàn)能的對(duì)象, 就如同它的名字一樣,就是個(gè)文件讀取器,
之所以說(shuō)它是個(gè)萬(wàn)能的對(duì)象是因?yàn)樗梢宰x取任意格式的內(nèi)容,最近我嘗試過(guò)用 FileReader 讀取過(guò) psd, ppt, 各種圖片等等.
雖然很多情況下,它讀出來(lái)的是我們完全看不懂的東西.不過(guò)通過(guò)一定的轉(zhuǎn)換,理論上我們可以在瀏覽器里面打開任何文件類型.

下面抄一段 MDN 的文檔

FileReader 對(duì)象允許Web應(yīng)用程序異步讀取存儲(chǔ)在用戶計(jì)算機(jī)上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對(duì)象指定要讀取的文件或數(shù)據(jù).

其中File對(duì)象可以是來(lái)自用戶在一個(gè) 元素上選擇文件后返回的 FileList 對(duì)象,也可以來(lái)自拖放操作生成的 DataTransfer 對(duì)象,還可以是來(lái)自在一個(gè) HTMLCanvasElement 上執(zhí)行 mozGetAsFile() 方法后返回結(jié)果.

由于是抄的,就不做詳細(xì)講解,重點(diǎn)是要知道你要讀的文件的編碼類型,然后調(diào)用對(duì)應(yīng)的方法取讀就可以了.這里有原文

由于 FileReader 可以把文件讀取成各種格式,所以這里可以利用這個(gè)特性,進(jìn)行編碼的轉(zhuǎn)換,如 ArrayBuffer, Blob對(duì)象 和 字符串, base64 之間的相互轉(zhuǎn)換/單向轉(zhuǎn)換, 部分類型只能單向轉(zhuǎn)換,是因?yàn)?FileReader 只接受 File 或 Blob 類型的數(shù)據(jù)(事實(shí)上 File 也 Blob 的一種),如果數(shù)據(jù)無(wú)法轉(zhuǎn)換成指定類型,就無(wú)法用 FileReader 轉(zhuǎn)換.

 const filereader = new FileReader();
 const blob = new Blob(["hello file-reader"], { type: "text/plain"});

 filereader.onload = e => {

     console.log(e.target.result); // 輸出 data:text/plain;base64,aGVsbG8gZmlsZS1yZWFkZXI=

 }

 filereader.readAsDataURL(blob);

網(wǎng)上傳的用 Uint16Array 進(jìn)行 String 和 ArrayBufer 互轉(zhuǎn)的其實(shí)有編碼長(zhǎng)度的問(wèn)題,我親身體驗(yàn)過(guò),用 FileReader 就可以避開這個(gè)問(wèn)題.可以調(diào)用它的 readAsArrayBuffer()readAsText() 方法,把指定對(duì)象讀取成 ArrayBuffer 格式 或 純文本格式的數(shù)據(jù).

當(dāng)然 FileReader 不僅僅能用在編碼轉(zhuǎn)換上,讀取各種文件才是它主要的能力,配合 、DataTransfer、Blob 等,可以把任意格式的數(shù)據(jù)讀取到瀏覽器里面.

Blob 對(duì)象 (Binary Large Object)

上面多次提到 Blob 對(duì)象,私以為 Blob 也是個(gè)非常強(qiáng)大的對(duì)象,所以這里我覺(jué)得非常有必要介紹一下,先看看 MDN 怎么說(shuō)的

Blob 對(duì)象表示一個(gè)不可變、原始數(shù)據(jù)的類文件對(duì)象.Blob 表示的不一定是JavaScript原生格式的數(shù)據(jù).File 接口基于Blob,繼承了 blob 的功能并將其擴(kuò)展使其支持用戶系統(tǒng)上的文件.

Blob 對(duì)象有個(gè)同名構(gòu)造函數(shù),該構(gòu)造函數(shù)接收 2 個(gè)參數(shù),第一個(gè)參數(shù)必須是個(gè) Array 類型的,哪怕你只有一項(xiàng),也必須用 [ ] 包著,如 ["hello file-reader"],
第二個(gè)參數(shù)是個(gè)可選的,是個(gè)對(duì)象,有2個(gè)選項(xiàng),type 和 endings,type 指定第一個(gè)參數(shù)的 MIME-Type, endings 指定第一個(gè)參數(shù)的數(shù)據(jù)格式,其可選值有 transparent(不變,默認(rèn)) 和 native(隨系統(tǒng)轉(zhuǎn)換)

const blob = new Blob(["hello file-reader"], { type: "text/plain"});

Blob.size 可以獲取對(duì)象中所包含數(shù)據(jù)的大小(字節(jié)), Blob.type 可以獲取對(duì)象所包含數(shù)據(jù)的MIME類型.如果類型未知,則該值為空字符串.

Blob.slice() 方法可以返回一個(gè)新的 Blob對(duì)象,包含了源 Blob對(duì)象中指定范圍內(nèi)的數(shù)據(jù), 共接收3個(gè)參數(shù),前兩個(gè)參數(shù)和 Array.slice 的參數(shù)類似

參數(shù)1:開始索引,默認(rèn)為0
參數(shù)2:截取結(jié)束索引(不包括當(dāng)前值)
參數(shù)3:新Blob的MIME類型,默認(rèn)為空字符串

const newBlob = blob.slice(0, 5, "text/plain");

大文件分段上傳就靠它了,配合 Blob.size 食用,口感更佳哈

通過(guò) URL.createObjectURL(Blob對(duì)象), 可以把 Blob對(duì)象 轉(zhuǎn)換成一個(gè)鏈接地址,該地址可以直接用在某些 DOM 的 src 或者 href 上, 從而實(shí)現(xiàn)前端下載或圖片顯示.
一個(gè)比較w神奇的用法是 阮老師的 web worker 教程 里的「同頁(yè)面的 Web Worker」, 這個(gè)再配合動(dòng)態(tài)插入 DOM, 是不是就可以繞開 webworker 的同源策略?

上面提到 FileReader 只能接受 Blob 格式的數(shù)據(jù)(其他格式其實(shí)也是Blob的子集), 其實(shí) Blob 也只能通過(guò) FileReader 讀取.簡(jiǎn)直就是泡面跟火腿腸,最佳搭檔啊哈
Arraybuffer, 類型數(shù)組對(duì)象, DataView

先說(shuō)說(shuō) Arraybuffer 之所以要介紹它,是因?yàn)?FileReader 有個(gè) readAsArrayBuffer() 方法,如果的被讀的文件是二進(jìn)制數(shù)據(jù),那用這個(gè)方法去讀應(yīng)該是最合適的,讀出來(lái)的數(shù)據(jù),就是一個(gè) Arraybuffer 對(duì)象,老規(guī)矩,看看定義:

ArrayBuffer 對(duì)象用來(lái)表示通用的、固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū).ArrayBuffer 不能直接操作,而是要通過(guò)類型數(shù)組對(duì)象或 DataView 對(duì)象來(lái)操作,它們會(huì)將緩沖區(qū)中的數(shù)據(jù)表示為特定的格式,并通過(guò)這些格式來(lái)讀寫緩沖區(qū)的內(nèi)容.

Arraybuffer 也有個(gè)同名構(gòu)造函數(shù),用于創(chuàng)建一個(gè)指定長(zhǎng)度的,內(nèi)容全部為 0 的 ArrayBuffer 對(duì)象,構(gòu)造函數(shù)接收一個(gè)參數(shù),用來(lái)指定要?jiǎng)?chuàng)建的內(nèi)容長(zhǎng)度.如:

let ab = new ArrayBuffer(8); // 創(chuàng)建一個(gè) 8 字節(jié)的 ArrayBuffer

由于無(wú)法對(duì) Arraybuffer 直接進(jìn)行操作,所以我們需要借助其他對(duì)象來(lái)操作. 所有就有了 TypedArray(類型數(shù)組對(duì)象)和 DataView.

TypedArray, TypedArray 是一類對(duì)象的統(tǒng)稱,事實(shí)上 JS 里面并沒(méi)有一個(gè)叫 TypedArray 的對(duì)象或構(gòu)造函數(shù).所以你不能直接使用 TypedArray.以下是 9 個(gè) TypedArray 對(duì)象/構(gòu)造函數(shù)

Int8Array();
Uint8Array();
Uint8ClampedArray();
Int16Array();
Uint16Array();
Int32Array();
Uint32Array();
Float32Array();
Float64Array();

具體用法請(qǐng)參考 MDN: TypedArray

TypedArray 雖然不是真的數(shù)組,但是有幾乎跟數(shù)組一樣的 API,我們可以像操作數(shù)組一樣操作 TypedArray ,所以有了 TypedArray 我們就可以把 ArrayBuffer 轉(zhuǎn)換成 TypedArray,然后在進(jìn)行讀寫操作,達(dá)到操作二進(jìn)制的目的,下面是個(gè)例子

    let arrayBuffer = new ArrayBuffer(8);

    console.log(arrayBuffer[0]);  // undefined

    let uint8Array = new Uint8Array(arrayBuffer);

    console.log(uint8Array);  // [0, 0, 0, 0, 0, 0, 0, 0]

    uint8Array[0] = 1;
    console.log(uint8Array[0]); // 1

    console.log(uint8Array);  // [1, 0, 0, 0, 0, 0, 0, 0]

可以看出,用 arrayBuffer[0] 的方式直接獲取 ArrayBuffer 對(duì)象的內(nèi)容是獲取不到的,而 TypedArray 可以.

直接 console.log(arrayBuffer) 在控制臺(tái)是可以看到 [[Int8Array]] [[Int16Array]] [[Int32Array]] [[Uint8Array]] 4 種 TypedArray 數(shù)據(jù),不過(guò)這應(yīng)該是瀏覽器為了方便開發(fā)者觀察數(shù)據(jù),而做的轉(zhuǎn)換,而不是 ArrayBuffer 真的擁有這些數(shù)據(jù),畢竟對(duì)象名稱看起來(lái)也不是那么正式(用 [[]] 包含)

arrayBuffer[0] = 1 給 ArrayBuffer 對(duì)象的某個(gè)下標(biāo)賦值是不會(huì)報(bào)錯(cuò)的,而且稍后你可以用同樣的路徑取出該值 console.log(arrayBuffer[0]) // 1, 但這并不代表你操作了 ArrayBuffer 的數(shù)據(jù),道理跟 給數(shù)組設(shè)置屬性 相同.

DataView, DataView 提供了跟 TypedArray 類似的功能,與 TypedArray 不同的是 DataView 是一個(gè)真實(shí)存在的對(duì)象,通過(guò)提供各種方法來(lái)操作不通類型的數(shù)據(jù),直接看栗子吧.

let arrayBuffer = new ArrayBuffer(8);

    let dataView = new DataView(arrayBuffer);

    console.log(dataView.getUint8(1)); // 0

    dataView.setUint8(1, 2);
    console.log(dataView.getUint8(1)); // 2
    console.log(dataView.getUint16(1)); // 512

    dataView.setUint16(1, 255);
    console.log(dataView.getUint16(1)); // 255
    console.log(dataView.getUint8(1)); // 0

就像你看到的,我們可以在同一個(gè)數(shù)據(jù)上面,調(diào)用不同的方法,讀取/寫入 不同類型(長(zhǎng)度)的數(shù)據(jù),但是大部分情況下,這么做會(huì)很難得到我們預(yù)期的效果.就像上面的輸出,看起來(lái)好像不是那么的正常,這是因?yàn)?一個(gè) 16 位的二進(jìn)制,用 8 位的格式來(lái)讀,剛好可以讀成 2 個(gè) 8 位的二進(jìn)制.舉個(gè)栗子

// 16 位的 1

0000 0000 0000 0001

// 用 8 位的讀就變成

0000 0000  // 0

0000 0001  // 1

因?yàn)榍懊?8 位剛好都是 0 , 所以結(jié)果看起來(lái)除了多個(gè) 0 似乎沒(méi)啥區(qū)別? 當(dāng)數(shù)字比較大的時(shí)候

// 應(yīng)該是256? 我也不太會(huì)算這個(gè)

0000 0001 0000 0001

// 用 8 位的讀就變成

0000 0001  // 1

0000 0001  // 1

扯遠(yuǎn)了,我們回頭看看 DataView 提供了哪些方法

// 讀
DataView.prototype.getInt8()
DataView.prototype.getUint8()
DataView.prototype.getInt16()
DataView.prototype.getUint16()
DataView.prototype.getInt32()
DataView.prototype.getUint32()
DataView.prototype.getFloat32()
DataView.prototype.getFloat64()

// 寫
DataView.prototype.setInt8()
DataView.prototype.setUint8()
DataView.prototype.setInt16()
DataView.prototype.setUint16()
DataView.prototype.setInt32()
DataView.prototype.setUint32()
DataView.prototype.setFloat32()
DataView.prototype.setFloat64()
跟 TypedArray 比 少了一個(gè) Uint8ClampedArray() 具體看 MDN: DataView
atob 和 btoa

base64 這個(gè)利器,相信前端的你不會(huì)陌生吧,最常用的操作可能就是圖片轉(zhuǎn) base64 了吧? 在之前 要在字符串跟 base64 直接互轉(zhuǎn),我們可能需要去網(wǎng)上拷一個(gè)別人的方法,而且大部分情況下,你沒(méi)有時(shí)間去驗(yàn)證這個(gè)方法是不是真的可靠,有沒(méi)有 bug, 現(xiàn)在我們可以直接用內(nèi)置的方法了

    let str = "I am a string";

    let a = btoa(str);  // a = "SSBhbSBhIHN0cmluZw=="

    let b = atob(a);  // b = "I am a string"

沒(méi)錯(cuò),就是這么簡(jiǎn)單,而且大部分瀏覽器都支持 除了 IE9-, 具體可以參考 CanIUse: atob

btoa 方法不支持中文和特殊字符,所以保險(xiǎn)起見,在轉(zhuǎn)換之前還是 encodeURIComponent 一下吧, 當(dāng)然別忘了在 atob 后,再 decodeURIComponent 回來(lái)。
jspack zipjs xml2js

最后再安利 3 個(gè)包

jspack https://github.com/pgriess/no... js操作二進(jìn)制文件, 我們的 psd 文件解析就用到這個(gè)包.

jszip https://github.com/Stuk/jszip js操作壓縮文件, 我們的 pptx 的壓縮比解析成 xml 都靠它.

xml2js https://github.com/Leonidas-f... 把 xml 文件轉(zhuǎn)換成 json, 我們的 pptx 解析就是用它進(jìn)行 pptx 的 xml 文件的轉(zhuǎn)換.

廣告時(shí)間

我們40人的前端團(tuán)隊(duì)常年招兵買馬中,在廈門的和想來(lái)廈門的童鞋們,不要吝惜你的簡(jiǎn)歷,使勁砸過(guò)來(lái) 郵箱:atob("bnVveWFAZ2FvZGluZy5jb20="), 期待你一起來(lái)稿

對(duì)本文有意見或者建議,請(qǐng)盡量在 github 上提 issue, 最近比較忙,比較不怎么逛社區(qū)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/101367.html

相關(guān)文章

  • 前端實(shí)習(xí)面試匯總

    摘要:題目來(lái)源前端實(shí)習(xí)生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄下來(lái)進(jìn)行一個(gè)總結(jié),同樣也希望對(duì)正在準(zhǔn)備面實(shí)習(xí)生的童鞋們有所幫助最后一個(gè)參數(shù)是做什么用的答規(guī)定事件是冒泡還是捕獲。 最近一直在多看基礎(chǔ)的書多碼代碼準(zhǔn)備找實(shí)習(xí),在網(wǎng)上也搜羅了不少面經(jīng),現(xiàn)在把搜羅到的實(shí)習(xí)生面試題自己整理一下。 題目來(lái)源:前端實(shí)習(xí)生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄...

    張利勇 評(píng)論0 收藏0
  • 前端實(shí)習(xí)面試匯總

    摘要:題目來(lái)源前端實(shí)習(xí)生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄下來(lái)進(jìn)行一個(gè)總結(jié),同樣也希望對(duì)正在準(zhǔn)備面實(shí)習(xí)生的童鞋們有所幫助最后一個(gè)參數(shù)是做什么用的答規(guī)定事件是冒泡還是捕獲。 最近一直在多看基礎(chǔ)的書多碼代碼準(zhǔn)備找實(shí)習(xí),在網(wǎng)上也搜羅了不少面經(jīng),現(xiàn)在把搜羅到的實(shí)習(xí)生面試題自己整理一下。 題目來(lái)源:前端實(shí)習(xí)生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄...

    wangzy2019 評(píng)論0 收藏0
  • 前端實(shí)習(xí)面試匯總

    摘要:題目來(lái)源前端實(shí)習(xí)生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄下來(lái)進(jìn)行一個(gè)總結(jié),同樣也希望對(duì)正在準(zhǔn)備面實(shí)習(xí)生的童鞋們有所幫助最后一個(gè)參數(shù)是做什么用的答規(guī)定事件是冒泡還是捕獲。 最近一直在多看基礎(chǔ)的書多碼代碼準(zhǔn)備找實(shí)習(xí),在網(wǎng)上也搜羅了不少面經(jīng),現(xiàn)在把搜羅到的實(shí)習(xí)生面試題自己整理一下。 題目來(lái)源:前端實(shí)習(xí)生面試總結(jié)最近開始了幾次面試,雖然還不知道結(jié)果如何,但是還是要記錄...

    NicolasHe 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<