成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

有趣的 JavaScript 格式轉(zhuǎn)換

fireflow / 2031人閱讀

摘要:位無符號整數(shù),長度個字節(jié),溢出處理為最大值。所以你拿到的英文字母編碼前后一樣的,但是漢字等字符就不同了。為了直接得到漢字的碼,使用其實(shí)還可以選擇使用處理漢字,但是英文又不能正常轉(zhuǎn)換了。

原文鏈接:https://ssshooter.com/2019-04...

之前做文件上傳和 canvas 修圖時接觸到幾個格式,這里打算整理一下他們的關(guān)系

Blob

使用 input 獲取文件時,你拿到的就是 file 對象,而 file 繼承于 blob,所以直接講比較陌生的 blob 吧。

BLOB (binary large object),二進(jìn)制大對象,是一個可以存儲二進(jìn)制文件的“容器”。

Blob 有什么用

使用 Blob 可以讓你在瀏覽器生成一個臨時文件,使用 URL.createObjectURL() 獲取他的鏈接,你就能像服務(wù)器文件一樣使用他。

let temp = new Blob(["hello fantasy"])
URL.createObjectURL(temp)
// 返回 "blob:https://ssshooter.com/1bf84bba-b53a-4155-8348-33a487e8ab7e"

返回的 url 前面是主機(jī),后面是一個唯一識別碼。

在創(chuàng)建這個臨時文件后,只要不關(guān)閉當(dāng)前頁面,這個文件就會一直存在于內(nèi)存,你需要主動運(yùn)行 URL.revokeObjectURL(url) 刪除引用。

從 Blob 中提取數(shù)據(jù)

在控制臺打出 blob 你根本不知道里面是啥,那么怎么讀取 blob 呢?

借助 FileReader,你可以把 Blob 讀取為 Buffer。

FileReader 對象允許 Web 應(yīng)用程序異步讀取存儲在用戶計算機(jī)上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對象指定要讀取的文件或數(shù)據(jù)。
var reader = new FileReader()
reader.addEventListener("loadend", function() {
  // reader.result 包含轉(zhuǎn)化為類型數(shù)組的blob
})
reader.readAsArrayBuffer(blob)
ArrayBuffer

經(jīng)過 FileReader 的讀取,你能看到計算機(jī)儲存數(shù)據(jù)的本質(zhì) —— 二進(jìn)制數(shù)據(jù)。

ArrayBuffer 的編輯

ArrayBuffer 類似數(shù)組,每一格放入 1Byte(8bit)數(shù)據(jù),也就是八位的 0 或 1,所以換成十進(jìn)制一格最大是 255.

例如:

ArrayBuffer 不能直接操作,而是要通過類型數(shù)組對象(下面列出來的)或 DataView 對象來操作,它們會將緩沖區(qū)中的數(shù)據(jù)表示為特定的格式,并通過這些格式來讀寫緩沖區(qū)的內(nèi)容。

Int8Array:8 位有符號整數(shù),長度 1 個字節(jié),溢出處理為 數(shù)值%(取模)255。

Uint8Array:8 位無符號整數(shù),長度 1 個字節(jié)。

Uint8ClampedArray:8 位無符號整數(shù),長度 1 個字節(jié),溢出處理為 255(最大值)。

Int16Array:16 位有符號整數(shù),長度 2 個字節(jié)。

Uint16Array:16 位無符號整數(shù),長度 2 個字節(jié)。

Int32Array:32 位有符號整數(shù),長度 4 個字節(jié)。

Uint32Array:32 位無符號整數(shù),長度 4 個字節(jié)。

Float32Array:32 位浮點(diǎn)數(shù),長度 4 個字節(jié)。

Float64Array:64 位浮點(diǎn)數(shù),長度 8 個字節(jié)。

對應(yīng)視圖的轉(zhuǎn)換還很神奇的,ArrayBuffer 是一個格子 8 位,也就是跟 xx8Array 是一樣的,自然不用轉(zhuǎn)換,而 16 之后的都是把每幾個格子合成一個。

// 創(chuàng)建 buffer
ab = new ArrayBuffer(4)
// 創(chuàng)建視圖
a = new Uint8Array(ab)
// 通過視圖操作 buffer
a[0] = 2
a[1] = 25
a[2] = 31
a[2] = 233

打印 ab 會輸出:

為了方便理解他們?nèi)绾无D(zhuǎn)換,我把他轉(zhuǎn)為 2 進(jìn)制:

// Int16Array
;["1100100000010", "11101001"]
// Int32Array
;["111010010001100100000010"]
// Uint8Array
;["10", "11001", "11101001", "0"]

可能還沒能看出來?那再在前面補(bǔ) 0:

// Int16Array
;["0001100100000010", "0000000011101001"]
// Int32Array
;["00000000111010010001100100000010"]
// Uint8Array
;["00000010", "00011001", "11101001", "00000000"]

這就很明顯能看出:要轉(zhuǎn)換就要在分組之后把同一組數(shù)據(jù)從右到左拼接。

不過我自覺一般不太會用到這么細(xì)致的 bit 操作(

canvas 與 buffer

另外,canvas 可以通過 ctx.createImageData() 得到 ImageData。

ImageData.data 就是一個 Uint8ClampedArray,里面順序放著圖片每一個像素的 rgba 值。你可以對這個 Uint8ClampedArray 進(jìn)行一系列操作,再用 canvas.toBlob 這個 buffer 變回 Blob,就完成了圖片編輯的操作。

通過這個操作,再結(jié)合一些卷積核相關(guān)知識,就能完成類似這個卷積核圖片修改器的功能。

Data Url

Data Url 是一個前綴為 data:協(xié)議,你可以借助這個協(xié)議在文檔中嵌入一些小文件(最常見就是內(nèi)聯(lián)圖片了),數(shù)據(jù)格式如下:

data:[][;base64],

mediatype 填入MIME 類型,MIME 也用于服務(wù)器返回數(shù)據(jù)時指定數(shù)據(jù)類型;base64 是一種編碼方式;后面接著就是數(shù)據(jù)本體。

幾個例子:

普通文字:data:,Hello%2C%20World!

base64 處理的文字:data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D

html 文檔:data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E

執(zhí)行 script 的 html 文檔:data:text/html,

base64

上面提到的 base64 不算是一種加密算法,它只是簡單地將每 3 個 8bit 字符轉(zhuǎn)換為 4 個 6Bit 字符(base64 只有 2^6 = 64 種字符,因此得名),這樣保證了傳輸中必定使用 ASCII 中可見字符,不會出奇怪的空白字符或是功能性標(biāo)志 。

由于是 3 個字符變 4 個,那么很明顯了,base64 編碼后,編碼對象的體積會變成原來的 4/3 倍。

特別要注意的是如果 bit 數(shù)不能被 3 整除,需要在末尾添加 1 或 2 個 byte(8 或 16bit),并且末尾的 0 不使用 A 而使用 =,這就是為什么 base64 有的編碼結(jié)果后面會有一或兩個等號。

喜聞樂見的舉例時間:

前置知識點(diǎn):utf8 與 unicode 的關(guān)系

你可以使用 charCodeAt() 獲取一個字符的 unicode 編碼(0 到 65535 之間的整數(shù)),但是 unicode 只是一個碼表,并不是一個具體的編碼方式,utf8 才是。所以你拿到的英文字母編碼前后一樣的,但是漢字(等字符)就不同了。

為了直接得到漢字的 utf8 碼,使用 TextEncoder(其實(shí)還可以選擇使用 encodeURIComponent 處理漢字,但是英文又不能正常轉(zhuǎn)換了)。

下面用 JavaScript 簡單寫個 base64 轉(zhuǎn)換流程:

var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Array.from(new TextEncoder().encode("碧藍(lán)幻想"))
  .map(val => val.toString(2).padStart(8, 0)) // 轉(zhuǎn)二進(jìn)制,補(bǔ)充到八位
  .join("")
  .replace(/([10]{6})/g, "$1,") // 每六位插個逗號用于拆分
  .split(",") // 拆分為每 6 位一組
  .map(val => parseInt(val.padEnd(6, 0), 2)) // 補(bǔ)充后面的 0(但是沒有補(bǔ)夠)
  .map(val => b64[val])
  .join("")

結(jié)果基本是對的,但是后面的 = 還是用了普通的 A 而且位數(shù)沒有加夠,所以上面轉(zhuǎn)換出來的不是標(biāo)準(zhǔn) base64,僅供參考

base64 算法參考

blob url 與 Data Url 對比

blob url

不需要做編碼,省了運(yùn)算資源

大小也不會改變

在不使用時需要手動刪除引用

關(guān)閉頁面鏈接自動廢棄

Data Url

需要編碼,且體積變大 1.3 倍

容易刪除

鏈接不變,保存了可以以后使用

參考

mdn Blob

mdn FileReader

mdn HTMLCanvasElement

阮一峰 ES6 arraybuffer

進(jìn)階 FileAPI 實(shí)現(xiàn)標(biāo)準(zhǔn)

javascript info - blob

附錄 N 進(jìn)制數(shù)的表示方法
// 10
var a = 10
// 8
var b = 0o1234567
// 或直接在前面加0,如果后面數(shù)字都小于8就自動變成8進(jìn)制
var c = 01234567
// 2
var d = 0b1010101110101
// 16
var e = 0xe87a90
N 進(jìn)制數(shù)轉(zhuǎn) 10 進(jìn)制
parseInt(0o1234567, 8)
parseInt(0b1010101110101, 2)
parseInt(0xe87a90, 16)
10 進(jìn)制數(shù)轉(zhuǎn) N 進(jìn)制
;(123456).toString(2)
;(123456).toString(8)
;(123456).toString(16)

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105969.html

相關(guān)文章

  • JavaScriptSource Map (sourceURL / sourceMappingUR

    摘要:常見的源碼轉(zhuǎn)換,主要是以下三種情況壓縮,減小體積。該項(xiàng)是一個數(shù)組,表示可能存在多個文件合并。第一層是行對應(yīng),以分號表示,每個分號對應(yīng)轉(zhuǎn)換后源碼的一行。在這個位中,左邊的第一位最高位表示是否連續(xù)。 這兩天完成了自己的個人任務(wù),準(zhǔn)備學(xué)習(xí)一下前輩們的經(jīng)驗(yàn)教訓(xùn),在項(xiàng)目組的文檔中發(fā)現(xiàn)了一個要求注意的點(diǎn),如下: Js文件的開頭可以加上類似//@ sourceURL=jquery.extends.j...

    renweihub 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<