日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

談談JS二進制:File、Blob、FileReader、ArrayBuffer、Base64

來源: 責編: 時間:2024-03-18 09:42:16 180觀看
導讀大家好,我是 CUGGZ。JavaScript 提供了一些 API 來處理文件或原始文件數據,例如:File、Blob、FileReader、ArrayBuffer、base64 等。下面就來看看它們都是如何使用的,它們之間又有何區別和聯系!1. BlobBlob 全稱為 binary

大家好,我是 CUGGZ。ybJ28資訊網——每日最新資訊28at.com

JavaScript 提供了一些 API 來處理文件或原始文件數據,例如:File、Blob、FileReader、ArrayBuffer、base64 等。下面就來看看它們都是如何使用的,它們之間又有何區別和聯系!ybJ28資訊網——每日最新資訊28at.com

圖片ybJ28資訊網——每日最新資訊28at.com

1. Blob

Blob 全稱為 binary large object ,即二進制大對象,它是 JavaScript 中的一個對象,表示原始的類似文件的數據。下面是 MDN 中對 Blob 的解釋:ybJ28資訊網——每日最新資訊28at.com

Blob 對象表示一個不可變、原始數據的類文件對象。它的數據可以按文本或二進制的格式進行讀取,也可以轉換成 ReadableStream 來用于數據操作。ybJ28資訊網——每日最新資訊28at.com

實際上,Blob 對象是包含有只讀原始數據的類文件對象。簡單來說,Blob 對象就是一個不可修改的二進制文件。ybJ28資訊網——每日最新資訊28at.com

(1)Blob 創建

可以使用 Blob() 構造函數來創建一個 Blob:ybJ28資訊網——每日最新資訊28at.com

new Blob(array, options);

其有兩個參數:ybJ28資訊網——每日最新資訊28at.com

  • array:由 ArrayBuffer、ArrayBufferView、Blob、DOMString 等對象構成的,將會被放進 Blob;
  • options:可選的 BlobPropertyBag 字典,它可能會指定如下兩個屬性
  • type:默認值為 "",表示將會被放入到 blob 中的數組內容的 MIME 類型。
  • endings:默認值為"transparent",用于指定包含行結束符/n的字符串如何被寫入,不常用。

常見的 MIME 類型如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

下面來看一個簡單的例子:ybJ28資訊網——每日最新資訊28at.com

const blob = new Blob(["Hello World"], {type: "text/plain"});

這里可以成為動態文件創建,其正在創建一個類似文件的對象。這個 blob 對象上有兩個屬性:ybJ28資訊網——每日最新資訊28at.com

  • size:Blob對象中所包含數據的大小(字節);
  • type:字符串,認為該Blob對象所包含的 MIME 類型。如果類型未知,則為空字符串。

下面來看打印結果:ybJ28資訊網——每日最新資訊28at.com

const blob = new Blob(["Hello World"], {type: "text/plain"});console.log(blob.size); // 11console.log(blob.type); // "text/plain"

注意,字符串"Hello World"是 UTF-8 編碼的,因此它的每個字符占用 1 個字節。ybJ28資訊網——每日最新資訊28at.com

到現在,Blob 對象看起來似乎我們還是沒有啥用。那該如何使用 Blob 對象呢?可以使用 URL.createObjectURL() 方法將將其轉化為一個 URL,并在 Iframe 中加載:ybJ28資訊網——每日最新資訊28at.com

<iframe></iframe>const iframe = document.getElementsByTagName("iframe")[0];const blob = new Blob(["Hello World"], {type: "text/plain"});iframe.src = URL.createObjectURL(blob);

(2)Blob 分片

除了使用Blob()構造函數來創建blob 對象之外,還可以從 blob 對象中創建blob,也就是將 blob 對象切片。Blob 對象內置了 slice() 方法用來將 blob 對象分片,其語法如下:ybJ28資訊網——每日最新資訊28at.com

const blob = instanceOfBlob.slice([start [, end [, contentType]]]};

其有三個參數:ybJ28資訊網——每日最新資訊28at.com

  • start:設置切片的起點,即切片開始位置。默認值為 0,這意味著切片應該從第一個字節開始;
  • end:設置切片的結束點,會對該位置之前的數據進行切片。默認值為blob.size;
  • contentType:設置新 blob 的 MIME 類型。如果省略 type,則默認為 blob 的原始值。

下面來看例子:ybJ28資訊網——每日最新資訊28at.com

const iframe = document.getElementsByTagName("iframe")[0];const blob = new Blob(["Hello World"], {type: "text/plain"});const subBlob = blob.slice(0, 5);iframe.src = URL.createObjectURL(subBlob);

此時頁面會顯示"Hello"。ybJ28資訊網——每日最新資訊28at.com

2. File

文件(File)接口提供有關文件的信息,并允許網頁中的 JavaScript 訪問其內容。實際上,File 對象是特殊類型的 Blob,且可以用在任意的 Blob 類型的 context 中。Blob 的屬性和方法都可以用于 File 對象。ybJ28資訊網——每日最新資訊28at.com

注意:File 對象中只存在于瀏覽器環境中,在 Node.js 環境中不存在。ybJ28資訊網——每日最新資訊28at.com

在 JavaScript 中,主要有兩種方法來獲取 File 對象:ybJ28資訊網——每日最新資訊28at.com

  • <input> 元素上選擇文件后返回的 FileList 對象;
  • 文件拖放操作生成的 DataTransfer 對象;

(1)input

首先定義一個輸入類型為 file 的 input 標簽:ybJ28資訊網——每日最新資訊28at.com

<input type="file" id="fileInput" multiple="multiple">

這里給 input 標簽添加了三個屬性:ybJ28資訊網——每日最新資訊28at.com

  • type="file":指定 input 的輸入類型為文件;
  • id="fileInput":指定 input 的唯一 id;
  • multiple="multiple":指定 input 可以同時上傳多個文件;

下面來給 input 標簽添加 onchange 事件,當選擇文件并上傳之后觸發:ybJ28資訊網——每日最新資訊28at.com

const fileInput = document.getElementById("fileInput");fileInput.onchange = (e) => {    console.log(e.target.files);}

當點擊上傳文件時,控制臺就會輸出一個 FileList 數組,這個數組的每個元素都是一個 File 對象,一個上傳的文件就對應一個 File 對象:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

每個 File 對象都包含文件的一些屬性,這些屬性都繼承自 Blob 對象:ybJ28資訊網——每日最新資訊28at.com

  • lastModified:引用文件最后修改日期,為自1970年1月1日0:00以來的毫秒數;
  • lastModifiedDate:引用文件的最后修改日期;
  • name:引用文件的文件名;
  • size:引用文件的文件大小;
  • type:文件的媒體類型(MIME);
  • webkitRelativePath:文件的路徑或 URL。

通常,我們在上傳文件時,可以通過對比 size 屬性來限制文件大小,通過對比 type 來限制上傳文件的格式等。ybJ28資訊網——每日最新資訊28at.com

(2)文件拖放

另一種獲取 File 對象的方式就是拖放 API,這個 API 很簡單,就是將瀏覽器之外的文件拖到瀏覽器窗口中,并將它放在一個成為拖放區域的特殊區域中。拖放區域用于響應放置操作并從放置的項目中提取信息。這些是通過 ondrop 和 ondragover 兩個 API 實現的。ybJ28資訊網——每日最新資訊28at.com

下面來看一個簡單的例子,首先定義一個拖放區域:ybJ28資訊網——每日最新資訊28at.com

<div id="drop-zone"></div>

然后給這個元素添加 ondragover 和 ondrop 事件處理程序:ybJ28資訊網——每日最新資訊28at.com

const dropZone = document.getElementById("drop-zone");dropZone.ondragover = (e) => {    e.preventDefault();}dropZone.ondrop = (e) => {    e.preventDefault();    const files = e.dataTransfer.files;    console.log(files)}

注意:這里給兩個 API 都添加了 e.preventDefault(),用來阻止默認事件。它是非常重要的,可以用來阻止瀏覽器的一些默認行為,比如放置文件將顯示在瀏覽器窗口中。ybJ28資訊網——每日最新資訊28at.com

當拖放文件到拖放區域時,控制臺就會輸出一個  FileList 數組,該數組的每一個元素都是一個 File 對象。這個 FileList 數組是從事件參數的 dataTransfer 屬性的 files 獲取的:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

可以看到,這里得到的 File 對象和通過 input 標簽獲得的 File 對象是完全一樣的。ybJ28資訊網——每日最新資訊28at.com

3. FileReader

FileReader 是一個異步 API,用于讀取文件并提取其內容以供進一步使用。FileReader 可以將 Blob 讀取為不同的格式。ybJ28資訊網——每日最新資訊28at.com

注意:FileReader 僅用于以安全的方式從用戶(遠程)系統讀取文件內容,不能用于從文件系統中按路徑名簡單地讀取文件。ybJ28資訊網——每日最新資訊28at.com

(1)基本使用

可以使用 FileReader 構造函數來創建一個 FileReader 對象:ybJ28資訊網——每日最新資訊28at.com

const reader = new FileReader();

這個對象常用屬性如下:ybJ28資訊網——每日最新資訊28at.com

  • error:表示在讀取文件時發生的錯誤;
  • result:文件內容。該屬性僅在讀取操作完成后才有效,數據的格式取決于使用哪個方法來啟動讀取操作。
  • readyState:表示FileReader狀態的數字。取值如下:

圖片圖片ybJ28資訊網——每日最新資訊28at.com

FileReader 對象提供了以下方法來加載文件:ybJ28資訊網——每日最新資訊28at.com

  • readAsArrayBuffer():讀取指定 Blob 中的內容,完成之后,result 屬性中保存的將是被讀取文件的 ArrayBuffer 數據對象;
  • FileReader.readAsBinaryString():讀取指定 Blob 中的內容,完成之后,result 屬性中將包含所讀取文件的原始二進制數據;
  • FileReader.readAsDataURL():讀取指定 Blob 中的內容,完成之后,result 屬性中將包含一個data: URL 格式的 Base64 字符串以表示所讀取文件的內容。
  • FileReader.readAsText():讀取指定 Blob 中的內容,完成之后,result 屬性中將包含一個字符串以表示所讀取的文件內容。

可以看到,上面這些方法都接受一個要讀取的 blob 對象作為參數,讀取完之后會將讀取的結果放入對象的 result 屬性中。ybJ28資訊網——每日最新資訊28at.com

(2)事件處理

FileReader 對象常用的事件如下:ybJ28資訊網——每日最新資訊28at.com

  • abort:該事件在讀取操作被中斷時觸發;
  • error:該事件在讀取操作發生錯誤時觸發;
  • load:該事件在讀取操作完成時觸發;
  • progress:該事件在讀取 Blob 時觸發。

當然,這些方法可以加上前置 on 后在HTML元素上使用,比如onload、onerror、onabort、onprogress。除此之外,由于FileReader對象繼承自EventTarget,因此還可以使用 addEventListener() 監聽上述事件。ybJ28資訊網——每日最新資訊28at.com

下面來看一個簡單的例子,首先定義一個 input 輸入框用于上傳文件:ybJ28資訊網——每日最新資訊28at.com

<input type="file" id="fileInput">

接下來定義 input 標簽的 onchange 事件處理函數和FileReader對象的onload事件處理函數:ybJ28資訊網——每日最新資訊28at.com

const fileInput = document.getElementById("fileInput");const reader = new FileReader();fileInput.onchange = (e) => {    reader.readAsText(e.target.files[0]);}reader.onload = (e) => {    console.log(e.target.result);}

這里,首先創建了一個 FileReader 對象,當文件上傳成功時,使用 readAsText() 方法讀取 File 對象,當讀取操作完成時打印讀取結果。ybJ28資訊網——每日最新資訊28at.com

使用上述例子讀取文本文件時,就是比較正常的。如果讀取二進制文件,比如png格式的圖片,往往會產生亂碼,如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

那該如何處理這種二進制數據呢?readAsDataURL() 是一個不錯的選擇,它可以將讀取的文件的內容轉換為 base64 數據的 URL 表示。這樣,就可以直接將 URL 用在需要源鏈接的地方,比如 img 標簽的 src 屬性。ybJ28資訊網——每日最新資訊28at.com

對于上述例子,將 readAsText 方法改為 readAsDataURL():ybJ28資訊網——每日最新資訊28at.com

const fileInput = document.getElementById("fileInput");const reader = new FileReader();fileInput.onchange = (e) => {    reader.readAsDataURL(e.target.files[0]);}reader.onload = (e) => {    console.log(e.target.result);}

這時,再次上傳二進制圖片時,就會在控制臺打印一個 base64 編碼的 URL,如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

下面來修改一下這個例子,將上傳的圖片通過以上方式顯示在頁面上:ybJ28資訊網——每日最新資訊28at.com

<input type="file" id="fileInput" /><img id="preview" />
const fileInput = document.getElementById("fileInput");const preview = document.getElementById("preview");const reader = new FileReader();fileInput.onchange = (e) => {  reader.readAsDataURL(e.target.files[0]);};reader.onload = (e) => {  preview.src = e.target.result;  console.log(e.target.result);};

圖片圖片ybJ28資訊網——每日最新資訊28at.com

當上傳大文件時,可以通過 progress 事件來監控文件的讀取進度:ybJ28資訊網——每日最新資訊28at.com

const reader = new FileReader();reader.onprogress = (e) => {  if (e.loaded && e.total) {    const percent = (event.loaded / event.total) * 100;    console.log(`上傳進度: ${Math.round(percent)} %`);  }});

progress 事件提供了兩個屬性:loaded(已讀取量)和total(需讀取總量)。ybJ28資訊網——每日最新資訊28at.com

4. ArrayBuffer

(1)ArrayBuffer

ArrayBuffer 對象用來表示通用的、固定長度的原始二進制數據緩沖區。ArrayBuffer 的內容不能直接操作,只能通過 DataView 對象或 TypedArrray 對象來訪問。這些對象用于讀取和寫入緩沖區內容。ybJ28資訊網——每日最新資訊28at.com

ArrayBuffer 本身就是一個黑盒,不能直接讀寫所存儲的數據,需要借助以下視圖對象來讀寫:ybJ28資訊網——每日最新資訊28at.com

  • TypedArray:用來生成內存的視圖,通過9個構造函數,可以生成9種數據格式的視圖。
  • DataViews:用來生成內存的視圖,可以自定義格式和字節序。

圖片圖片ybJ28資訊網——每日最新資訊28at.com

TypedArray視圖和 DataView視圖的區別主要是字節序,前者的數組成員都是同一個數據類型,后者的數組成員可以是不同的數據類型。ybJ28資訊網——每日最新資訊28at.com

那 ArrayBuffer 與 Blob 有啥區別呢?根據 ArrayBuffer 和 Blob 的特性,Blob 作為一個整體文件,適合用于傳輸;當需要對二進制數據進行操作時(比如要修改某一段數據時),就可以使用 ArrayBuffer。ybJ28資訊網——每日最新資訊28at.com

下面來看看 ArrayBuffer 有哪些常用的方法和屬性。ybJ28資訊網——每日最新資訊28at.com

① new ArrayBuffer()

ArrayBuffer 可以通過以下方式生成:ybJ28資訊網——每日最新資訊28at.com

new ArrayBuffer(bytelength)

ArrayBuffer()構造函數可以分配指定字節數量的緩沖區,其參數和返回值如下:ybJ28資訊網——每日最新資訊28at.com

  • 參數:它接受一個參數,即 bytelength,表示要創建數組緩沖區的大小(以字節為單位。);
  • 返回值:返回一個新的指定大小的ArrayBuffer對象,內容初始化為0。

② ArrayBuffer.prototype.byteLength

ArrayBuffer 實例上有一個 byteLength 屬性,它是一個只讀屬性,表示 ArrayBuffer 的 byte 的大小,在 ArrayBuffer 構造完成時生成,不可改變。來看例子:ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(16); console.log(buffer.byteLength);  // 16

③ ArrayBuffer.prototype.slice()

ArrayBuffer 實例上還有一個 slice 方法,該方法可以用來截取 ArrayBuffer 實例,它返回一個新的 ArrayBuffer ,它的內容是這個 ArrayBuffer 的字節副本,從 begin(包括),到 end(不包括)。來看例子:ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(16); console.log(buffer.slice(0, 8));  // 16

這里會從 buffer 對象上將前8個字節生成一個新的ArrayBuffer對象。這個方法實際上有兩步操作,首先會分配一段指定長度的內存,然后拷貝原來ArrayBuffer對象的置頂部分。ybJ28資訊網——每日最新資訊28at.com

④ ArrayBuffer.isView()

ArrayBuffer 上有一個 isView()方法,它的返回值是一個布爾值,如果參數是 ArrayBuffer 的視圖實例則返回 true,例如類型數組對象或 DataView 對象;否則返回 false。簡單來說,這個方法就是用來判斷參數是否是 TypedArray 實例或者 DataView 實例:ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(16);ArrayBuffer.isView(buffer)   // falseconst view = new Uint32Array(buffer);ArrayBuffer.isView(view)     // true

(2)TypedArray

TypedArray 對象一共提供 9 種類型的視圖,每一種視圖都是一種構造函數。如下:ybJ28資訊網——每日最新資訊28at.com

元素ybJ28資訊網——每日最新資訊28at.com

類型化數組ybJ28資訊網——每日最新資訊28at.com

字節ybJ28資訊網——每日最新資訊28at.com

描述ybJ28資訊網——每日最新資訊28at.com

Int8
ybJ28資訊網——每日最新資訊28at.com

Int8Array
ybJ28資訊網——每日最新資訊28at.com

1
ybJ28資訊網——每日最新資訊28at.com

8 位有符號整數
ybJ28資訊網——每日最新資訊28at.com

Uint8
ybJ28資訊網——每日最新資訊28at.com

Uint8Array
ybJ28資訊網——每日最新資訊28at.com

1
ybJ28資訊網——每日最新資訊28at.com

8 位無符號整數
ybJ28資訊網——每日最新資訊28at.com

Uint8C
ybJ28資訊網——每日最新資訊28at.com

Uint8ClampedArray
ybJ28資訊網——每日最新資訊28at.com

1
ybJ28資訊網——每日最新資訊28at.com

8 位無符號整數
ybJ28資訊網——每日最新資訊28at.com

Int16
ybJ28資訊網——每日最新資訊28at.com

Int16Array
ybJ28資訊網——每日最新資訊28at.com

2
ybJ28資訊網——每日最新資訊28at.com

16 位有符號整數
ybJ28資訊網——每日最新資訊28at.com

Uint16
ybJ28資訊網——每日最新資訊28at.com

Uint16Array
ybJ28資訊網——每日最新資訊28at.com

2
ybJ28資訊網——每日最新資訊28at.com

16 位無符號整數
ybJ28資訊網——每日最新資訊28at.com

Int32
ybJ28資訊網——每日最新資訊28at.com

Int32Array
ybJ28資訊網——每日最新資訊28at.com

4
ybJ28資訊網——每日最新資訊28at.com

32 位有符號整數
ybJ28資訊網——每日最新資訊28at.com

Uint32
ybJ28資訊網——每日最新資訊28at.com

Uint32Array
ybJ28資訊網——每日最新資訊28at.com

4
ybJ28資訊網——每日最新資訊28at.com

32 位無符號整數
ybJ28資訊網——每日最新資訊28at.com

Float32
ybJ28資訊網——每日最新資訊28at.com

Float32Array
ybJ28資訊網——每日最新資訊28at.com

4
ybJ28資訊網——每日最新資訊28at.com

32 位浮點
ybJ28資訊網——每日最新資訊28at.com

Float64
ybJ28資訊網——每日最新資訊28at.com

Float64Array
ybJ28資訊網——每日最新資訊28at.com

8
ybJ28資訊網——每日最新資訊28at.com

64 位浮點
ybJ28資訊網——每日最新資訊28at.com

來看看這些都是什么意思:ybJ28資訊網——每日最新資訊28at.com

  • Uint8Array: 將 ArrayBuffer 中的每個字節視為一個整數,可能的值從 0 到 255 (一個字節等于 8 位)。這樣的值稱為“8 位無符號整數”。
  • Uint16Array:將 ArrayBuffer 中任意兩個字節視為一個整數,可能的值從 0 到 65535。這樣的值稱為“16 位無符號整數”。
  • Uint32Array:將 ArrayBuffer 中任何四個字節視為一個整數,可能值從 0 到 4294967295,這樣的值稱為“32 位無符號整數”。

這些構造函數生成的對象統稱為 TypedArray 對象。它們和正常的數組很類似,都有length 屬性,都能用索引獲取數組元素,所有數組的方法都可以在類型化數組上面使用。ybJ28資訊網——每日最新資訊28at.com

那類型化數組和數組有什么區別呢?ybJ28資訊網——每日最新資訊28at.com

  • 類型化數組的元素都是連續的,不會為空;
  • 類型化數組的所有成員的類型和格式相同;
  • 類型化數組元素默認值為 0;
  • 類型化數組本質上只是一個視圖層,不會存儲數據,數據都存儲在更底層的 ArrayBuffer 對象中。

下面來看看 TypedArray 都有哪些常用的方法和屬性。ybJ28資訊網——每日最新資訊28at.com

① new TypedArray()

TypedArray 的語法如下(TypedArray只是一個概念,實際使用的是那9個對象):ybJ28資訊網——每日最新資訊28at.com

new Int8Array(length);new Int8Array(typedArray);new Int8Array(object);new Int8Array(buffer [, byteOffset [, length]]);

可以看到,TypedArray 有多種用法,下面來分別看一下。ybJ28資訊網——每日最新資訊28at.com

  • TypedArray(length) :通過分配指定長度內容進行分配
let view = new Int8Array(16);view[0] = 10;view[10] = 6;console.log(view);

輸出結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

這里就生成了一個 16個元素的 Int8Array 數組,除了手動賦值的元素,其他元素的初始值都是 0。ybJ28資訊網——每日最新資訊28at.com

  • TypedArray(typeArray) :接收一個視圖實例作為參數
const view = new Int8Array(new Uint8Array(6));view[0] = 10;view[3] = 6;console.log(view);

輸出結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

  • TypedArray(object) :參數可以是一個普通數組
const view = new Int8Array([1, 2, 3, 4, 5]);view[0] = 10;view[3] = 6;console.log(view);

輸出結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

需要注意,TypedArray視圖會開辟一段新的內存,不會在原數組上建立內存。當然,這里創建的類型化數組也能轉換回普通數組:ybJ28資訊網——每日最新資訊28at.com

Array.prototype.slice.call(view); // [10, 2, 3, 6, 5]
  • TypeArray(buffer [, byteOffset [, length]]) :

這種方式有三個參數,其中第一個參數是一個ArrayBuffer對象;第二個參數是視圖開始的字節序號,默認從0開始,可選;第三個參數是視圖包含的數據個數,默認直到本段內存區域結束。ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(8);const view1 = new Int32Array(buffer); const view2 = new Int32Array(buffer, 4); console.log(view1, view2);

輸出結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

② BYTES_PER_ELEMENT

每種視圖的構造函數都有一個 BYTES_PER_ELEMENT 屬性,表示這種數據類型占據的字節數:ybJ28資訊網——每日最新資訊28at.com

Int8Array.BYTES_PER_ELEMENT // 1Uint8Array.BYTES_PER_ELEMENT // 1Int16Array.BYTES_PER_ELEMENT // 2Uint16Array.BYTES_PER_ELEMENT // 2Int32Array.BYTES_PER_ELEMENT // 4Uint32Array.BYTES_PER_ELEMENT // 4Float32Array.BYTES_PER_ELEMENT // 4Float64Array.BYTES_PER_ELEMENT // 8

BYTES_PER_ELEMENT 屬性也可以在類型化數組的實例上獲取:ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(16); const view = new Uint32Array(buffer); console.log(Uint32Array.BYTES_PER_ELEMENT); // 4

③ TypedArray.prototype.buffer

TypedArray 實例的 buffer 屬性會返回內存中對應的 ArrayBuffer對象,只讀屬性。ybJ28資訊網——每日最新資訊28at.com

const a = new Uint32Array(8);const b = new Int32Array(a.buffer); console.log(a, b);

輸出結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

④ TypedArray.prototype.slice()

TypeArray 實例的 slice方法可以返回一個指定位置的新的 TypedArray實例。ybJ28資訊網——每日最新資訊28at.com

const view = new Int16Array(8);console.log(view.slice(0 ,5));

輸出結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

⑤ byteLength 和 length

  • byteLength:返回 TypedArray 占據的內存長度,單位為字節;
  • length:返回 TypedArray 元素個數;
const view = new Int16Array(8);view.length;      // 8view.byteLength;  // 16

(3)DataView

說完 ArrayBuffer,下面來看看另一種操作 ArrayBuffer 的方式:DataView。DataView 視圖是一個可以從 二進制 ArrayBuffer 對象中讀寫多種數值類型的底層接口,使用它時,不用考慮不同平臺的字節序問題。ybJ28資訊網——每日最新資訊28at.com

DataView視圖提供更多操作選項,而且支持設定字節序。本來,在設計目的上,ArrayBuffer對象的各種TypedArray視圖,是用來向網卡、聲卡之類的本機設備傳送數據,所以使用本機的字節序就可以了;而DataView視圖的設計目的,是用來處理網絡設備傳來的數據,所以大端字節序或小端字節序是可以自行設定的。ybJ28資訊網——每日最新資訊28at.com

① new DataView()

DataView視圖可以通過構造函數來創建,它的參數是一個ArrayBuffer對象,生成視圖。其語法如下:ybJ28資訊網——每日最新資訊28at.com

new DataView(buffer [, byteOffset [, byteLength]])

其有三個參數:ybJ28資訊網——每日最新資訊28at.com

  • buffer:一個已經存在的 ArrayBuffer 對象,DataView 對象的數據源。
  • byteOffset:可選,此 DataView 對象的第一個字節在 buffer 中的字節偏移。如果未指定,則默認從第一個字節開始。
  • byteLength:可選,此 DataView 對象的字節長度。如果未指定,這個視圖的長度將匹配 buffer 的長度。

來看一個例子:ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(16);const view = new DataView(buffer);console.log(view);

打印結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

② buffer、byteLength、byteOffset

DataView 實例有以下常用屬性:ybJ28資訊網——每日最新資訊28at.com

  • buffer:返回對應的ArrayBuffer對象;
  • byteLength:返回占據的內存字節長度;
  • byteOffset:返回當前視圖從對應的ArrayBuffer對象的哪個字節開始。
const buffer = new ArrayBuffer(16);const view = new DataView(buffer);view.buffer;view.byteLength;view.byteOffset;

打印結果如下:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

③ 讀取內存

DataView 實例提供了以下方法來讀取內存,它們的參數都是一個字節序號,表示開始讀取的字節位置:ybJ28資訊網——每日最新資訊28at.com

  • getInt8:讀取1個字節,返回一個8位整數。
  • getUint8:讀取1個字節,返回一個無符號的8位整數。
  • getInt16:讀取2個字節,返回一個16位整數。
  • getUint16:讀取2個字節,返回一個無符號的16位整數。
  • getInt32:讀取4個字節,返回一個32位整數。
  • getUint32:讀取4個字節,返回一個無符號的32位整數。
  • getFloat32:讀取4個字節,返回一個32位浮點數。
  • getFloat64:讀取8個字節,返回一個64位浮點數。

下面來看一個例子:ybJ28資訊網——每日最新資訊28at.com

const buffer = new ArrayBuffer(24);const view = new DataView(buffer);// 從第1個字節讀取一個8位無符號整數const view1 = view.getUint8(0);// 從第2個字節讀取一個16位無符號整數const view2 = view.getUint16(1);// 從第4個字節讀取一個16位無符號整數const view3 = view.getUint16(3);

④ 寫入內存

DataView 實例提供了以下方法來寫入內存,它們都接受兩個參數,第一個參數表示開始寫入數據的字節序號,第二個參數為寫入的數據:ybJ28資訊網——每日最新資訊28at.com

  • setInt8:寫入1個字節的8位整數。
  • setUint8:寫入1個字節的8位無符號整數。
  • setInt16:寫入2個字節的16位整數。
  • setUint16:寫入2個字節的16位無符號整數。
  • setInt32:寫入4個字節的32位整數。
  • setUint32:寫入4個字節的32位無符號整數。
  • setFloat32:寫入4個字節的32位浮點數。
  • setFloat64:寫入8個字節的64位浮點數。

5. Object URL

Object URL(MDN定義名稱)又稱Blob URL(W3C定義名稱),是HTML5中的新標準。它是一個用來表示File Object 或Blob Object 的URL。在網頁中,我們可能會看到過這種形式的 Blob URL:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

其實 Blob URL/Object URL 是一種偽協議,允許將 Blob 和 File 對象用作圖像、二進制數據下載鏈接等的 URL 源。ybJ28資訊網——每日最新資訊28at.com

對于 Blob/File 對象,可以使用 URL構造函數的 createObjectURL() 方法創建將給出的對象的 URL。這個 URL 對象表示指定的 File 對象或 Blob 對象。我們可以在<img>、<script> 標簽中或者 <a> 和 <link> 標簽的 href 屬性中使用這個 URL。ybJ28資訊網——每日最新資訊28at.com

來看一個簡單的例子,首先定義一個文件上傳的 input 和一個 圖片預覽的 img:ybJ28資訊網——每日最新資訊28at.com

<input type="file" id="fileInput" /><img id="preview" />

再來使用 URL.createObjectURL() 將File 對象轉化為一個 URL:ybJ28資訊網——每日最新資訊28at.com

const fileInput = document.getElementById("fileInput");const preview = document.getElementById("preview");fileInput.onchange = (e) => {  preview.src = URL.createObjectURL(e.target.files[0]);  console.log(preview.src);};

可以看到,上傳的圖片轉化成了一個 URL,并顯示在了屏幕上:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

那這個 API 有什么意義呢?可以將Blob/File對象轉化為URL,通過這個URL 就可以實現文件下載或者圖片顯示等。ybJ28資訊網——每日最新資訊28at.com

當我們使用createObjectURL()方法創建一個data URL 時,就需要使用revokeObjectURL()方法從內存中清除它來釋放內存。雖然瀏覽器會在文檔卸載時自動釋放 Data URL,但為了提高性能,我們應該使用revokeObjectURL()來手動釋放它。revokeObjectURL()方法接受一個Data URL 作為其參數,返回undefined。下面來看一個例子:ybJ28資訊網——每日最新資訊28at.com

const objUrl = URL.createObjectURL(new File([""], "filename"));console.log(objUrl);URL.revokeObjectURL(objUrl);

6. Base64

Base64 是一種基于64個可打印字符來表示二進制數據的表示方法。Base64 編碼普遍應用于需要通過被設計為處理文本數據的媒介上儲存和傳輸二進制數據而需要編碼該二進制數據的場景。這樣是為了保證數據的完整并且不用在傳輸過程中修改這些數據。ybJ28資訊網——每日最新資訊28at.com

在 JavaScript 中,有兩個函數被分別用來處理解碼和編碼 base64 字符串:ybJ28資訊網——每日最新資訊28at.com

  • atob():解碼,解碼一個 Base64 字符串;
  • btoa():編碼,從一個字符串或者二進制數據編碼一個 Base64 字符串。
btoa("JavaScript")       // 'SmF2YVNjcmlwdA=='atob('SmF2YVNjcmlwdA==') // 'JavaScript'

那 base64 的實際應用場景有哪些呢?其實多數場景就是基于Data URL的。比如,使用toDataURL()方法把 canvas 畫布內容生成 base64 編碼格式的圖片:ybJ28資訊網——每日最新資訊28at.com

const canvas = document.getElementById('canvas'); const ctx = canvas.getContext("2d");const dataUrl = canvas.toDataURL();

除此之外,還可以使用readAsDataURL()方法把上傳的文件轉為base64格式的data URI,比如上傳頭像展示或者編輯:ybJ28資訊網——每日最新資訊28at.com

<input type="file" id="fileInput" /><img id="preview" />
const fileInput = document.getElementById("fileInput");const preview = document.getElementById("preview");const reader = new FileReader();fileInput.onchange = (e) => {  reader.readAsDataURL(e.target.files[0]);};reader.onload = (e) => {  preview.src = e.target.result;  console.log(e.target.result);};

效果如下,將圖片(二進制數據)轉化為可打印的字符,也便于數據的傳輸:ybJ28資訊網——每日最新資訊28at.com

圖片圖片ybJ28資訊網——每日最新資訊28at.com

另外,一些小的圖片都可以使用 base64 格式進行展示,img標簽和background的 url 屬性都支持使用base64 格式的圖片,這樣做也可以減少 HTTP 請求。ybJ28資訊網——每日最新資訊28at.com

7. 格式轉化

看完這些基本的概念,下面就來看看常用格式之間是如何轉換的。ybJ28資訊網——每日最新資訊28at.com

(1)ArrayBuffer → blob

const blob = new Blob([new Uint8Array(buffer, byteOffset, length)]);

(2)ArrayBuffer → base64

const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));

(3)base64 → blob

const base64toBlob = (base64Data, contentType, sliceSize) => {  const byteCharacters = atob(base64Data);  const byteArrays = [];  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {    const slice = byteCharacters.slice(offset, offset + sliceSize);    const byteNumbers = new Array(slice.length);    for (let i = 0; i < slice.length; i++) {      byteNumbers[i] = slice.charCodeAt(i);    }    const byteArray = new Uint8Array(byteNumbers);    byteArrays.push(byteArray);  }  const blob = new Blob(byteArrays, {type: contentType});  return blob;}

(4)blob → ArrayBuffer

function blobToArrayBuffer(blob) {   return new Promise((resolve, reject) => {      const reader = new FileReader();      reader.onload = () => resolve(reader.result);      reader.onerror = () => reject;      reader.readAsArrayBuffer(blob);  });}

(5)blob → base64

function blobToBase64(blob) {  return new Promise((resolve) => {    const reader = new FileReader();    reader.onloadend = () => resolve(reader.result);    reader.readAsDataURL(blob);  });}

(6)blob → Object URL

const objectUrl = URL.createObjectURL(blob);

本文鏈接:http://www.www897cc.com/showinfo-26-76537-0.html談談JS二進制:File、Blob、FileReader、ArrayBuffer、Base64

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 五大基于Cesium的開源框架及其優劣勢,一文導讀

下一篇: 注意!Electron 無法獲取設備ID了!

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 丹巴县| 思南县| 休宁县| 洪洞县| 松桃| 措美县| 闻喜县| 高雄市| 井冈山市| 五大连池市| 西乡县| 绥中县| 天镇县| 古浪县| 潼南县| 贺州市| 玉门市| 伽师县| 无棣县| 北京市| 平乡县| 石景山区| 汝城县| 额敏县| 色达县| 深泽县| 枣强县| 大余县| 仪征市| 蓬莱市| 娄底市| 沾化县| 萨迦县| 海晏县| 礼泉县| 平利县| 北流市| 方正县| 青川县| 台江县| 白朗县|