当前位置: 首页 > news >正文

前端二进制数据指南:从 ArrayBuffer 到高级流处理

前端开发中,二进制数据是处理文件、图像、音视频、网络通信等场景的基础。以下是核心概念和用途的通俗解释:

前端二进制数据介绍

1. 什么是前端二进制数据?

指计算机原始的 0 和 1 格式的数据(比如一张图片的底层代码),前端通过特定 API 操作这些数据。


2. 核心用途

  • 文件操作
    上传/下载文件(如用户传图片)、切片大文件(断点续传)。

  • 图像处理
    修改图片像素(滤镜、裁剪)、Canvas 绘图。

  • 网络通信
    WebSocket 传输二进制帧、AJAX 上传二进制数据。

  • 高性能计算
    WebAssembly 运行编译型代码(如游戏、加密算法)。


3. 关键 API 速览

API作用示例场景
ArrayBuffer存储原始二进制数据文件解析、网络数据接收
Uint8Array按字节操作数据(8位无符号整数)图像像素处理
Blob表示文件类数据(不可变)文件分片上传
FileReader读取本地文件内容图片预览(转Base64)
Canvas操作图像像素数据实时滤镜效果

4. 为什么需要二进制操作?

  • 性能更高:直接操作内存,比文本处理快。

  • 功能更强:实现文件编辑、音视频解码等复杂功能。

  • 节省带宽:二进制比文本格式(如JSON)体积更小。

前端二进制数据核心类型对比表

类型/API继承关系使用场景核心优势
ArrayBuffer基础容器,无继承关系存储原始二进制数据,如网络传输、文件解析、WebAssembly 内存操作直接操作内存,性能极高
TypedArray基于 ArrayBuffer 的视图(如 Uint8Array类型化数据处理(图像像素、音频采样、网络协议解析)类型明确,自动处理字节对齐,简化操作
DataView基于 ArrayBuffer 的视图处理混合数据类型或需要控制字节序的场景(如解析二进制文件格式、网络协议)灵活读写不同数据类型,支持手动控制字节序
Blob无继承关系处理不可变的类文件数据(文件分片上传、生成临时 URL)支持大文件分片(Blob.slice()),可直接用于 fetch 或 FormData
File继承自 Blob表示用户上传的本地文件(通过 <input type="file"> 获取)包含文件名、类型、修改时间等元信息
FileReader无继承关系异步读取 Blob 或 File 内容(转为 ArrayBufferDataURL、文本等)支持多种读取格式,兼容浏览器文件操作
ImageData包含 Uint8ClampedArray操作 Canvas 像素数据(图像滤镜、特效处理)直接映射到 Canvas 像素,RGBA 格式标准化
Streams API基于 ReadableStream/WritableStream流式处理大文件(如视频分块加载、实时数据传输)分块处理数据,避免内存溢出,提升性能
WebAssembly通过 ArrayBuffer 加载模块高性能计算(游戏、音视频编码、密码学算法)接近原生代码性能,支持 C/C++/Rust 编译运行

二进制数据核心类型关键关联说明

  1. 继承链

    • File → Blob → 所有文件相关操作基于 Blob 扩展。

    • TypedArray/DataView → ArrayBuffer → 所有类型化操作依赖原始二进制缓冲区。

  2. 协作流程示例

    • 文件上传
      File → FileReader → ArrayBuffer → TypedArray(处理数据) → fetch 上传。

    • 图像处理
      Blob → Image → Canvas → ImageData(像素操作) → 显示结果。

    • WebAssembly
      .wasm → ArrayBuffer → 编译实例化 → 调用高性能函数。

 快速对比示例

// 1. Blob → ArrayBuffer → TypedArray
const blob = new Blob([new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f])]); // "Hello"
blob.arrayBuffer().then(buffer => {const uint8 = new Uint8Array(buffer);console.log(uint8); // Uint8Array(5) [72, 101, 108, 108, 111]
});// 2. File → FileReader → ArrayBuffer
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {const file = e.target.files[0];const reader = new FileReader();reader.onload = () => {const buffer = reader.result;const dataView = new DataView(buffer);console.log("文件头:", dataView.getUint32(0));};reader.readAsArrayBuffer(file);
});

二进制数据核心类型总结

  • 底层核心ArrayBuffer 是二进制操作的基础,其他类型均围绕它扩展。

  • 文件处理Blob 和 File 用于文件级操作,FileReader 提供读取能力。

  • 数据视图TypedArray 和 DataView 提供灵活的内存操作方式。

  • 高性能场景WebAssembly 和 Streams API 解决计算和流式处理需求。

前端常用二进制数据介绍

1. ArrayBuffer

作用:最基础的二进制数据容器,表示通用的、固定长度的原始二进制数据缓冲区,不能直接操作,需通过 TypedArray 或 DataView 访问
优势:直接操作内存,性能极高,适合处理音频、视频等二进制数据。
使用场景:网络传输、文件解析、WebAssembly 内存操作。

区分:Buffer是Node.js 特有的二进制类型(等同于 Uint8Array),前端通常通过浏览器 API 或工具库(如 buffer polyfill)使用

<!DOCTYPE html>
<html>
<head><title>ArrayBuffer 示例</title>
</head>
<body><script>// 1. 创建一个 16 字节的 ArrayBufferconst buffer = new ArrayBuffer(16);// 2. 使用 TypedArray 操作数据const int32View = new Int32Array(buffer); // 每个元素占 4 字节int32View[0] = 42;                        // 写入数据int32View[1] = 1024;// 3. 通过另一个视图验证数据const uint8View = new Uint8Array(buffer);console.log("ArrayBuffer 内容(十六进制):");for (let i = 0; i < uint8View.length; i++) {console.log(uint8View[i].toString(16).padStart(2, '0'));}</script>
</body>
</html>

2. TypedArray

作用

  • 基于 ArrayBuffer 的视图,提供特定类型的二进制数据操作,包括:

    • Int8ArrayUint8Array(无符号字节)

    • Uint8ClampedArray(限制在 0-255,常用于图像处理)

    • Int16ArrayUint16Array

    • Int32ArrayUint32Array

    • Float32ArrayFloat64Array

    • BigInt64ArrayBigUint64Array(ES2020 引入,用于大整数)

优势:类型明确,无需手动处理字节细节。
使用场景:图像像素操作、音频数据处理。

<!DOCTYPE html>
<html>
<head><title>TypedArray 示例</title>
</head>
<body><script>// 1. 创建一个 4 字节的 ArrayBufferconst buffer = new ArrayBuffer(4);// 2. 使用不同类型视图操作同一 bufferconst uint8View = new Uint8Array(buffer);uint8View[0] = 0x12;  // 写入字节数据uint8View[1] = 0x34;const uint16View = new Uint16Array(buffer);console.log("Uint16 视图的值:", uint16View[0].toString(16)); // 输出 3412(小端序)const uint32View = new Uint32Array(buffer);console.log("Uint32 视图的值:", uint32View[0].toString(16)); // 输出 34120000</script>
</body>
</html>

3. DataView

作用:灵活读写 ArrayBuffer,支持混合数据类型和字节序控制。
优势:处理复杂二进制格式时更灵活。
使用场景:解析自定义协议、处理网络数据包

<!DOCTYPE html>
<html>
<head><title>DataView 示例</title>
</head>
<body><script>// 1. 创建一个 8 字节的 ArrayBufferconst buffer = new ArrayBuffer(8);const view = new DataView(buffer);// 2. 写入不同数据类型(大端序)view.setInt32(0, 0x12345678, false);  // 大端序写入 4 字节整数view.setFloat32(4, Math.PI, false);   // 大端序写入浮点数// 3. 读取数据console.log("整数:", view.getInt32(0, false).toString(16));console.log("浮点数:", view.getFloat32(4, false));</script>
</body>
</html>

4. Blob (Binary Large Object)

作用:不可变的类文件对象,常用于文件切片(slice())、下载或上传(如 fetch 的 FormData)
优势:适合处理大文件,可直接用于网络请求。
使用场景:文件下载、图片预览。

<!DOCTYPE html>
<html>
<body><button onclick="downloadFile()">下载 Blob 文件</button><script>function downloadFile() {// 1. 创建 Blob 内容const text = "Hello, Blob!";const blob = new Blob([text], { type: 'text/plain' });// 2. 生成临时 URL 并下载const url = URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = 'example.txt';a.click();URL.revokeObjectURL(url);}</script>
</body>
</html>

5. File 和 FileReader

File作用:读取用户本地文件内容,继承自 Blob,表示用户本地文件(通过 <input type="file"> 获取),包含文件名、类型等元数据

FileReader作用:用于异步读取 Blob 或 File 内容为 ArrayBufferDataURL 或文本
优势:直接获取文件元数据,支持异步读取。
使用场景:文件上传、图片预览。

<!DOCTYPE html>
<html>
<body><input type="file" id="fileInput"><div id="output"></div><script>document.getElementById('fileInput').addEventListener('change', function(e) {const file = e.target.files[0];const reader = new FileReader();// 1. 读取为文本reader.readAsText(file);reader.onload = () => {document.getElementById('output').innerHTML = `<p>文件名: ${file.name}</p><p>大小: ${file.size} 字节</p><p>内容: ${reader.result}</p>`;};});</script>
</body>
</html>

6. ImageData 和 Canvas

作用:操作 Canvas 的像素数据。
优势:直接修改图像像素,实现实时效果。
使用场景:图像滤镜、实时视频处理。

<!DOCTYPE html>
<html>
<body><canvas id="canvas" width="200" height="200"></canvas><script>const canvas = document.getElementById('canvas');const ctx = canvas.getContext('2d');// 1. 绘制原始图形ctx.fillStyle = 'red';ctx.fillRect(0, 0, 200, 200);// 2. 获取像素数据并反色const imageData = ctx.getImageData(0, 0, 200, 200);const data = imageData.data;for (let i = 0; i < data.length; i += 4) {data[i] = 255 - data[i];     // Rdata[i + 1] = 255 - data[i + 1]; // Gdata[i + 2] = 255 - data[i + 2]; // B}// 3. 写回修改后的像素ctx.putImageData(imageData, 0, 0);</script>
</body>
</html>

7. Streams API

作用:分块处理大型数据流,避免内存溢出。
优势:高效处理大文件,实时数据传输。
使用场景:视频流、大文件上传/下载。

<!DOCTYPE html>
<html>
<body><script>// 1. 创建一个简单的 ReadableStreamconst stream = new ReadableStream({start(controller) {controller.enqueue(new Uint8Array([72, 101, 108, 108, 111])); // "Hello"controller.close();}});// 2. 通过 Reader 读取数据块const reader = stream.getReader();reader.read().then(({ done, value }) => {if (!done) {console.log("流数据:", new TextDecoder().decode(value));}});</script>
</body>
</html>

8. WebAssembly

作用:运行高性能编译型代码(如 C/C++)。
优势:接近原生性能,适合计算密集型任务。
使用场景:游戏、音视频编码、加密算法。

<!DOCTYPE html>
<html>
<body><script>// 假设存在 add.wasm 文件,导出一个加法函数fetch('add.wasm').then(response => response.arrayBuffer()).then(buffer => WebAssembly.instantiate(buffer)).then(({ instance }) => {console.log("WASM 加法结果:", instance.exports.add(2, 3));});</script>
</body>
</html>

常用的二进制数据转换函数

1. 将 File 对象转换为 Blob 对象

/*** 将 File 对象转换为 Blob 对象(File 继承自 Blob,可直接切片)* @param {File} file - 用户上传的 File 对象* @returns {Blob} - 转换后的 Blob 对象*/
function fileToBlob(file) {// File 本身是 Blob 的子类,直接使用 slice 方法切割完整文件return file.slice(0, file.size, file.type);
}// 示例用法
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {const file = e.target.files[0];const blob = fileToBlob(file);console.log('File -> Blob:', blob);
});

2. 将 Blob 对象转换为 File 对象

/*** 将 Blob 转换为 File 对象(添加文件名和类型)* @param {Blob} blob - 需要转换的 Blob 对象* @param {string} fileName - 文件名(含扩展名,如 "image.jpg")* @param {string} [fileType] - 文件类型(如 "image/jpeg",默认使用 Blob 的 type)* @returns {File} - 转换后的 File 对象*/
function blobToFile(blob, fileName, fileType) {// 保留原始 Blob 的类型(若未指定 fileType)const type = fileType || blob.type;// 使用 File 构造函数创建对象(兼容性良好)return new File([blob], fileName, { type });
}// 示例用法
const blob = new Blob(['Hello, World!'], { type: 'text/plain' });
const file = blobToFile(blob, 'example.txt');
console.log('Blob -> File:', file);

3. 将 Blob 转换为 ArrayBuffer

/*** 异步将 Blob 转换为 ArrayBuffer* @param {Blob} blob - 需要转换的 Blob 对象* @returns {Promise<ArrayBuffer>} - 返回 Promise 包含 ArrayBuffer*/
function blobToArrayBuffer(blob) {return new Promise((resolve, reject) => {// 使用 FileReader 读取 Blobconst reader = new FileReader();reader.onload = () => resolve(reader.result); // 读取完成返回 ArrayBufferreader.onerror = () => reject(reader.error);  // 处理错误reader.readAsArrayBuffer(blob); // 关键 API 调用});
}// 示例用法
const blob = new Blob(['Hello']);
blobToArrayBuffer(blob).then(buffer => {console.log('Blob -> ArrayBuffer:', buffer);
});

4. 将 ArrayBuffer 转换为 Blob

/*** 将 ArrayBuffer 转换为 Blob 对象* @param {ArrayBuffer} buffer - 需要转换的 ArrayBuffer* @param {string} [type] - Blob 的 MIME 类型(如 "image/png")* @returns {Blob} - 转换后的 Blob*/
function arrayBufferToBlob(buffer, type) {// 直接通过 Blob 构造函数转换return new Blob([buffer], { type: type || '' });
}// 示例用法
const buffer = new Uint8Array([72, 101, 108, 108, 111]).buffer;
const blob = arrayBufferToBlob(buffer, 'text/plain');
console.log('ArrayBuffer -> Blob:', blob);

5. 将 Blob 转换为 Base64 字符串

/*** 异步将 Blob 转换为 Base64 字符串* @param {Blob} blob - 需要转换的 Blob* @returns {Promise<string>} - 返回 Promise 包含 Base64 字符串*/
function blobToBase64(blob) {return new Promise((resolve, reject) => {const reader = new FileReader();reader.onload = () => {// 去除 DataURL 前缀(如 "data:text/plain;base64,")const base64 = reader.result.split(',')[1];resolve(base64);};reader.onerror = () => reject(reader.error);reader.readAsDataURL(blob); // 读取为 DataURL});
}// 示例用法
const blob = new Blob(['Hello']);
blobToBase64(blob).then(base64 => {console.log('Blob -> Base64:', base64); // 输出 "SGVsbG8="
});

6. 将 Base64 字符串转换为 Blob

/*** 将 Base64 字符串转换为 Blob 对象* @param {string} base64 - Base64 字符串* @param {string} [type] - Blob 的 MIME 类型(如 "image/png")* @returns {Blob} - 转换后的 Blob*/
function base64ToBlob(base64, type) {// 将 Base64 转换为二进制字符串const byteString = atob(base64);// 创建 Uint8Array 视图const buffer = new Uint8Array(byteString.length);for (let i = 0; i < byteString.length; i++) {buffer[i] = byteString.charCodeAt(i);}// 生成 Blobreturn new Blob([buffer], { type: type || '' });
}// 示例用法
const base64 = 'SGVsbG8='; // "Hello" 的 Base64
const blob = base64ToBlob(base64, 'text/plain');
console.log('Base64 -> Blob:', blob);

7. 将 Blob 转换为 DataURL

/*** 异步将 Blob 转换为 DataURL(可直接用于 img.src)* @param {Blob} blob - 需要转换的 Blob* @returns {Promise<string>} - 返回 Promise 包含 DataURL*/
function blobToDataURL(blob) {return new Promise((resolve, reject) => {const reader = new FileReader();reader.onload = () => resolve(reader.result); // 直接返回完整 DataURLreader.onerror = () => reject(reader.error);reader.readAsDataURL(blob);});
}// 示例用法(图片预览)
const blob = new Blob([new Uint8Array([0x89, 0x50, 0x4E, 0x47])], { type: 'image/png' });
blobToDataURL(blob).then(dataURL => {console.log('Blob -> DataURL:', dataURL); // 输出 "data:image/png;base64,..."
});

8. 将 Blob 转换为 Object URL

/*** 将 Blob 转换为 Object URL(需手动释放内存)* @param {Blob} blob - 需要转换的 Blob* @returns {string} - Object URL(如 "blob:http://...")*/
function blobToObjectURL(blob) {// 使用 URL.createObjectURL 生成临时链接return URL.createObjectURL(blob);
}// 示例用法
const blob = new Blob(['Hello']);
const url = blobToObjectURL(blob);
console.log('Blob -> Object URL:', url);// 使用后需释放内存!
// URL.revokeObjectURL(url);

9. 将 Blob 转换为 Uint8Array

/*** 异步将 Blob 转换为 Uint8Array* @param {Blob} blob - 需要转换的 Blob* @returns {Promise<Uint8Array>} - 返回 Promise 包含 Uint8Array*/
function blobToUint8Array(blob) {return new Promise((resolve, reject) => {const reader = new FileReader();reader.onload = () => {// 通过 ArrayBuffer 创建 Uint8Arrayconst buffer = reader.result;resolve(new Uint8Array(buffer));};reader.onerror = () => reject(reader.error);reader.readAsArrayBuffer(blob);});
}// 示例用法
const blob = new Blob(['Hello']);
blobToUint8Array(blob).then(uint8Array => {console.log('Blob -> Uint8Array:', uint8Array); // 输出 [72, 101, 108, 108, 111]
});

10. 将 Blob 转换为文本

/*** 异步将 Blob 转换为文本内容* @param {Blob} blob - 需要转换的 Blob* @param {string} [encoding] - 文本编码(默认 "utf-8")* @returns {Promise<string>} - 返回 Promise 包含文本内容*/
function blobToText(blob, encoding = 'utf-8') {return new Promise((resolve, reject) => {const reader = new FileReader();reader.onload = () => resolve(reader.result);reader.onerror = () => reject(reader.error);reader.readAsText(blob, encoding); // 指定编码读取});
}// 示例用法
const blob = new Blob(['你好']);
blobToText(blob).then(text => {console.log('Blob -> Text:', text); // 输出 "你好"
});

11.使用总结

  • 通用逻辑:大部分转换依赖 FileReader 和 Blob 构造函数。

  • 关键点

    • FileReader 的 readAsXXX 方法决定读取格式。

    • Blob 的 type 属性影响生成文件的 MIME 类型。

    • Object URL 使用后需调用 URL.revokeObjectURL() 释放内存。

  • 错误处理:所有异步函数均返回 Promise,建议用 try/catch 包裹。

完整的图片上传案例

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>图片上传与居中全屏预览</title><style>/* 基础样式重置 */* {margin: 0;padding: 0;box-sizing: border-box;}/* 页面主体样式 */body {font-family: Arial, sans-serif;min-height: 100vh;background: #f5f5f5;display: flex;flex-direction: column;align-items: center;padding: 20px;}/* 上传容器样式 */.upload-container {background: white;padding: 30px;border-radius: 10px;box-shadow: 0 2px 10px rgba(0,0,0,0.1);margin-bottom: 20px;text-align: center;}/* 自定义上传按钮 */.custom-upload-btn {background: #2196F3;color: white;padding: 12px 24px;border-radius: 5px;cursor: pointer;transition: background 0.3s;display: inline-block;}.custom-upload-btn:hover {background: #1976D2;}/* 隐藏原生文件输入 */#fileInput {display: none;}/* 错误提示样式 */.error-message {color: #ff4444;margin-top: 10px;display: none;}/* 预览容器样式 */#previewContainer {max-width: 90%;margin: 20px 0;cursor: zoom-in;position: relative;display: none; /* 默认隐藏 */}/* 预览图片样式 */#previewImage {max-width: 100%;max-height: 70vh;border-radius: 8px;box-shadow: 0 4px 12px rgba(0,0,0,0.15);transition: transform 0.3s;}/* 全屏模式样式 */#previewContainer.fullscreen {position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;background: rgba(0, 0, 0, 0.9);z-index: 9999;cursor: zoom-out;display: flex !important; /* 强制覆盖默认样式 */align-items: center; /* 垂直居中 */justify-content: center; /* 水平居中 */}/* 全屏时图片样式 */#previewContainer.fullscreen #previewImage {max-width: 90vw;max-height: 90vh;object-fit: contain; /* 保持比例填充 */}</style>
</head>
<body>
<!-- 上传区域 -->
<div class="upload-container"><label class="custom-upload-btn" for="fileInput">📷 点击上传图片</label><input type="file" id="fileInput" accept="image/*"><div class="error-message" id="errorMessage">只能上传图片文件 (JPEG/PNG/GIF)</div>
</div><!-- 图片预览区域 -->
<div id="previewContainer"><img id="previewImage" alt="图片预览">
</div><script>// =====================// 元素获取// =====================const fileInput = document.getElementById('fileInput');const previewImage = document.getElementById('previewImage');const previewContainer = document.getElementById('previewContainer');const errorMessage = document.getElementById('errorMessage');// =====================// 文件上传处理// =====================fileInput.addEventListener('change', function(e) {const file = e.target.files[0];// 清除错误提示errorMessage.style.display = 'none';if (!file) return;// 验证文件类型if (!file.type.startsWith('image/')) {showError("文件类型错误,请选择图片");this.value = ''; // 清空选择return;}// 创建文件阅读器const reader = new FileReader();// 文件读取成功回调reader.onload = function(e) {previewImage.src = e.target.result;previewContainer.style.display = 'block'; // 显示预览容器};// 错误处理reader.onerror = function() {showError("文件读取失败");previewContainer.style.display = 'none';};// 开始读取文件reader.readAsDataURL(file);});// =====================// 全屏功能// =====================previewContainer.addEventListener('click', toggleFullscreen);// 全屏切换函数function toggleFullscreen() {if (document.fullscreenElement) {exitFullscreen();} else {enterFullscreen(previewContainer);}}// 进入全屏function enterFullscreen(element) {if (element.requestFullscreen) {element.requestFullscreen();} else if (element.mozRequestFullScreen) { // Firefoxelement.mozRequestFullScreen();} else if (element.webkitRequestFullscreen) { // Chrome/Safarielement.webkitRequestFullscreen();} else if (element.msRequestFullscreen) { // IE/Edgeelement.msRequestFullscreen();}// 添加全屏类名element.classList.add('fullscreen');}// 退出全屏function exitFullscreen() {if (document.exitFullscreen) {document.exitFullscreen();} else if (document.mozCancelFullScreen) { // Firefoxdocument.mozCancelFullScreen();} else if (document.webkitExitFullscreen) { // Chrome/Safaridocument.webkitExitFullscreen();} else if (document.msExitFullscreen) { // IE/Edgedocument.msExitFullscreen();}// 移除全屏类名previewContainer.classList.remove('fullscreen');}// 监听全屏状态变化document.addEventListener('fullscreenchange', () => {previewContainer.classList.toggle('fullscreen', !!document.fullscreenElement);});// =====================// 辅助函数// =====================function showError(message) {errorMessage.textContent = message;errorMessage.style.display = 'block';previewContainer.style.display = 'none';}
</script>
</body>
</html>

相关文章:

前端二进制数据指南:从 ArrayBuffer 到高级流处理

前端开发中&#xff0c;二进制数据是处理文件、图像、音视频、网络通信等场景的基础。以下是核心概念和用途的通俗解释&#xff1a; 前端二进制数据介绍 1. 什么是前端二进制数据&#xff1f; 指计算机原始的 0 和 1 格式的数据&#xff08;比如一张图片的底层代码&#xff…...

深入理解构造函数,析构函数

目录 1.引言 2.构造函数 1.概念 2.特性 3.析构函数 1.概念 2.特性 1.引言 如果一个类中什么都没有&#xff0c;叫作空类. class A {}; 那么我们这个类中真的是什么都没有吗?其实不是,如果我们类当中上面都不写.编译器会生成6个默认的成员函数。 默认成员函数:用户没有显…...

数值分析知识重构

数值分析知识重构 一 Question 请构造一下数值分析中的误差概念以及每一个具体数值方法的误差是如何估计的&#xff1f; 二 Question 已知 n 1 n1 n1个数据点 ( x i , y i ) , i 0 , 1 , ⋯ , n (x_i,y_i),i0,1,\cdots,n (xi​,yi​),i0,1,⋯,n,请使用多种方法建立数据之间…...

全端同步!ZKmall开源商城如何用B2B2C模板让消费者跨设备购物体验无缝衔接?

在数字化浪潮席卷下&#xff0c;消费者的购物行为不再局限于单一设备。早晨用手机小程序浏览商品&#xff0c;中午在 PC 端对比参数&#xff0c;晚上通过平板下单&#xff0c;跨设备购物已成常态。然而&#xff0c;设备间数据不同步、操作体验割裂等问题&#xff0c;严重影响购…...

Redis Sentinel如何实现高可用?

Redis Sentinel 通过以下核心机制实现高可用&#xff1a; 1. 监控&#xff08;Monitoring&#xff09; Sentinel 集群会持续监控主节点&#xff08;Master&#xff09;和从节点&#xff08;Slave&#xff09;的状态&#xff1a; 定期发送 PING 命令检测节点是否存活&#xf…...

环形缓冲区 ring buffer 概述

环形缓冲区 ring buffer 概述 1. 简介 环形缓冲区&#xff08;ring buffer&#xff09;&#xff0c;是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构&#xff0c;适合缓存数据流。也称作环形缓冲区&#xff08;circular buffer&#xff09;&#xff0c;环形队列&…...

Spring源码之解决循环依赖 三级缓存

目录 三级缓存核心原理 循环依赖的解决过程 1. Bean A创建过程中提前曝光工厂 2. Bean B创建时发现依赖A&#xff0c;从缓存获取 3. Bean A继续完成初始化 三级缓存的作用总结 二级缓存为何不够解决缓存依赖&#xff1f; 三级缓存如何解决&#xff1f; 为什么不直接在…...

山东大学计算机图形学期末复习9——CG12上

CG12上 几何管线末端&#xff1a;顶点已组装成基本图元&#xff08;Primitives&#xff0c;如点、线、三角形&#xff09;。 主要任务&#xff1a; 裁剪&#xff1a;视锥体是一个三维空间区域&#xff08;由近裁剪面、远裁剪面和侧面组成&#xff09;&#xff0c;超出该区域的图…...

关于软件测试开发的一些有趣的知识

文章目录 一、什么是测试&#xff1f;二、为什么要软件测试软件测试三、测试的岗位有哪些四 、软件测试和开发的区别五、走测试岗位为什么还要学开发。4、优秀的测试人员具备的素质我为什么走测试岗位 一、什么是测试&#xff1f; 其实这个问题说简单也不简单&#xff0c;说难…...

在Solana上使用 Scaled UI Amount 扩展

本指南提供 Solana Web3.js (Legacy v 1.x) 和 Solana Kit (v 2.x) 版本。选择适当的选项卡以查看你首选库的代码片段和说明&#xff1a; Solana Web3.js (Legacy)Solana Kit 概述 Solana Token-2022 程序 引入了强大的扩展&#xff0c;增强了代币功能&#xff0c;使其超越了…...

线性表之数组与栈详解

线性表之数组与栈详解 前言一、数组&#xff08;Array&#xff09;1.1 数组的基本概念1.2 数组的实现与操作1.3 数组的应用场景1.4 数组的优缺点 二、栈&#xff08;Stack&#xff09;2.1 栈的基本概念2.2 栈的实现方式2.3 栈的应用场景 2.4 栈的优缺点 三、数组与栈的对比总结…...

车载以太网驱动智能化:域控架构设计与开发实践

title: 车载以太网驱动专用车智能化&#xff1a;域控架构设计与开发实践 date: 2023-12-01 categories: 新能源汽车 tags: [车载以太网, 电子电气架构, 域控架构, 专用车智能化, SOME/IP, AUTOSAR] 引言&#xff1a;专用车智能化转型的挑战与机遇 专用车作为城市建设与工业运输…...

【Redis】redis用作缓存和分布式锁

文章目录 1. 缓存1.1 Redis作为缓存1.2 缓存更新、淘汰策略1.3 缓存预热、缓存穿透、缓存雪崩和缓存击穿1.3.1 缓存预热&#xff08;preheating&#xff09;1.3.2 缓存穿透&#xff08;penetration&#xff09;1.3.3 缓存雪崩&#xff08;avalanche&#xff09;1.3.4 缓存击穿&…...

深度学习中独热编码(One-Hot Encoding)

文章目录 独热编码独热编码的作用独热编码的优点独热编码的缺点场景选择独热编码&#xff08;PyTorch实现&#xff09;替代方案 实际使用分析&#xff1a;对对象类型使用独热编码为什么使用独热编码是合适的&#xff1f;&#x1f4cc; 场景说明&#xff1a;&#x1f4cc; 为什么…...

如何根据竞价数据判断竞价强度,是否抢筹等

竞价强度判断方法 价格变化幅度 观察开盘价与前一交易日收盘价的差距 &#xff1a;如果一只股票在开盘集合竞价阶段价格大幅高于前一交易日收盘价&#xff0c;说明市场对该股票的预期较为积极&#xff0c;可能有资金在主动抬高价格&#xff0c;这是一种较强的竞价强度表现。例如…...

Codex与LangChain结合的智能代理架构:重塑软件开发的未来

🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言:当代码生成遇见智能决策 想象以下场景: 凌晨三点:你需要紧急修复一个遗留系统的内存泄漏漏洞,但代码注释缺失且逻辑复杂; 产品经理需求变更:要求在24小时内将现有…...

2025年PMP 学习十八 第11章 项目风险管理 (11.5~11.7)

2025年PMP 学习十八 第11章 项目风险管理 &#xff08;11.5~11.7&#xff09; 第11章 项目风险管理 序号过程过程组1规划风险管理规划2识别风险规划3实施定性风险分析规划4实施定量风险分析规划5规划风险应对执行6实施风险应对执行7监控风险监控 文章目录 2025年PMP 学习十八…...

2025年PMP 学习十七 第11章 项目风险管理 (11.1~11.4)

2025年PMP 学习十七 第11章 项目风险管理 &#xff08;11.1~11.4&#xff09; 第11章 项目风险管理 序号过程过程组1规划风险管理规划2识别风险规划3实施定性风险分析规划4实施定量风险分析规划5规划风险应对执行6实施风险应对执行7监控风险监控 文章目录 2025年PMP 学习十七…...

impala

Impala&#xff0c;它是 Cloudera 开发的开源 实时 SQL 查询引擎&#xff0c;专为 Hadoop 设计。与 Presto 类似&#xff0c;Impala 用于交互式分析&#xff0c;但架构和设计理念有所不同。以下是 Impala 的核心特点和工作原理&#xff1a; 一、Impala 核心架构 1. 组件组成 …...

湖北理元理律师事务所:债务优化中的双维支持实践解析

在债务压力与生活质量失衡的社会议题下&#xff0c;法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式&#xff0c;探索债务优化与生活保障的平衡路径&#xff0c;其方法论或为行业提供实践参考。 法律框架&…...

Redis设计与实现——Redis命令参考与高级特性

Redis命令参考 数据类型相关命令 SET&#xff1a;设置键值&#xff0c;支持过期时间、不存在/存在条件。GET&#xff1a;获取键值&#xff0c;若键不存在返回 nil。INCR/DECR&#xff1a;将键的整数值增1/减1&#xff0c;键不存在时初始化为0。MSET/MGET&#xff1a;批量设置…...

TCP/UDP协议原理和区别 笔记

从简单到难吧 区别就是TCP一般用于安全稳定的需求&#xff0c;UDP一般用于不那么需要完全数据的需求&#xff0c;比如说直播&#xff0c;视频等。 再然后就是TPC性能慢于UDP。 再然后我们看TCP的原理&#xff08;三次握手&#xff0c;数据传输&#xff0c;四次挥手&#xff0…...

JavaScript基础-对象的相关概念

在JavaScript中&#xff0c;对象是核心的数据结构之一&#xff0c;几乎所有的高级功能都围绕着对象展开。理解对象的基本概念、创建方法以及操作方式对于掌握JavaScript至关重要。本文将详细介绍JavaScript中对象的相关概念&#xff0c;包括对象的定义、属性的操作、原型链和面…...

如何通过交流沟通实现闭环思考模式不断实现自身强效赋能-250517

感谢一直以来和我交流沟通的朋友们。 闭环思考 文字部分&#xff08;25-05-04&#xff09;这一天是青年节&#xff0c;在这一天与青年朋友交流这个是事先规划好的&#xff1a; “可以猜一猜&#xff0c;博士会被撤销吗&#xff1f;导师会被处理吗&#xff1f;千万不要回复&…...

震荡指标工具

一、引言 - 可视化数字烛台工具是对传统蜡烛图的补充&#xff0c;旨在帮助交易者更有效地进入和退出交易&#xff0c;提高交易利润。 - 通过分析蜡烛图&#xff0c;结合烛台震荡指标&#xff0c;提出了一个辅助视觉工具来辅助交易决策。 二、烛台指标与交易策略 -图表通过平均开…...

【自然语言处理与大模型】大模型(LLM)基础知识④

&#xff08;1&#xff09;微调主要用来干什么&#xff1f; 微调目前最主要用在定制模型的自我认知和改变模型对话风格。模型能力的适配与强化只是辅助。 定制模型的自我认知&#xff1a;通过微调可以调整模型对自我身份、角色功能的重新认知&#xff0c;使其回答更加符合自定义…...

返回码的方案对比和思考

前言 一般我们定义 Restful 接口返回码&#xff0c;常见的就是 const 定义 code &#xff0c; StatusToText() 来实现定义 msg&#xff0c; 在封装1 ~ 2个返回方法&#xff08;success、error&#xff09;就可以实现&#xff0c;只是突然想到这样设计是违反开闭原则的&#xf…...

Flink 的任务槽和槽共享

在 Apache Flink 中&#xff0c;任务槽&#xff08;Task Slot&#xff09; 和 槽共享组&#xff08;Slot Sharing Group&#xff09; 是资源管理和任务调度的关键机制。它们决定了 Flink 如何在集群中分配资源并执行任务。 一、任务槽&#xff08;Task Slot&#xff09; 1. 定…...

实验七 基于Python的数字图像水印算法

一、实验目的 掌握图像水印的应用&#xff1b; 掌握我国版权保护的发展现状&#xff1b; 掌握常见的数字图像水印算法。 二、实验内容 学习内容补充&#xff1a; 数字水印的鲁棒性评价主要采用含水印图像提取出的水印与原始水印的相似程度,使用归一化相关(NC&#xff0c;Nor…...

C语言:在 Win 10 上,gcc 如何编译 gtk 应用程序

在 Windows 10 上使用 g&#xff08;或 gcc&#xff09;编译基于 GTK 的 C 语言程序是完全可行的&#xff0c;且相比 Tcc 更为推荐&#xff0c;因为 g&#xff08;GNU 编译器套件&#xff09;对 GTK 的支持更加完善&#xff0c;配置也更简单。以下是详细步骤和注意事项&#xf…...

Vue.js---watch 的实现原理

4.7 watch 的实现原理 watch本质上就是使用了effect以及options.scheduler 定义watch函数&#xff1a; // watch函数:传入参数source以及回调函数function watch(source , cb) {effect(() > source.foo,{scheduler(){// 回调函数cb()}})}watch接收两个参数分别是source和c…...

Linux_ELF文件

目录 前言&#xff1a; 一、ELF文件的类型 二、ELF文件的组成格式 1. ELF头部(ELF Header) 2. 节头表(Section Header Table) 3. 程序头表(Program Header Table) 4. 节(Sections)与段(Segments) 三、ELF文件从形成到加载轮廓 1、ELF可执行文件形成过程 2、 可执行文…...

磁盘I/O子系统

一、数据写入磁盘流程 当执行向磁盘写入数据操作的时候&#xff0c;会发生如下的一系列基本操作。假设文件数据存在于磁盘扇区上&#xff0c;并且已经被读入到页缓存中。 进程使用write()系统调用写入文件。内核更新映射到文件的page cache。内核线程pdflush负责把页缓存刷入…...

【2025 技术指南】如何创建和配置国际版 Apple ID

想要体验更丰富的应用生态、使用国际版专属服务&#xff0c;或访问更多开发者工具&#xff1f;一个国际版 Apple ID 能帮你实现这些需求。本教程将详细介绍如何注册国际版 Apple ID 并正确配置支付信息&#xff0c;全程操作简单&#xff0c;适合开发者和技术爱好者参考。 一、准…...

C++(20): 文件输入输出库 —— <fstream>

目录 一、 的核心功能 二、核心类及功能 三、核心操作示例 1. 文本文件写入&#xff08;ofstream&#xff09; 2. 文本文件读取&#xff08;ifstream&#xff09; 3. 二进制文件操作&#xff08;fstream&#xff09; 四、文件打开模式 五、文件指针操作 六、错误处理技巧…...

05、基础入门-SpringBoot-HelloWorld

05、基础入门-SpringBoot-HelloWorld ## 一、Spring Boot 简介 **Spring Boot** 是一个用于简化 **Spring** 应用初始搭建和开发的框架&#xff0c;旨在让开发者快速启动项目并减少配置文件。 ### 主要特点 - **简化配置**&#xff1a;采用“约定优于配置”的原则&#xff0c;减…...

深入理解指针(6)

目录 1 sizeof和strlen的对⽐ 1.1 sizeof ​编辑1.2strlen 1.3 sizeof 和 strlen的对⽐ 2 数组和指针笔试题解析 2.1 ⼀维数组 ​编辑 2.2 字符数组 3 指针运算笔试题解析 3.1 题⽬1&#xff1a; ​编辑3.2 题目2 3.3 题目3 3.4 题目4 3.5 题目5 3.6 题目6 3.7…...

力扣HOT100之二叉树:108. 将有序数组转换为二叉搜索树

这道题之前做过&#xff0c;思路又给忘了&#xff0c;这道题用递归做是最简单的。 由于得到的数组是有序的&#xff0c;我们只需要取出中间位置的元素medium作为根节点&#xff0c;然后medium左边的剩余元素组成根节点的左子树&#xff0c;medium右边的剩余元素组成根节点的右子…...

手撕I2C和SPI协议实现

手撕I2C和SPI协议实现 目录 I2C协议原理I2C位操作实现I2C驱动代码编写SPI协议原理SPI位操作实现SPI驱动代码编写 I2C协议原理 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种串行通信总线&#xff0c;使用两根线&#xff1a;SCL&#xff08;时钟线&#xff09…...

452. Minimum Number of Arrows to Burst Balloons

题目描述 这道题用leetcode官方的解答反而搞复杂了。本题其实就是求重叠区间的交集。先按照区间左端点从小到大排序。然后拿出第一个区间作为【当前区间交集】的初始值。遍历后面的区间看那个区间和【当前交集】是否有重叠。如果有重叠则将【当前交集】和【当前区间】求交集并更…...

React 中,闭包陷阱

文章目录 前言1. 经典闭包陷阱示例过期状态问题 2. 解决方案2.1 正确声明依赖数组2.2 使用 useRef 捕获最新值**2.3 使用函数式更新&#xff08;针对状态更新&#xff09;****2.4 使用 useCallback 冻结闭包** **3. 异步操作中的闭包陷阱****事件监听示例** **4. 自定义 Hooks …...

代码复现5——VLMaps

项目地址 1 Setup # 拉取VLMaps仓库,成功运行后会在主目录生成文件夹vlmapsgit clone https://github.com/vlmaps/vlmaps.git#通过 conda 创建虚拟环境conda create -n vlmaps python=3.8 -yconda activate vlmaps #激活环境cd vlmaps # 切换到项目文件下bash install.ba…...

qt6 c++操作qtableview和yaml

保存qtableview数据到yaml文件从yaml文件读取数据到qtableview qtableview在UI界面拖放。 代码是问chat百度的深度探索。 - name: a1address: db1.dbw10type: int - name: a2address: db1.dbx1.0type: bool写到yaml&#xff0c;写前检查 bool plot1::isRowValid(const QStan…...

使用UniApi调用百度地图API的需要注意的地方

目录 前言 一、百度开放平台 1、功能简介 2、地点搜索服务 3、按行政区划检索API 二、Uniapi集成百度API 1、API集成流程 2、访问接口的定义 3、业务调用集成 三、可能遇到的问题 1、指定输出格式无效 2、返回数据的总数 四、总结 前言 在之前的系列博客中&#xf…...

(9)python开发经验

文章目录 1 os.path.join()拼接路径2 条件变量3 添加临时环境变量 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt开发 &#x1f448;&#x1f449;python开发 &#x1f448; 1 os.path.join()拼接路径 os.path.join() 是 Python 中处理文件路径拼接的核心函…...

windows 10 做服务器 其他电脑无法访问,怎么回事?

一般我们会先打开win10自己的防火墙策略&#xff0c;但是容易忽略 电脑之间 路由器上的防火墙&#xff0c;此时也需要查看一下&#xff0c;可以尝试先关闭路由器防火墙&#xff0c;如果可以了&#xff0c;再 设置路由器上的防火墙规则。 将路由器的上网设置 改成 路由模式 &a…...

mysql中limit深度分页详细剖析【爽文】

目录 一 mysql中limit深度分页 1.1 背景描述 1.2 mysql深度分页很慢原因 1.2.1 mysql的sql执行流程 1.2.2 mysql的深度分页很慢原因 1.3 解决办法 1.3.1 覆盖索引 1.3.2 子查询 1.3.3 标签查询 1.3.4 分区表 一 mysql中limit深度分页 1.1 背景描述 Limit深度分页造…...

【C++ Qt】布局管理器

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” &#x1f914;绪论​&#xff1a; 在Qt开发中&#xff0c;界面布局的合理设计是提升用户体验的关键。早期&#xff0c;开发者常采用绝对定位的方式摆放控件&#xff0c;即通…...

Windows系统永久暂停更新操作步骤

目录 Windows系统永久暂停更新操作步骤 打开运行窗口进入注册表编辑器 导航路径图示 新建并配置DWORD值 新建值操作图示数值设置图示 在系统设置中应用暂停 暂停选项图示 注意事项 打开运行窗口 按下键盘上的 Win键 R 组合键&#xff0c;调出“运行”对话框。 进入组策略编…...

Java IO流进阶实战详解(含文件读写、拷贝、加密、字符集)

本文基于 Java 原生 IO 流&#xff0c;从最基础的字节流到字符流&#xff0c;再到实战案例&#xff08;如文件夹拷贝、文件加密等&#xff09;进行逐步深入讲解。适合有一定 Java 基础、希望掌握文件读写操作的。 一、前言 Java IO&#xff08;输入输出&#xff09;是我们日常…...