主頁 > 企業開發 > 深入理解前端位元組二進制知識以及相關API

深入理解前端位元組二進制知識以及相關API

2023-05-10 11:09:27 企業開發

當前,前端對二進制資料有許多的API可以使用,這豐富了前端對檔案資料的處理能力,有了這些能力,就能夠對圖片等檔案的資料進行各種處理,
本文將著重介紹一些前端二進制資料處理相關的API知識,如Blob、File、FileReader、ArrayBuffer、TypeArray、DataView等等,

位元組

在介紹各種API之前,我們需要先了解下和位元組有關的知識,

我們知道,計算機是二進制的世界,而位元組(byte)是計算機技術中關于二進制資料的一種基本單位,1位元組有8個二進制位,即8位元(bit),

位元又叫位,一位二進制資料要么是0、要么是1,只有兩種狀態,所以1位元有2種狀態,
1位元組有8位元,即8個二進制位,那就能表示 2**8 = 256 種狀態,取值從 00000000 到 11111111,

位元組作為基本單位,在很多地方都被使用,如字符編碼知識,見前文前端需要了解的編碼知識,

二進制資料在存盤的時候,以位元組為單位,這里還涉及到一個關于位元組序的知識,

位元組序

位元組序描述的是計算機如何存盤位元組,
因為我們知道,記憶體存盤都有索引地址,每個位元組對應一個索引地址,一個位元組存盤8位二進制,即0到255之間,但需要存盤大于255的數值的時候,就需要多個位元組,多個位元組就涉及到排序問題,
所以位元組序就是:當需要多個位元組表示一個值的時候,這多個位元組使用什么樣的排序方式在記憶體中進行存盤,
而排序方式主要是兩種:大端存盤(big-endian)和小端存盤(little-endian),

大端存盤和小端存盤

大端存盤又稱大位元組序、高位元組序,方式是低位位元組排在記憶體中的高地址端,高位元組位排放在記憶體中的低地址端,圖片檔案 png、jpg都是這種方式,
小端存盤又稱為小位元組序、低位元組序,方式是低位位元組排在記憶體中的低地址端,高位位元組排在記憶體中的高地址端,圖片檔案gif是小端序,

示例

當我們使用不同的位元組序存盤數字 0x12345678 (這里是16進制表示,對應的十進制:305419896,進制相關知識可見前文Javascript中的進制和進制轉換:

大端存盤在記憶體中的存盤地址:
image
小端存盤在記憶體中的存盤地址:
image

這里數字位元組的高-低位是從左到右,最高位是 12,最低位是 78;而記憶體中存盤時從左到右是低地址——高地址,
所以在大端序中高位位元組的 12 在記憶體最左邊的低地址位,而低位元組位 78 則在記憶體最右邊的高地址位;而小端序則正好相反,

從視覺習慣上,大端存盤似乎更順眼,但無論哪種方式,計算的結果都是一樣的,只是在計算的時候需要處理這個排序方式,下文會涉及到,

Blob

Blob,即 Binary large Object,本質上是一個二進制物件,該物件表示的是一個不可變、原始資料的類檔案物件,
它的不可變,代表它是只讀的,不可被改變,

Blob物件的建構式語法:new Blob(array, options)

引數array:是一個資料陣列,可以是多種物件的資料,包含 ArrayBuffer、Blob、String 等等,
引數options:可選物件,指定兩個屬性:

type 表示Blob物件資料的MIME型別;
endings 指定包含行結束符\n的字串如何寫入,

我們可以使用建構式直接創建一個新的 Blob 物件:

const blob = new Blob(['123456789'], {type : 'text/plain'});

新創建的物件實體,結構如下:

image

從以上示例,我們就可以看到Blob物件的方法和屬性:

  • 實體屬性
    • size:Blob物件中資料的位元組大小
    • type:字串,表示Blob物件資料的MIME型別
  • 示例方法
    • arrayBuffer():回傳包含Blob所有內容的二進制格式的ArrayBuffer的一個promise物件
    • stream():回傳能讀取Blob的ReadableStream物件
    • text():回傳包含Blob所有內容的字串(UTF-8編碼)的一個promise物件
    • slice([start [, end [, contentType]]]):
      • 該方法有三個可選引數,可用于分割Blob資料
      • 它根據指定的起始和結束位置,回傳原Blob在該范圍的資料,得到一個新的Blob物件
      • 第三個引數 contentType 可以為新Blob物件指定自己的MIME型別

可以針對上面的 blob 實體進行操作:

blob.slice(0, 3).text().then(res => {
  console.log(res)
})
// 結果:123

以上代碼,使用slice()方法獲取原blob的前三位的資料,生成新的Blob實體后,通過text()方法列印出文本內容,

下面可以看看Blob在介面請求中的應用,Fetch API中的 Response 物件,擁有一個blob方法,能夠得到Blob物件,

const imgRequst = new Request('11.jpg')
fetch(imgRequst).then((response) => {
  return response.blob()
}).then((mBlob) => {
  console.log(mBlob)
})

通過以上代碼,請求一個jpg圖片檔案,回應物件通過 blob() 方法轉為Blob物件:

image

File

File物件繼承了Blob物件,是一種特殊型別的Blob,它擴展了對系統檔案的支持能力,
File提供檔案資訊,并能夠在javascript中進行訪問,一般在使用 <input> 標簽選擇檔案時回傳,因為 <input> 標簽允許選擇多個檔案,這里回傳的是檔案串列 files

除了 <input> 標簽以外,還有兩種方式回傳File物件:

  • 自由拖放操作生成的 DataTransfer 物件,
  • 檔案系統訪問API中的 FileSystemFileHandle 物件的 getFile() 方法,

File的建構式:new File(bits, name[, options])
有三個引數:

  • bits:是一個資料陣列,可以是多種物件的資料,與Blob物件類似
  • name:檔案名稱
  • options:可選屬性物件,包含兩個選項
    • type:MIME型別字串
    • lastModified:時間戳,表示檔案的最后修改時間

下面代碼,通過 <input> 標簽讀取檔案:

<input id="input-file" type="file" accept="image/*" />
document.getElementById('input-file').onchange = (e) => {
  const file = e.target.files[0]
  console.log(file)
  // ...
}

這是一個簡單的圖片上傳,獲取到的file實體,控制臺列印出來:

image

通過上圖(chrome瀏覽器下),可以看到File繼承了Blob的素有屬性和方法:

  • 屬性除了size和type以外,File還有自己的幾個屬性
    • lastModified:只讀,時間戳,檔案最后修改時間
    • name:只讀,檔案名
      lastModifiedDate:只讀,檔案最后修改時間的 Date 物件,該物件已廢棄
    • webkitRelativePath:非標準屬性,回傳path或URL
  • File沒有自己的實體方法,都繼承自Blob

對Blob和File的讀取

File繼承自Blob,都是只讀物件,除了使用slice分片以外,并沒有其他操作能力,所以如果對它們進行處理需要借助其他的API,
主要用于操作Blob的API有:FileReader、URL.createObjectURL()、createImageBitmap()和XMLHttpRequest.send(),下面將介紹這幾種方式,

Blob和File都是 WebAPI,是由瀏覽器環境提供的,而上面提到這四種物件也同樣是WebAPI,

FileReader

FileReader是用于異步讀取檔案型別(或原始資料緩沖區)的內容,指定Blob或File物件為需要讀取的檔案資料,

FileReader 不能在檔案系統中用路徑名的方式讀取檔案,

建構式:new FileReader()

如果對檔案處理功能開發較多,對FileReader物件應該較熟,我們先看一個示例:

document.getElementById('input-file').onchange = (e) => {
  const file = e.target.files[0]
  const reader = new FileReader()
  reader.onload = async (event) => {
    const img = new Image()
    img.src = https://www.cnblogs.com/jimojianghu/p/event.target.result
  }
  reader.readAsDataURL(file)
}

以上代碼,就是很常用的,使用FileReader讀取一個圖片檔案的Base64資料,然后使用圖片物件加載,Base64知識,可參考前文深入理解Base64編碼字串,
這段代碼也涉及到FileReader對像的屬性、事件、方法,

FileReader的屬性事件和方法
  • 屬性(皆只讀)
    • error:在讀取檔案時發生的錯誤
    • readyState:表示當前讀取狀態
      常量名 狀態描述
      EMPTY 0 沒有加載
      LOADING 1 正在加載
      DONE 2 已完成全部讀取
    • result:檔案內容,讀取狀態完成時才有效
  • 方法
    • abort():中止讀取操作,在回傳時,readyState屬性為DONE
    • readAsArrayBuffer():以ArrayBuffer型別讀取Blob中的內容
    • readAsBinaryString():以原始二進制資料型別讀取Blob中的內容
    • readAsDataURL():以Base64字串型別讀取Blob中的內容
    • readAsText():以文本字串型別讀取Blob中的內容
  • 事件
    • onabort:讀取操作被中斷時觸發
    • onerror:讀取操作發生錯誤時觸發
    • onload:讀取操作完成時觸發
    • onloadstart:讀取操作開始時觸發
    • onloadend:讀取操作結束時觸發
    • onprogress:讀取Blob時觸發

URL.createObjectURL()

URL是瀏覽器環境提供的,用于處理url鏈接的一個介面物件,可以通過它,決議、構造、規范和編碼各種url鏈接,
而URL提供的一個靜態方法 createObjectURL(),可以用來處理Blob和File檔案物件,

先看一個例子:

document.getElementById('input-file').onchange = (e) => {
  const file = e.target.files[0]
  const url = URL.createObjectURL(file)
  const img = new Image()
  img.onload = () => {
    document.body.append(img)
  }
  img.src = https://www.cnblogs.com/jimojianghu/p/url
}

頁面展示:

image

這段代碼就實作了上傳圖片,通過 URL.createObjectURL 讀取后生成一個本地映射的url,再使用Image物件加載圖片,
通過查看頁面元素,可以看到新添加的圖片元素,它的src是一個類似鏈接的字串:blob:http://localhost:8088/29c8f4a5-9b47-436f-8983-03643c917f1c,通過這個字串,圖片就能加載顯示出來,
再來看 createObjectURL(),它回傳一個包含給定的Blob或File物件的url,就可以當做檔案資源被加載,而這個url的生命周期和它的視窗同步,視窗關閉這個url就自動釋放了,

這個url就是被稱為偽協議的Objct URL,

Object URL

Object URL 又被稱為Blob URL,一般使用Blob或File物件生成,通過 URL.createObjectURL() 方法創建一個唯一的URL,
Object URL的格式為:blob:origin/唯一標識(uuid)

上面生成的URL字串就符合這個格式:blob:http://localhost:8088/29c8f4a5-9b47-436f-8983-03643c917f1c

  • origin 對應的 http://localhost:8088/,如果直接打開本地html檔案,則origin為null,
  • uuid 對應 29c8f4a5-9b47-436f-8983-03643c917f1c

瀏覽器內部會為生成Object URL保持一個 URLBlob 的映射,Blob是留存在記憶體中,瀏覽器只有在卸載當前視窗檔案時才會釋放,

如果要手動釋放,則需要URL的另外一個靜態方法:URL.revokeObjectURL(),它用于銷毀之前創建的URL實體,在合適的時機呼叫即可銷毀Object URL,

URL.revokeObjectURL(url)

XMLHttpRequest.send()

XMLHttpRequest.send(body):用于在XHR的HTTP請求中,發送資料體,
這里的body引數,可以是多種資料型別,包括Blob物件,

const xhr = new XMLHttpRequest()
xhr.send(new Blob())

createImageBitmap()

createImageBitmap(): 主要處理圖片資源,接受不同的圖片資源物件為引數,并生成一個ImageBitmap物件,
這些引數就就可以是Blob和File物件,

ImageBitmap表示可以繪制在canvas上的位圖影像,

createImageBitmap(file).then(imageBitmap => {
  const canvas = document.createElement('canvas')
  canvas.width = imageBitmap.width
  canvas.height = imageBitmap.height
  const ctx = canvas.getContext('2d')
  ctx.drawImage(imageBitmap, 0, 0)
  document.body.append(canvas)
})

如上代碼,即可讀取圖片檔案,使用canvas繪制,

ArrayBuffer

ArrayBuffer 物件表示通用的、固定長度的原始二進制緩沖區,它是一個位元組陣列,但不能直接操作它的內容,而需要通過其他方式(如TypeArray或DataView等)進行處理,

建構式:new ArrayBuffer(length),回傳一個指定大小的ArrayBuffer物件,
引數length:要創建的 ArrayBuffer 的位元組大小,大于Number.MAX_SAFE_INTEGER(>= 2 ** 53)或為負數,則拋出一個RangeError例外,

下面我們先使用前面介紹的 FileReader 讀取一個檔案的ArrayBuffer內容:

document.getElementById('input-file').onchange = (e) => {
  const file = e.target.files[0]
  const reader = new FileReader()
  reader.onload = async (event) => {
    console.log(event.target.result)
  }
  reader.readAsArrayBuffer(file)
}

控制臺日志列印輸出:

image

從上圖,可以看到ArrayBuffer的實體屬性和方法:

  • byteLength:表示位元組大小,不可改變
  • slice(begin[, end]):根據指定位置范圍回傳一個新的ArrayBuffer,可以分割ArrayBuffer,

ArrayBuffer還有靜態屬性和方法:

  • ArrayBuffer.length:建構式的length屬性,值為1
  • ArrayBuffer.isView(arg):如果引數是ArrayBuffer的視圖實體則回傳true,

由于我們無法直接操作ArrayBuffer,所以需要使用其他物件來處理,下面將介紹其中兩種,

TypeArray

TypeArray,即型別化陣列,它描述了二進制資料緩沖區的一個類陣列,TypeArray本身不是一個可用的物件,只是一個輔助的資料型別,作為所有型別陣列的構造原型,真正可用的型別陣列包含了多種,如Int8Array、Uint8Array等,
常用的型別陣列如下表所示:

物件 元素所占位元組數 取值范圍 描述
Int8Array 1 -128 - 127 8 位有符號整型陣列
Uint8Array 1 0 - 255 8 位無符號整型陣列
Uint8ClampedArray 1 0 - 255 8 位無符號整型固定陣列
Int16Array 2 -32768 - 32767 16 位有符號整型陣列
Uint16Array 2 0 - 65535 16 位無符號整型陣列
Int32Array 4 -2147483648 - 2147483647 32 位有符號整型陣列
Uint32Array 4 0 - 4294967295 32 位無符號整型陣列
Float32Array 4 1.2×10**-38 to 3.4×10**38 32 位浮點數型陣列
Float64Array 8 5.0×10**-324 to 1.8×10**308 64 位浮點數型陣列
BigInt64Array 8 -2**63 to 2**63-1 64 位有符號數型陣列
BigUint64Array 8 0 to 2**64-1 64 位無符號整型陣列

型別化陣列與普通資料也較相似,同樣擁有一系列的方法和屬性,但不支持 pushpopshiftunshiftsplice 等可以改變原陣列的增刪改方法,
型別化陣列由于定義了資料型別,則各元素必須是同型別的資料,不能像普通資料那樣元素可以是不同型別;當元素資料型別固定統一時,處理效率更優,

各型別陣列在建構式、屬性、方法等語法上相同,下面就以 Uint8Array 為例,

語法

Uint8Array建構式:

new Uint8Array()
new Uint8Array(length)
new Uint8Array(typedArray)
new Uint8Array(object)
new Uint8Array(buffer [, byteOffset [, length]])

length 引數的最大取值

8 位類陣列是 2145386496
16 位類陣列是 1072693248
32 位類陣列是 536346624
32 位類陣列是 268173312

靜態屬性和方法

  • BYTES_PER_ELEMENT:回傳陣列元素所占位元組數,Uint8Array中的值是1,Uint32Array中的值是4,見上表
  • length:固定長度,Uint8Array中的值是1,Uint32Array中的值是3,基本沒用
  • name:型別陣列回傳自己的構造名,Uint8Array型別回傳 Uint8Array,Uint32Array型別回傳 Uint32Array 等等
  • from(source[, mapFn[, thisArg]]):從源型別陣列中回傳一個新的陣列
  • of(element0[, element1[, ...[, elementN]]]):創建一個具有可變數量引數的新型別陣列

實體屬性和方法

介紹完靜態屬性和方法,下面通過一個示例,來查看下Uint8Array的實體屬性和方法,代碼如下,

const reader = new FileReader()
reader.onload = async (event) => {
  const aBuffer = event.target.result
  const uint8Array = new Uint8Array(aBuffer)
  console.log(uint8Array)
}
reader.readAsArrayBuffer(file)

以上代碼,直接讀取檔案的ArrayBuffer資料,然后通過 Uint8Array 建構式,得到Uint8Array實體,控制臺查看:

image

通過加載一張png圖片,得到它的Uint8Array陣列資料,可以看到型別陣列大部分的屬性和方法都和普通陣列類似,除了前文提到的增刪改陣列的方法以外,因此,對型別陣列使用下標、回圈等等方式進行讀取,和普通函式沒什么兩樣,

而型別陣列也自己的特殊屬性(都只讀)和方法,如下:

  • buffer:回傳型別陣列參考的ArrayBuffer
  • byteLength:位元組數長度
  • byteOffset:相對源ArrayBuffer的偏移位元組數
  • length:陣列長度
  • set(array[, offset]):從給定陣列中讀取元素值,并存盤在型別陣列中
  • subarray(begin, end):給定開始和結尾索引,回傳一個新的型別陣列

型別陣列間的關系

要了解常見型別陣列間的關系,我們先看下面這張圖:

image

圖上所示,是一張png圖片的ArrayBuffer資料,可以看到,ArrayBuffer的位元組長度屬性默認取8位整型陣列的長度,即與Int8Array和Uint8Array的長度一致,
而Int8Array的長度29848,正好是Int16Array的長度14924的兩倍,是Int32Array的長度7462的四倍,可知,這里就是對位元組的合并計算:

  • Int8Array(Uint8Array) 轉 Int16Array(Uint16Array),需要依序合并兩個位元組后計算數值,
  • Int8Array(Uint8Array) 轉 Int32Array(Uint32Array),需要依序合并四個位元組后計算數值,
  • Int16Array(Uint16Array) 轉 Int32Array(Uint32Array),需要依序合并兩個位元組后計算數值,

讀取GIF檔案示例

型別陣列通過陣列的方式對ArrayBuffer的內容進行讀取操作,可以方便我們處理檔案的二進制資料,
但使用型別陣列的時候,碰到多位元組的資料時,需要考慮位元組序的問題,

下面,我們以讀取小端存盤的GIF圖片為例,

GIF圖片的Uint8Array陣列資料中,寬高資料的存盤就是使用了兩個位元組,第7-8位存盤圖片的寬度,9-10位存盤圖片的高度,

我們加載的GIF圖片寬高皆為600,需要處理位元組序,代碼如下:

const uint8Array = new Uint8Array(aBuffer)
let bufferIndex = 6
// 獲取GIF寬度的兩個位元組的值
const width1 = uint8Array[bufferIndex]
// width1 結果:88
const width2 = uint8Array[bufferIndex + 1]
// width2 結果:2

// 得到各自的16進制資料
const width1hex = width1.toString(16)
const width2hex = width2.toString(16)
// 轉換成實際的寬度大小,注意這里把兩個位元組的順序做了調整,符合小端序
const width = parseInt(width2hex + width1hex, 16)
// width 結果:600

使用小端序處理后,寬度結果等于600,符合圖片實際寬度,
自己手動處理位元組序會稍顯麻煩,如果不想手動去處理位元組序的問題,可以使用另外一個物件:DataView

DataView

DataView 是一個從 ArrayBuffer 中讀取多種型別數值并且不用考慮位元組序的介面物件,它的使用簡單方便,擁有一系列的 get-set- 實體方法操作資料,

DataView的建構式:new DataView(buffer [, byteOffset [, byteLength]])
引數:

  • buffer:源ArrayBuffer
  • byteOffset:buffer中的位元組偏移量
  • byteLength:位元組長度

DataView不用考慮位元組序,同樣是讀取GIF的寬度時,代碼可簡化:

const fileDataView = new DataView(arrBuffer)
let bufferIndex = 6
const width = fileDataView.getUint16(bufferIndex, true)
// 結果:600
bufferIndex += 2
const height = fileDataView.getUint16(bufferIndex, true)
// 結果:600

以上代碼,很方便就得到GIF圖片的寬高資料(600),因為使用了 DataView 和它的 getUint16 方法,不需要手動處理位元組序,
getUint16 方法有兩個引數:第一個引數代表位元組索引;第二引數表示位元組序,默認大端序,為true則是小端序,GIF是小端,所以上面代碼為true,
除了getUint16以外,DataView 還有十多個類似的實體方法,

DataView的get和set系列方法

get系列方法通過位元組偏移索引獲取對應的數值,其中多位元組的資料,需要兩個引數:

  • byteOffset:讀取時的位元組偏移量
  • littleEndian:位元組序,默認大端,設為true則是小端
名稱 引數 描述
getInt8 (byteOffset) 有符號 8-bit 整數(1個位元組)
getUint8 (byteOffset) 無符號 8-bit 整數(1個位元組)
getInt16 (byteOffset [, littleEndian]) 16-bit數(短整型,2個位元組)
getUint16 (byteOffset [, littleEndian]) 16-bit數(無符號短整型,2個位元組)
getInt32 (byteOffset [, littleEndian]) 32-bit數(長整型,4個位元組)
getUint32 (byteOffset [, littleEndian]) 32-bit數(無符號長整型,4個位元組)
getFloat32 (byteOffset [, littleEndian]) 32-bit浮點數(單精度浮點數,4個位元組)
getFloat64 (byteOffset [, littleEndian]) 64-bit數(雙精度浮點型,8個位元組)
getBigInt64 (byteOffset [, littleEndian]) 帶符號的64位整數(long long型別)值
getBigUint64 (byteOffset [, littleEndian]) 無符號的64位整數(unsigned long long型別)值

set系列方法是和get方法對應的,處理相應位元組偏移索引位置的數值,引數如下:

  • byteOffset:讀取時的位元組偏移量
  • value:設定相應型別的數值
  • littleEndian:位元組序,默認大端,設為true則是小端
名稱 引數 描述
setInt8 (byteOffset, value) 8-bit數(一個位元組)
setUint8 (byteOffset, value) 8-bit數(無符號位元組)
setInt16 (byteOffset, value [, littleEndian]) 16-bit數(短整型)
setUint16 (byteOffset, value [, littleEndian]) 16-bit數(無符號短整型)
setInt32 (byteOffset, value [, littleEndian]) 32-bit數(長整型)
setUint32 (byteOffset, value [, littleEndian]) 32-bit數(無符號長整型)
setFloat32 (byteOffset, value [, littleEndian]) 32-bit數(浮點型)
setFloat64 (byteOffset, value [, littleEndian]) 64-bit數(雙精度浮點型)
setBigInt64 (byteOffset, value [, littleEndian]) 帶符號的64位整數(long long型別)值
setBigUint64 (byteOffset, value [, littleEndian]) 無符號的64位整數(unsigned long long型別)值

Blob和ArrayBuffer

對于Blob和ArrayBuffer兩個物件,我們可以稍做總結:

  1. Blob是Web API,瀏覽器環境提供,讀取它可以使用FileReader、URL.createObjectURL等WebAPI;ArrayBuffer是JS語言內置物件,處理它則需要使用TypeArray、DataView等JS-API,
  2. Blob表示不可變的類檔案資料;ArrayBuffer則表示原始資料緩沖區,
  3. Blob用于讀取類檔案資料,不對應記憶體;ArrayBuffer用于讀取記憶體資料,
  4. Blob和ArrayBuffer都需要通過其他物件才能操作資料,
  5. Blob和ArrayBuffer可以使用不同方式進行相互之間的轉換,
  6. 要操作位元組二進制資料,得依賴ArrayBuffer和輔助它的操作物件,

Blob和ArrayBuffer之間的轉換:

  • 使用Blob建構式可以讀取ArrayBuffer,生成一個新的Blob,
  • 通過Blob實體的arrayBuffer()方法,可以獲取到對應的ArrayBuffer,
  • 通過FileReader物件的readAsArrayBuffer()方法,將Blob讀取為ArrayBuffer,

如下代碼:

const aBuffer = new ArrayBuffer(4)
// 使用Blob建構式
const blob = new Blob([aBuffer])
// Blob的arrayBuffer()方法(promise)
blob.arrayBuffer()
// FileReader
const reader = new FileReader()
reader.readAsArrayBuffer(blob)

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/552094.html

標籤:JavaScript

上一篇:配置式表單渲染器的實作

下一篇:返回列表

標籤雲
其他(158765) Python(38125) JavaScript(25413) Java(18025) C(15225) 區塊鏈(8263) C#(7972) AI(7469) 爪哇(7425) MySQL(7175) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5871) 数组(5741) R(5409) Linux(5338) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4570) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1972) 功能(1967) Web開發(1951) HtmlCss(1935) python-3.x(1918) 弹簧靴(1913) C++(1913) xml(1889) PostgreSQL(1875) .NETCore(1860) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 深入理解前端位元組二進制知識以及相關API

    當前,前端對二進制資料有許多的API可以使用,這豐富了前端對檔案資料的處理能力,有了這些能力,就能夠對圖片等檔案的資料進行各種處理。 本文將著重介紹一些前端二進制資料處理相關的API知識,如Blob、File、FileReader、ArrayBuffer、TypeArray、DataView等等。 ......

    uj5u.com 2023-05-10 11:09:27 more
  • 配置式表單渲染器的實作

    我們是袋鼠云數堆疊 UED 團隊,致力于打造優秀的一站式資料中臺產品。我們始終保持工匠精神,探索前端道路,為社區積累并傳播經驗價值。。 本文作者:奇銘(掘金) 需求背景 前段時間,離線計算產品接到改造資料同步表單的需求。 一方面,資料同步模塊的代碼可讀性和可維護性比較差,相對應的,在資料同步模塊開發新 ......

    uj5u.com 2023-05-10 11:08:42 more
  • 關于華為MetaERP,我說幾句

    關于華為MetaERP,我說幾句 作為一個ERP(SAP ERP)咨詢行業的老兵,筆者對于華為的MetaERP充滿期待,它代表了高端國產ERP系統的未來! MetaERP的出現,使得國產高端ERP系統實作了從無到有的突破。在長遠的可以預計的未來,華為的MetaERP將會給以SAP/Oracle為代表 ......

    uj5u.com 2023-05-10 11:08:07 more
  • 關于華為MetaERP,我說幾句

    關于華為MetaERP,我說幾句 作為一個ERP(SAP ERP)咨詢行業的老兵,筆者對于華為的MetaERP充滿期待,它代表了高端國產ERP系統的未來! MetaERP的出現,使得國產高端ERP系統實作了從無到有的突破。在長遠的可以預計的未來,華為的MetaERP將會給以SAP/Oracle為代表 ......

    uj5u.com 2023-05-10 11:07:39 more
  • 如何在VSCode Webview中打開一個新的頁面

    上一篇我介紹了如何在VSCode Webview中實作點擊鏈接下載圖片或檔案,本文介紹如何在默認瀏覽器中打開一個新的頁面。 在瀏覽器中,如果要實作打開一個新的頁面有許多種不同的方法,例如: window.open("https://www.cnblogs.com/jaxu", "_blank"); ......

    uj5u.com 2023-05-10 09:05:59 more
  • ReactHub:我用 ChatGPT 搞了一個 React 的資源導航網站,誰有我用心

    大家好,我是DOM哥。 圖譜年年有,今年我來盤! 之前已經盤完了 Vue 的技術圖譜,今天來盤 React 的。不管你是資深 React 用戶,還是剛入門想學習 React 的小白,相信都能幫助到你 ......

    uj5u.com 2023-05-10 08:59:14 more
  • 記錄--前端實作點擊選詞功能

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 今天有一個需求,點擊選中某個英文單詞,然后對這個單詞做一些處理,例如高亮背景、查看一些詳細資訊等等,今天簡單實作了一下,效果如下:(支持移動端,chrome和sarafi瀏覽器均能正常使用。語言🚀 vue3 + typescript) ......

    uj5u.com 2023-05-10 08:52:49 more
  • 學node 之前你要知道這些

    初識nodejs 19年年底一個偶然的機會接到年會任務,有微信掃碼登錄、投票、彈幕等功能,于是決定用node 來寫幾個服務,結果也比較順利。 當時用看了下koa2的官方檔案,知道怎么連接資料庫、怎么映射表物體,怎么處理http,怎么處理例外等,就可以直接寫起來了。從應用層面上來說 nodejs 入門 ......

    uj5u.com 2023-05-10 08:47:38 more
  • HTML常用標簽

    1. 基礎語法 1.1 標記(標簽) - 常規標記(雙標記) <標記></標記> - 空標記(單標記) <標記 /> 1.2 <!DOCTYPE html> 檔案型別 1.3 <html lang="zh-CN"> 為瀏覽器指出本檔案所用語言 1.4 <meta /> - <meta charset ......

    uj5u.com 2023-05-10 08:47:30 more
  • js中的變數

    在JavaScript中,我們用var關鍵字來宣告一個變數,var關鍵字后緊跟變數的名稱,例如: var a1 = 40; a1就是變數的名稱,用來標識一個變數,所以它又稱為變數的識別符號。一個變數的識別符號必須是由字母、數字、下劃線組成,但首字符不能為數字,如: 1user、#user 都不是正確的標 ......

    uj5u.com 2023-05-10 08:47:25 more