В мире JS есть класс вещей, которые выглядят очень большими, но на самом деле очень просты: буферы. Позвольте мне представить этого парня сегодня.
что такое бинарный объект
Если вы когда-либо искали знания, связанные с буфером, вы должны были видеть следующих братьев:ArrayBuffer
,Uint8Array
,Uint16Array
,Uint32Array
,TypedArray
,Blob
,DataView
...
...
...
Тогда нетерпеливые одноклассники могут закрыть кучу вкладок для поиска 🙂
Так что же это за вещи? говорящийbuffer
Прежде всего, нам нужно разобраться во всех тонкостях этих вещей.
ArrayBuffer и его собратья
ArrayBuffer
Это самый простой двоичный объект, который является ссылкой на непрерывное пространство памяти фиксированной длины.
Хотя он и называется Array, к массивам он отношения по сути не имеет. Это штука для подачи заявки на область памяти, но что в ней находится, мы не знаем, она просто хранит кучу байт, и с ней нельзя напрямую манипулировать. Что, если мы хотим манипулировать этим пространством памяти? Это требует视图
парень
Uint8Array
,Uint16Array
,Uint32Array
, эти вещиПосмотреть. вы можете понять это какArrayBuffer
переводчики, но они переводят немного по-другому:
-
Uint8Array
БудуArrayBuffer
Каждый байт считается единицей. Каждая единица представляет собой число от 0 до 255. Причина 255 в том, что каждая единица состоит не более чем из 8 бит, что составляет мощность 2^8. -
Uint16Array
БудуArrayBuffer
Каждые 2 байта считаются единицей. Каждая единица представляет собой целое число от 0 до 65535. Принцип тот же, что и выше. -
Uint32Array
БудуArrayBuffer
Каждые 4 байта считаются единицей. Каждая единица представляет собой целое число от 0 до 4294967295. Принцип тот же, что и выше.
// 我们可以通过 BYTES_PER_ELEMENT 静态属性来得之视图单位的大小
const buf8 = new Uint8Array();
const buf16 = new Uint16Array();
const buf32 = new Uint32Array();
console.log(buf8.BYTES_PER_ELEMENT); // 1
console.log(buf16.BYTES_PER_ELEMENT); // 2
console.log(buf32.BYTES_PER_ELEMENT); // 4
TypedArray
TypedArray
как указано вышеUint8Array
Собирательное имя для тех парней. Они всеTypedArray
(типизированный массив) является формой этого.
Следует отметить, что на самом деле нет
TypedArray
этот конструктор. Это просто общий термин.
В дополнение к вышеописанному типу есть другие типы массивов, таких какFloat64Array
Ждать. Вы можете проверить MDN, здесь нечего сказать.
Blob
Blob
дасреда браузераДвоичный объект, который содержит необработанные данные, предоставленные наArrayBuffer
Нет необходимой связи, но они могут трансформироваться друг в друга. можно просто понимать какДругая форма, не такая низкоуровневаяArrayBuffer
DataView
DataView
является основой,Читать более гибкийArrayBuffer
Посмотреть.Из вышеизложенного мы знаем, например,Unit8Array
"переводчикам" (просмотрам) нравитсяArrayBuffer
, но иногда мы не хотим закреплять тип «перевод», например, я иногда хочу использовать 8 переводов, а иногда хочу использовать 16 переводов.DataView
Является более гибким взглядом, он может удовлетворить это необоснованное требование.
const buffer = new ArrayBuffer(16); // 分配一个内存空间
const view = new DataView(buffer); // 创建 DataView 视图
view.setUint32(0, 4294967295); // 从第 0 个空间开始,以 32 位的形式写入数据
// 有时候我想以 8 位的形式 “翻译” 这个内存空间,从偏移量 0 开始翻译
console.log(view.getUint8(0)); // 255
// 今天心情好,想以 16 位的形式 “翻译” 这个内存空间,从偏移量 0 开始读
console.log(view.getUint16(0)); // 65535
// 今天心情超好,想以 32 位的形式 “翻译” 这个内存空间,从偏移量 0 开始读
console.log(view.getUint32(0)); // 4294967295
Разберитесь с этими братьями
Зачем нужны бинарные объекты, ведь компьютеры общаются бинарно. Чтобы привести неуместный пример, вы не можете говорить по-китайски с французом, и он не поймет без волны переводов. То же самое и с компьютерами: если он не бинарный, то не поймет, и все языки со временем нужно будет переводить. Это также причина, по которой двоичный код эффективен, потому что по своей природе нет необходимости в переводе, и машина может его понять. Обобщите приведенные выше понятия:
-
ArrayBuffer
Это постоянная ссылка на память, которой нельзя напрямую манипулировать. Итак, нам нужно что-то вродеUnit8Array
Подождите несколько просмотров, чтобы «перевести» этого парня - Давайте назовем эту кучу просмотров
TypedArray
типизированный массив. Но на самом деле его не существуетTypedArray
Этот конструктор, это просто собирательное название этой группы представлений -
Blob
это еще одна форма двоичного объекта, в основном в среде браузера. -
DataView
более гибкий вид, более гибкая работаArrayBuffer
что такое буфер
Ближе к дому, впереди так много предзнаменований, я думаю, что все уже что-то знают о бинарных объектах. Так что же такое буфер?
Буфер — это кеш, способ обработки двоичных данных.Студенты с базовыми компьютерными знаниями должны знать, что компьютеры могут обрабатывать только двоичные данные, это верно, это то, что вы смотрите, когда смотрите фильмы.010101
Эта груда вещей, которые выглядели очень высокими. Будь то числа, строки, картинки, аудио и видео, на самом деле компьютер в итоге сохраняет кучу0101
. Иногда мы хотим обработать или переместить какие-то данные, а это значит, что мы должны «переместить» стопку0101
.
Вообще говоря, мы перемещаемся, пока процессор обрабатывает, чтобы параллелизм не тратил время впустую. Тогда возникает проблема: если перемещение выполняется быстрее, чем процессор, это означает, что будут некоторые данные, ожидающие использования процессором; если перемещение выполняется медленнее, чем процессор, то процессор должен ждать достаточного количества данных ( композиция имеет интерпретируемое целое значения) может продолжать действовать.
В идеале мы, конечно, надеемся, что время перемещения данных согласуется со временем обработки ЦП.После перемещения пакета ЦП просто завершите обработку предыдущего пакета, чтобы принять новый пакет. Но на самом деле это не может быть таким уж совпадением. Передача данных может быть быстрее процессора или медленнее процессора. В любом случае всегда есть место для хранения этих временно недоступных данных (данные, которые поступают заранее, сохраняются в этом месте, если скорость передачи выше, чем у ЦП; если она медленнее, чем у ЦП, этого места достаточно для хранения пакет данных, который можно использовать. Затем данные передаются процессору) Эта область называетсяБуфер, обычно пространство памяти используется в качестве пространства кэша.
Некоторые люди могут задаться вопросом, почему чтение ввода-вывода с диска в кеш памяти вместо того, чтобы процессор считывал данные непосредственно с диска? Это связано с тем, что скорость чтения и записи в памяти намного выше, чем у диска.В конечном счете, кэширование в высокоскоростной памяти должно заставить ЦП использовать данные быстрее, не дожидаясь ввода-вывода.
Буферы в узле
JS в первые годы не имеет буфера, пока ES6 не запущен.ArrayBuffer
эта вещь. Но Node работает на стороне сервера, а Buffer как раз нужен для Node. В первые дни Node реализовал набор нестандартных спецификаций Buffer. Объект Buffer можно создать с помощью конструктора Buffer. С включением Buffer в стандартную спецификацию js узел Buffer постепенно адаптировался к новой спецификации. Текущий буфер находится в глобальной области видимости, его не нужно импортировать, он готов к использованию.Uint8Array
Подкласс класса.
В узле есть много API для объектов Buffer, вы можете видетьофициальная документацияК пониманию. В дополнение к объектам Buffer, Stream и Readline также являются широко используемыми встроенными модулями бинарной обработки узла. Краткое введение в базовый API Buffer
-
Buffer.alloc(size[, fill[, encoding]])
Создать буферное пространство, можно заполнить указанными элементами, также можно указать тип кодировки -
Buffer.from()
хранить содержимое в буфере-
Buffer.from(array)
Создайте буферный массив buf,buf.values()
возвращает итерируемый объект -
Buffer.from(string[, encoding])
Создайте строку буфера, вы можете указать тип кодировки -
Buffer.from(buffer)
скопировать буферный объект
-
Какая польза
На первый взгляд кажется, что Buffer не имеет ничего общего с нашими обычными сценариями приложений. На самом деле, это отражается на каждом аспекте разработки нашего приложения.
Буфер в глазах фронтендеров
Начнем с более распространенных на переднем конце. В веб-разработке нам может понадобиться выполнить некоторую обработку файлов. НапримерЭкспорт в Excel, загрузка файлов, загрузка аватаров и многое другое.Эти операции на самом деле являются операциями над двоичными данными.
// 伪代码示例
// Blob 上传图片
// fileHandler 为前置工作伪代码
// FileReader 加载图片,cavans 压缩图片等
const canvas = fileHandler()
// 创建 Blob 对象和 FormData
canvas.toBlob(blob => {
this.imgBlob = blob
}, 'image/jpeg')
let formdata = new FormData()
formdata.append('file', this.imgBlob, 'img.jpeg')
// 上传图片
axios({
headers: {
"Content-Type": "multipart/form-data"
},
method: "post",
url: uploadUrl,
data: formdata
})
.then(res => {
// do something
})
.catch(err => {
// do something
});
Буфер в глазах большой передней части
Большой внешний интерфейс может включать в себя некоторые предварительные разработки, строительные леса, инструменты для упаковки и т. д. В настоящее время буфером можно управлять посредством потоковой передачи. НапримерЧтение файла конфигурации построчно, обрабатывать некоторые рабочие процессы веб-пакета, взаимодействовать с cli для чтения и записи файлов и т. д.
// 伪代码示例
// 逐行读取配置文件,个性化配置
const fs = require("fs");
const readline = require("readline");
// 创建可读流
const rl = readline.createInterface({
input: fs.createReadStream("theme.less"),
});
rl.on("line", (line: string) => {
if (line.trim().startsWith("configStart")) {
// 伪代码,处理变量
themeHandlerStart()
}
if (line.trim().startsWith("configStart")) {
// 伪代码,处理变量
themeHandlerEnd()
}
});
Сервер глазами Buffer
Для одноклассников сервера применение Buffer шире.
Например, сжатие и распаковка, такие как шифрование и дешифрование, десенсибилизация информации и т. д., фактически неотделимы от буфера.
Кроме того, поскольку буфер работает с двоичными объектами, его производительность и гибкость намного выше, чем у обычных API js.
- Например, когда требуется более быстрый ответ, эффективнее передать буфер напрямую по http, чем передавать строку.
- Например, когда сохранение журнала необходимо для экономии места, используйте разные кодировки для сжатия пространства и т. д.
Используйте буфер, чтобы согласовать взаимосвязь между временной и пространственной сложностью более свободно и гибко.
// 伪代码示例
// 压缩文件
const { createGzip } = require("zlib");
const { pipeline } = require("stream");
const { createReadStream, createWriteStream } = require("fs");
const gzip = createGzip();
const source = createReadStream("./package.json");
const destination = createWriteStream("./package.json.gz");
pipeline(source, gzip, destination, (err) => {
if (err) {
console.error("发生错误:", err);
process.exitCode = 1;
}
});