[node] Node.js 缓冲区Buffer

[node] Node.js 缓冲区Buffer

  • 什么是Buffer
  • Buffer 与字符编码
  • Buffer 的方法概览
  • Buffer 的实例
    • Buffer 的创建
    • 写入缓冲区
    • 从 Buffer 区读取数据
    • 将 Buffer 转换为 JSON 对象
    • Buffer 的合并
    • Buffer 的比较
    • Buffer 的覆盖
    • Buffer 的截取--slice
    • Buffer 的长度
    • writeUIntLE
    • writeUIntBE

什么是Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用 Buffer.from() 接口去创建Buffer对象。

Buffer 与字符编码

Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换

const buf = Buffer.from("test", "ascii");
console.log(buf.toString("hex"));// 输出 74657374
console.log(buf.toString("base64"));// 输出 dGVzdA==

Node.js 目前支持的字符编码包括:

  • ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
  • utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
  • utf16le - 2 或 4 个字节,小字节编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
  • ucs2 - utf16le 的别名。
  • base64 - Base64 编码。
  • latin1 - 一种把 Buffer 编码成字节编码的字符串的方式。
  • binary - latin1 的别名。
  • hex - 将每个字节编码为两个十六进制字符。

Buffer 的方法概览

写在前面,下面所有方法中:

  • 以LE结尾的API,指定使用endian (Little-Endian)字节序格式读取或写入
  • 以BE结尾的API,指定使用endian (Bid-Endian)字节序格式读取或写入
方法描述
new Buffer(size) Buffer.alloc(size)或 Buffer.allocUnsafe(size)分配新的 size 大小单位为8位字节的 buffer。 注意, size 必须小于 kMaxLength,否则,将会抛出异常 RangeError
new Buffer(buffer) Buffer.from(buffer)拷贝参数 buffer 的数据到 Buffer 实例
new Buffer(str[, encoding]) Buffer.from(str[, encoding])分配新的 buffer.str 字符串, encoding 编码方式默认为 ‘utf8’
buf.length返回 buf 的 bytes 数。注意这未必是 buf 里面内容的大小。length 是 buffer 对象所分配的内存数,若指定size 它不会随着buf 对象内容的改变而改变,若未指定则会发生变化
buf.toString([encoding[, start[, end]]])根据 encoding (默认 utf8)返回解码过的 string 类型。根据 start (默认 0) ,end (默认 buffer.length)作为取值范围
buf.toJSON()将 Buffer 实例转换为 JSON 对象。
buf[index]获取或设置指定的字节。返回值代表一个字节,所以返回值的合法范围是十六进制0x00到0xFF 或者十进制0至 255。
buf.equals(otherBuffer)比较两个缓冲区是否相等,相等返回 true,否则返回 false
buf.compare(otherBuffer)比较两个 Buffer 对象,返回数字,表示 buf 在 otherBuffer 之前,之后或相同
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])将buf指定区间的内容覆盖targetBuffer指定索引开始的相同长度内容,源和目标可以相同。buf开始位置sourceStart(默认0)和结束位置sourceEnd (默认buf的长度)的区间内容,覆盖targetBuffer从targetStart开始的相同长度的内容
buf.slice([start[, end]])截取 Buffer 对象,从 start(默认是 0 ) 到 end (默认是 buffer.length ) 的区间。 负的索引是从 buffer 尾部开始计算的
buf.fill(value[, offset][, end])使用指定的 value 来填充这个 buffer。如果没有指定 offset (默认是 0) 并且 end (默认是 buffer.length) ,将会填充整个buffer。
buf.write(str[, offset[, length]][, encoding])根据offset 偏移量(默认值是 0)和 encoding 编码方式(默认值是 utf8),将 str 数据写入buffer。 length 是将要写入的字符串的 bytes 大小。 返回 number 类型,表示写入了多少 8 位字节流。如果 buffer 没有足够的空间来放整个 str ,它将只会只写入部分字符串。 length 默认是 buffer.length - offset。 这个方法不会出现写入部分字符。
buf.writeUIntLE(value, offset, byteLength[, noAssert])将 value 写入到 buffer 里, 它由 offset 和 byteLength 决定,最高支持 48 位无符号整数。noAssert(默认 false) 为 true ,不再验证 value 和 offset 的有效性
buf.writeUIntBE(value, offset, byteLength[, noAssert])用法同上。注意:无符号整数
buf.writeIntLE(value, offset, byteLength[, noAssert])用法同上。注意:有符号整数
buf.writeIntBE(value, offset, byteLength[, noAssert])用法同上。注意:有符号整数
buf.readUIntLE(offset, byteLength[, noAssert])根据指定的偏移量,支持读取 48 位以下的无符号数字,指定Endian格式。noAssert (默认 false)为 true 时, 不验证offset是否超过 buffer 的长度
buf.readUIntBE(offset, byteLength[, noAssert])用法同上。注意:无符号整数
buf.readIntLE(offset, byteLength[, noAssert])用法同上。注意:有符号整数
buf.readIntBE(offset, byteLength[, noAssert])用法同上。注意:有符号整数
buf.readUInt8(offset[, noAssert])用法同上。注意:支持读取无符号 8 位整数
buf.readUInt16LE(offset[, noAssert])用法同上。注意:读取一个无符号 16 位整数
buf.readUInt16BE(offset[, noAssert])用法同上。注意:读取一个无符号 16 位整数
buf.readUInt32LE(offset[, noAssert])用法同上。注意:读取一个无符号 32 位整数。
buf.readUInt32BE(offset[, noAssert])用法同上。注意:读取一个无符号 32 位整数。
buf.readInt8(offset[, noAssert])用法同上。注意:读取一个有符号 8 位整数
buf.readInt16LE(offset[, noAssert])用法同上。注意:读取一个 有符号 16 位整数
buf.readInt16BE(offset[, noAssert])用法同上。注意:读取一个 有符号 16 位整数
buf.readInt32LE(offset[, noAssert])用法同上。注意:读取一个有符号 32 位整数。
buf.readInt32BE(offset[, noAssert])用法同上。注意:读取一个有符号 32 位整数。
buf.readFloatLE(offset[, noAssert])用法同上。注意:读取一个 32 位双浮点数。
buf.readFloatBE(offset[, noAssert])用法同上。注意:读取一个 32 位双浮点数。
buf.readDoubleLE(offset[, noAssert])用法同上。注意:读取一个 64 位双精度数。
buf.readDoubleBE(offset[, noAssert])用法同上。注意:读取一个 64 位双精度数。
buf.writeUInt8(value, offset[, noAssert])根据 offset 偏移量和 endian格式将 value 写入 buffer。注意:value 必须是一个合法的无符号 8 位整数。 若noAssert 为 true (默认 false)将不会验证 value 和 offset , 这意味着 value 可能过大,或者 offset 可能会超出buffer的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用
buf.writeUInt16LE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的无符号 16 位整数
buf.writeUInt16BE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的无符号 16 位整数。
buf.writeUInt32LE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的无符号 32 位整数。
buf.writeUInt32BE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的有符号 32 位整数。
buf.writeInt8(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的 signed 8 位整数。
buf.writeInt16LE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的 signed 16 位整数。
buf.writeInt16BE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的 signed 16 位整数。
buf.writeInt32LE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的 signed 32 位整数。
buf.writeInt32BE(value, offset[, noAssert])用法同上。注意:value 必须是一个合法的 signed 32 位整数。
buf.writeFloatLE(value, offset[, noAssert])用法同上。注意:当 value 不是一个 32 位浮点数类型的值时,结果将是不确定的。
buf.writeFloatBE(value, offset[, noAssert])用法同上。注意:当 value 不是一个 32 位浮点数类型的值时,结果将是不确定的
buf.writeDoubleLE(value, offset[, noAssert])用法同上。注意:value 必须是一个有效的 64 位double 类型的值
buf.writeDoubleBE(value, offset[, noAssert])用法同上。注意:value 必须是一个有效的 64 位double 类型的值

Buffer 的实例

Buffer 的创建

  • Buffer.alloc(size[, fill[, encoding]]): 返回一个size大小的 Buffer 实例,如果没有设置 fill,则默认填满 0
  • Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据
  • Buffer.allocUnsafeSlow(size)
  • Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)
  • Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。
  • Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例
  • Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);

// 创建一个长度为 10、且用 0x1 填充的 Buffer。 
const buf2 = Buffer.alloc(10, 1);

// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据, 因此需要 fill() 或 write() 重写。
const buf3 = Buffer.allocUnsafe(10);

// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);

// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('test');

// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('test', 'latin1');

写入缓冲区

buf.write(string[, offset[, length]][, encoding])

根据 encoding 的字符编码写入 string 到 buf 中的 offset 位置。 length 参数是写入的字节数。 如果 buf 没有足够的空间写入整个字符串,则只会写入 string 的一部分。 只部分解码的字符不会被写入.该方法返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串。

  • string:写入缓冲区的字符串
  • offset:偏移量,缓冲区开始写入的索引值,默认为 0
  • length:写入的字节数,默认 buffer.length
  • encoding:编码方式,默认utf8

返回实际写入的大小!!!如果 buffer 空间不足, 则只会写入部分字符串

const buf = Buffer.alloc(256);
const len = buf.write("TestDemo1");
console.log(len); // 输出 9
console.log(buf.length); // 输出 256

请注意,上述实例write函数的返回值len是实际的大小,而buf.length则是缓冲区的大小

从 Buffer 区读取数据

buf.toString([encoding[, start[, end]]])

解码缓冲区数据并使用指定的编码返回字符串

  • encoding:编码方式,默认utf8
  • start:指定开始读取的索引位置,默认为 0
  • end: 结束位置,默认为缓冲区的末尾
const buf = Buffer.alloc(256);
const len = buf.write("TestDemo1");
console.log(len); // 输出 9
console.log(buf.length); // 输出 256
const buf1 = Buffer.alloc(3);
buf1.write("TestDemo1");
console.log(buf1.toString()); // 输出 Tes

将 Buffer 转换为 JSON 对象

buf.toJSON()

将 Node Buffer 转换为 JSON 对象,返回 JSON 对象。

const buf = Buffer.alloc(3);
const len = buf.write("3");;
console.log(buf.toJSON()); // 输出 { type: 'Buffer', data: [ 51, 0, 0 ] }

Buffer 的合并

Buffer.concat(list[, totalLength])

Node 缓冲区合并,返回一个多个成员合并的新 Buffer 对象。

  • list : 用于合并的 Buffer 对象数组列表
  • totalLength : 指定合并后Buffer对象的总长度
var buffer1 = Buffer.from("demo1");
var buffer2 = Buffer.from("test2");
var buffer3 = Buffer.concat([buffer1, buffer2]);
var buffer4 = Buffer.concat([buffer1, buffer2],4);
console.log(buffer3.toString()); //demo1test2
console.log(buffer4.toString()); //demo

Buffer 的比较

buf.compare(otherBuffer);

Node Buffer 比较,返回一个数字,表示 buf 若与 otherBuffer 第一个字符相匹配返回-1;若是完全匹配返回0;其它从中间开始匹配,或者匹配不上返回1

这个方法是按位比较的

  • otherBuffer: 与 buf 对象比较的另外一个 Buffer 对象
var buffer2 = Buffer.from("ABCD");

var buffer1 = Buffer.from("AB");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 -1

var buffer1 = Buffer.from("B");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 1

var buffer1 = Buffer.from("E");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 1

var buffer1 = Buffer.from("AE");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 1

var buffer1 = Buffer.from("ABCD");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 0

Buffer 的覆盖

buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])

截取缓冲区 buf指定长度的内容复制到targetBuffer的指定位置,没有返回值

  • targetBuffer:要被覆盖的 Buffer 对象
  • targetStart:覆盖 Buffer 对象指定开始覆盖的索引位置,默认为 0
  • sourceStart: 用于覆盖的Buffer对象的指定开始位置,默认为 0
  • sourceEnd: 用于覆盖的Buffer对象的指定结束位置,默认: buffer.length
var buf1 = Buffer.from("abcdefghijkl");
var buf2 = Buffer.from("RUNOOB");

//将 buf2 插入到 buf1 指定位置上
buf2.copy(buf1, 2, 0, 2);

console.log(buf1.toString());//abRUefghijkl
console.log(buf2.toString());//RUNOOB

Buffer 的截取–slice

buf.slice([start[, end]])

返回指定区间内的缓冲区,它和旧缓冲区指向同一块内存,从索引 start 到 end 的位置区间.被截取缓冲区不变

  • start:数字, 可选, 默认 0
  • end: 数字, 可选, 默认 buffer.length
var buffer1 = Buffer.from("Test");
// 剪切缓冲区
var buffer2 = buffer1.slice(0, 2);
var buffer3 = Buffer.from("M");
buffer3.copy(buffer1);
console.log(buffer2.toString());//Me
console.log(buffer1.toString());//Mest

Buffer 的长度

const buf = Buffer.from("Test");
console.log(buf.length); // 输出 4
const buf1 = Buffer.from("TestDemo1");
console.log(buf1.length); // 输出 9

writeUIntLE

const buf = Buffer.allocUnsafe(6);
buf.writeUIntLE(0x1234567890ab, 0, 6);
// 输出: <Buffer ab 90 78 56 34 12>
console.log(buf);

writeUIntBE

const buf = Buffer.allocUnsafe(6);
buf.writeUIntBE(0x1234567890ab, 0, 6);
// 输出: <Buffer 12 34 56 78 90 ab>
console.log(buf);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/262266.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何用docke启动redis?(解决双击docker服务闪退问题)

要使用Docker启动Redis服务&#xff0c;您可以按照以下步骤进行操作&#xff1a; 安装Docker&#xff1a; 如果您还没有安装Docker&#xff0c;请先在您的系统上安装Docker。您可以从Docker官方网站获取安装说明。 https://www.docker.com/get-started/ 2.在Docker Hub上查找R…

论文中公式怎么降重 papergpt

大家好&#xff0c;今天来聊聊论文中公式怎么降重&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 论文中公式怎么降重 一、引言 在论文撰写过程中&#xff0c;公式是表达学…

声音克隆:让你的声音变得无所不能

什么是声音克隆&#xff1f; 声音克隆是一种利用人工智能技术&#xff0c;根据一段声音样本&#xff0c;生成与之相似或完全相同的声音的过程。声音克隆可以用于多种场景。 声音克隆的原理是利用深度学习模型&#xff0c;从声音样本中提取声音特征&#xff0c;然后根据目标文…

华为OD机试 - 发广播 - 并查集(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、并查集Java 实现并查集 五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&…

机器学习算法(12) — 集成技术(Boosting — Xgboost 分类)

一、说明 时间这是集成技术下的第 4 篇文章&#xff0c;如果您想了解有关集成技术的更多信息&#xff0c;您可以参考我的第 1 篇集成技术文章。 机器学习算法&#xff08;9&#xff09; - 集成技术&#xff08;装袋 - 随机森林分类器和...... 在这篇文章中&#xff0c;我将解释…

​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化

2022年亚马逊云科技re:Invent盛会于近日在拉斯维加斯成功召开&#xff0c;吸引了众多业界精英和创新者。亚马逊云科技边缘服务副总裁Jan Hofmeyr在演讲中分享了关于亚马逊云科技海外服务器边缘计算的最新发展和创新成果&#xff0c;引发与会者热烈关注。 re:Invent的核心主题是…

057:vue组件方法中加载匿名函数

第057个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

激光打标机:快速、精确、耐用的标记解决方案

随着科技的不断进步&#xff0c;激光打标机已经成为现代工业生产中不可或缺的一部分。作为一种高效、精确、耐用的标记解决方案&#xff0c;激光打标机在各个领域都发挥着重要的作用。 一、快速、精确的标记技术 激光打标机采用激光束作为标记工具&#xff0c;通过精确控制激光…

华为鸿蒙操作系统简介及系统架构分析(2)

接前一篇文章&#xff1a;华为鸿蒙操作系统简介及系统架构分析&#xff08;1&#xff09; 本文部分内容参考&#xff1a; 鸿蒙系统学习笔记(一) 鸿蒙系统介绍 特此致谢&#xff01; 上一回对于华为的鸿蒙操作系统&#xff08;HarmonyOS&#xff09;进行了介绍并说明了其层次化…

医保购药小程序:智能合约引领医疗数字革新

在医疗领域&#xff0c;医保购药小程序通过引入智能合约技术&#xff0c;为用户提供更为高效、安全的购药体验。本文将通过简单的智能合约代码示例&#xff0c;深入探讨医保购药小程序如何利用区块链技术中的智能合约&#xff0c;实现医保结算、购药监控等功能&#xff0c;为医…

Linux 宿主机搭建jenkins

目录 前言错误信息 前言 最近项目需要使用jenkins进行CICD&#xff0c;搭建后始终找不到git 错误信息 Source Code Management None出现这种情况主要是插件没有了&#xff0c;需要我们安装插件&#xff1a;

深入理解网络 I/O:mmap、sendfile、Direct I/O

&#x1f52d; 嗨&#xff0c;您好 &#x1f44b; 我是 vnjohn&#xff0c;在互联网企业担任 Java 开发&#xff0c;CSDN 优质创作者 &#x1f4d6; 推荐专栏&#xff1a;Spring、MySQL、Nacos、Java&#xff0c;后续其他专栏会持续优化更新迭代 &#x1f332;文章所在专栏&…

scrapy_redis概念作用和流程

scrapy_redis概念作用和流程 学习目标 了解 分布式的概念及特点了解 scarpy_redis的概念了解 scrapy_redis的作用了解 scrapy_redis的工作流程 在前面scrapy框架中我们已经能够使用框架实现爬虫爬取网站数据,如果当前网站的数据比较庞大, 我们就需要使用分布式来更快的爬取数…

PDF文件如何设置限制打印?

想要限制PDF文件的打印功能&#xff0c;想要限制PDF文件打印清晰度&#xff0c;都可以通过设置限制编辑来达到目的。 打开PDF编辑器&#xff0c;找到设置限制编辑的界面&#xff0c;切换到加密状态&#xff0c;然后我们就看到 有印刷许可。勾选【权限密码】输入一个PDF密码&am…

FPGA——XILINX原语(1)

FPGA——XILINX原语&#xff08;1&#xff09; 1.时钟组件&#xff08;1&#xff09;BUFG&#xff08;2&#xff09;BUFH&#xff08;3&#xff09;BUFR&#xff08;4&#xff09;BUFIO&#xff08;5&#xff09;使用场景 2.IO端口组件&#xff08;1&#xff09;IDDR&#xff0…

3. 行为模式 - 迭代器模式

亦称&#xff1a; Iterator 意图 迭代器模式是一种行为设计模式&#xff0c; 让你能在不暴露集合底层表现形式 &#xff08;列表、 栈和树等&#xff09; 的情况下遍历集合中所有的元素。 问题 集合是编程中最常使用的数据类型之一。 尽管如此&#xff0c; 集合只是一组对象的…

flink watermark 实例分析

WATERMARK 定义了表的事件时间属性&#xff0c;其形式为: WATERMARK FOR rowtime_column_name AS watermark_strategy_expression rowtime_column_name 把一个现有的列定义为一个为表标记事件时间的属性。该列的类型必须为 TIMESTAMP(3)/TIMESTAMP_LTZ(3)&#xff0c;且是 sche…

【让云服务器更灵活】iptables转发tcp/udp端口请求

iptables转发tcp/udp端口请求 文章目录 前言一、路由转发涉及点二、转发如何配置本机端口转发到本机其它端口本机端口转发到其它机器 三、固化iptables总结 前言 路由转发是计算机网络中的一种重要概念&#xff0c;特别是在网络设备和系统之间。它涉及到如何处理和传递数据包&…

【湖仓一体尝试】MYSQL和HIVE数据联合查询

爬了两天大大小小的一堆坑&#xff0c;今天把一个简单的单机环境的流程走通了&#xff0c;记录一笔。 先来个完工环境照&#xff1a; mysqlhadoophiveflinkicebergtrino 得益于IBM OPENJ9的优化&#xff0c;完全启动后的内存占用&#xff1a; 1&#xff09;执行联合查询后的…

《A++ 敏捷开发》-1 如何改善

1 如何改善 敏捷开发过程改进案例 5月 A公司一直专门为某电信公司提供针对客服、线上播放等服务。 张工是公司的中层管理者&#xff0c;管理好几个开发团队&#xff0c;有5位项目经理向他汇报。 他听说老同学的团队都开始用敏捷开发&#xff0c;很感兴趣&#xff0c;便参加了…
最新文章