缓冲区Buffer案例

wen java案例 5

本文目录导读:

缓冲区Buffer案例

  1. 基本读写案例
  2. 网络数据传输案例
  3. 文件处理的缓冲区案例
  4. 图像处理的缓冲区案例
  5. 数据包解析案例
  6. 性能优化案例
  7. 二进制协议编解码案例

我来为你介绍几个缓冲区(Buffer)的典型案例,涵盖不同应用场景:

基本读写案例

// 创建和操作缓冲区
const buf = Buffer.from('Hello World', 'utf8');
// 读取缓冲区
console.log(buf.toString()); // Hello World
console.log(buf.length);     // 11 字节
// 部分读取
console.log(buf.toString('utf8', 0, 5)); // Hello
// 修改缓冲区
buf[0] = 104; // 'h' 的ASCII码
console.log(buf.toString()); // hello World

网络数据传输案例

const net = require('net');
// TCP服务器处理二进制数据
const server = net.createServer((socket) => {
    // 收集数据块
    const chunks = [];
    let totalLength = 0;
    socket.on('data', (chunk) => {
        // 将接收到的Buffer片段存储
        chunks.push(chunk);
        totalLength += chunk.length;
        // 假设我们期望接收固定大小的数据包
        if (totalLength >= 4) {
            // 合并所有Buffer片段
            const completeBuffer = Buffer.concat(chunks);
            // 解析数据包
            const messageLength = completeBuffer.readUInt32BE(0);
            const message = completeBuffer.slice(4, 4 + messageLength);
            console.log('收到消息:', message.toString());
            // 发送响应
            const response = Buffer.from('ACK\n', 'utf8');
            socket.write(response);
            chunks.length = 0;
            totalLength = 0;
        }
    });
    socket.on('error', (err) => console.error('Socket错误:', err));
});
server.listen(3000, () => {
    console.log('服务器监听端口3000');
    // 创建客户端测试
    setTimeout(() => {
        const client = net.connect(3000);
        const message = 'Hello Server';
        const dataBuffer = Buffer.alloc(4 + message.length);
        dataBuffer.writeUInt32BE(message.length, 0);
        dataBuffer.write(message, 4, 'utf8');
        client.write(dataBuffer);
        client.on('data', (data) => console.log('服务器响应:', data.toString()));
        client.end();
    }, 100);
});

文件处理的缓冲区案例

const fs = require('fs');
// 高效的文件流处理
function readLargeFile(filePath) {
    const chunks = [];
    let fileSize = 0;
    const stream = fs.createReadStream(filePath, { highWaterMark: 64 * 1024 }); // 64KB块
    stream.on('data', (chunk) => {
        chunks.push(chunk);
        fileSize += chunk.length;
        // 实时处理每个缓冲区块
        console.log(`读取块: ${chunk.length} 字节`);
        // 查找特定字节模式
        const search = Buffer.from('IMPORTANT');
        const index = chunk.indexOf(search);
        if (index !== -1) {
            console.log(`在偏移 ${fileSize - chunk.length + index} 处找到关键字`);
        }
    });
    stream.on('end', () => {
        console.log(`文件读取完成,总大小: ${fileSize} 字节`);
        const allData = Buffer.concat(chunks);
        return allData;
    });
    stream.on('error', (err) => console.error('读取错误:', err));
}
// 创建测试文件
fs.writeFileSync('test.txt', '这是一个测试文件\n包含IMPORTANT关键信息'.repeat(100));
readLargeFile('test.txt');

图像处理的缓冲区案例

// 简单的BMP图像处理示例
function processImageBuffer(buffer) {
    // BMP文件头:前14字节包含文件信息
    if (buffer.length < 54) {
        throw new Error('非有效的BMP文件');
    }
    // 解析BMP头信息
    const fileSize = buffer.readUInt32LE(2);
    const dataOffset = buffer.readUInt32LE(10);
    const width = buffer.readInt32LE(18);
    const height = buffer.readInt32LE(22);
    const bitsPerPixel = buffer.readUInt16LE(28);
    console.log(`BMP图像信息: ${width}x${height}, ${bitsPerPixel}位色`);
    // 图像数据处理示例:反转颜色
    const pixelDataStart = dataOffset;
    const pixelData = buffer.slice(pixelDataStart);
    if (bitsPerPixel === 24) { // 24位色(RGB)
        for (let i = 0; i < pixelData.length; i += 3) {
            // 反转RGB值
            const temp = pixelData[i];
            pixelData[i] = pixelData[i + 2];
            pixelData[i + 2] = temp;
        }
    }
    return buffer; // 返回处理后的图像
}
// 创建测试用的最小BMP
function createTestBMP(width, height) {
    const dataSize = width * height * 3;
    const offset = 54;
    const buffer = Buffer.alloc(offset + dataSize);
    // 文件头
    buffer.write('BM', 0); // 签名
    buffer.writeUInt32LE(offset + dataSize, 2); // 文件大小
    buffer.writeUInt32LE(0, 6); // 预留
    buffer.writeUInt32LE(offset, 10); // 数据偏移
    // DIB头
    buffer.writeUInt32LE(40, 14); // DIB头大小
    buffer.writeInt32LE(width, 18);
    buffer.writeInt32LE(height, 22);
    buffer.writeUInt16LE(1, 26); // 平面数
    buffer.writeUInt16LE(24, 28); // 位深度
    buffer.writeUInt32LE(0, 30); // 压缩
    buffer.writeUInt32LE(dataSize, 34); // 图像大小
    // 填充像素数据(示例:红色)
    for (let i = offset; i < buffer.length; i += 3) {
        buffer[i] = 0;     // B
        buffer[i+1] = 0;   // G
        buffer[i+2] = 255; // R
    }
    return buffer;
}
// 测试
const testBMP = createTestBMP(100, 100);
console.log('原始BMP大小:', testBMP.length);
const processedBMP = processImageBuffer(testBMP);
console.log('图像处理完成');

数据包解析案例

// 解析自定义协议的数据包
class DataPacketParser {
    constructor() {
        this.buffer = Buffer.alloc(0);
        this.callbacks = [];
    }
    // 添加解析回调
    onPacket(callback) {
        this.callbacks.push(callback);
    }
    // 处理接收的数据
    handleData(data) {
        // 合并到缓冲区
        this.buffer = Buffer.concat([this.buffer, data]);
        while (this.buffer.length >= 8) { // 最小包头8字节
            // 检查包头
            const magic = this.buffer.readUInt16LE(0);
            if (magic !== 0xABCD) {
                console.error('无效的包头');
                // 跳过无效字节
                this.buffer = this.buffer.slice(1);
                continue;
            }
            // 解析包头
            const packetLength = this.buffer.readUInt16LE(2);
            const type = this.buffer.readUInt8(4);
            const flags = this.buffer.readUInt8(5);
            const checksum = this.buffer.readUInt16LE(6);
            // 检查数据包完整性
            if (this.buffer.length >= packetLength + 8) {
                // 提取数据
                const payload = this.buffer.slice(8, 8 + packetLength);
                // 解析数据包
                const packet = {
                    type,
                    flags,
                    checksum,
                    payload: payload.toString('utf8')
                };
                // 调用回调
                this.callbacks.forEach(cb => cb(packet));
                // 移除已处理的数据
                this.buffer = this.buffer.slice(8 + packetLength);
            } else {
                // 等待更多数据
                break;
            }
        }
    }
}
// 创建协议包
function createDataPacket(type, data) {
    const payload = Buffer.from(data, 'utf8');
    const buffer = Buffer.alloc(8 + payload.length);
    buffer.writeUInt16LE(0xABCD, 0);      // 魔术字节
    buffer.writeUInt16LE(payload.length, 2); // 数据长度
    buffer.writeUInt8(type, 4);            // 类型
    buffer.writeUInt8(0, 5);               // 标志位
    // 简单校验和
    let sum = 0;
    for (let i = 0; i < payload.length; i++) {
        sum = (sum + payload[i]) & 0xFFFF;
    }
    buffer.writeUInt16LE(sum, 6);
    payload.copy(buffer, 8);
    return buffer;
}
// 测试
const parser = new DataPacketParser();
parser.onPacket((packet) => {
    console.log(`收到数据包 - 类型: ${packet.type}, 数据: "${packet.payload}"`);
});
// 模拟接收数据块(可能被分片)
const packet1 = createDataPacket(1, 'Hello');
const packet2 = createDataPacket(2, 'World');
// 发送前半部分
parser.handleData(packet1.slice(0, 5));
// 发送后半部分和第二个包
parser.handleData(Buffer.concat([packet1.slice(5), packet2]));

性能优化案例

// Buffer池化技术
class BufferPool {
    constructor(poolSize = 1024, bufferSize = 8192) {
        this.poolSize = poolSize;
        this.bufferSize = bufferSize;
        this.freeBuffers = [];
        this.inUse = new Set();
        this.initialize();
    }
    initialize() {
        for (let i = 0; i < this.poolSize; i++) {
            this.freeBuffers.push(Buffer.alloc(this.bufferSize));
        }
    }
    acquire() {
        let buffer = this.freeBuffers.pop();
        if (!buffer) {
            // 池已耗尽,创建新的
            buffer = Buffer.alloc(this.bufferSize);
            console.warn('Buffer池已耗尽,创建新缓冲区');
        } else {
            buffer.fill(0); // 清空旧数据
        }
        this.inUse.add(buffer);
        return buffer;
    }
    release(buffer) {
        if (this.inUse.has(buffer)) {
            this.inUse.delete(buffer);
            this.freeBuffers.push(buffer);
        } else {
            console.error('尝试释放不存在的缓冲区');
        }
    }
    getPoolStats() {
        return {
            total: this.poolSize,
            inUse: this.inUse.size,
            free: this.freeBuffers.length
        };
    }
}
// 使用示例
const pool = new BufferPool(5, 100);
// 模拟并发任务
function processData(data) {
    const buffer = pool.acquire();
    console.log(`获取缓冲区,状态:`, pool.getPoolStats());
    // 模拟数据处理
    setTimeout(() => {
        buffer.write(data);
        console.log(`处理: "${buffer.toString('utf8', 0, data.length)}"`);
        // 释放缓冲区
        pool.release(buffer);
        console.log(`释放缓冲区,状态:`, pool.getPoolStats());
    }, 100);
}
// 并发处理
processData('任务1');
processData('任务2');
processData('任务3');
processData('任务4');
processData('任务5');
processData('任务6'); // 这将导致池耗尽警告

二进制协议编解码案例

// 定长和变长字段的处理
class BinaryProtocol {
    // 编码
    static encode({ id, name, scores, tags }) {
        // 计算所需缓冲区大小
        const nameBuffer = Buffer.from(name, 'utf8');
        const tagsBuffer = Buffer.concat(tags.map(t => {
            const tagBuf = Buffer.from(t, 'utf8');
            const lenBuf = Buffer.alloc(1);
            lenBuf.writeUInt8(tagBuf.length);
            return Buffer.concat([lenBuf, tagBuf]);
        }));
        const count = scores.length;
        const totalSize = 2 + 1 + nameBuffer.length + 1 + count * 4 + 1 + tagsBuffer.length;
        const buffer = Buffer.alloc(totalSize);
        let offset = 0;
        // ID (2字节)
        buffer.writeUInt16LE(id, offset);
        offset += 2;
        // 名字长度 (1字节)
        buffer.writeUInt8(nameBuffer.length, offset);
        offset += 1;
        // 名字数据
        nameBuffer.copy(buffer, offset);
        offset += nameBuffer.length;
        // 分数数量 (1字节)
        buffer.writeUInt8(count, offset);
        offset += 1;
        // 分数数组 (每个4字节)
        scores.forEach(score => {
            buffer.writeFloatLE(score, offset);
            offset += 4;
        });
        // 标签数量 (1字节)
        buffer.writeUInt8(tags.length, offset);
        offset += 1;
        // 标签数据
        tagsBuffer.copy(buffer, offset);
        return buffer;
    }
    // 解码
    static decode(buffer) {
        let offset = 0;
        // 解析ID
        const id = buffer.readUInt16LE(offset);
        offset += 2;
        // 名字
        const nameLen = buffer.readUInt8(offset);
        offset += 1;
        const name = buffer.toString('utf8', offset, offset + nameLen);
        offset += nameLen;
        // 分数
        const scoreCount = buffer.readUInt8(offset);
        offset += 1;
        const scores = [];
        for (let i = 0; i < scoreCount; i++) {
            scores.push(buffer.readFloatLE(offset));
            offset += 4;
        }
        // 标签
        const tagCount = buffer.readUInt8(offset);
        offset += 1;
        const tags = [];
        for (let i = 0; i < tagCount; i++) {
            const tagLen = buffer.readUInt8(offset);
            offset += 1;
            tags.push(buffer.toString('utf8', offset, offset + tagLen));
            offset += tagLen;
        }
        return { id, name, scores, tags };
    }
}
// 测试
const data = {
    id: 42,
    name: '张三',
    scores: [89.5, 92.3, 78.8],
    tags: ['优秀', '进步', '努力']
};
const encoded = BinaryProtocol.encode(data);
console.log('编码后大小:', encoded.length, '字节');
const decoded = BinaryProtocol.decode(encoded);
console.log('解码数据:', decoded);
  1. 缓冲区分片处理:处理大数据时要分片,避免内存溢出
  2. Buffer复用:使用池化技术,避免频繁创建/销毁
  3. 内存安全:及时释放不再使用的Buffer,防止内存泄漏
  4. 边界检查:始终验证读取/写入的字节范围
  5. 性能优化:预分配缓冲区,减少动态扩容
  6. 错误处理:对空缓冲区、无效数据等做好异常处理

这些案例展示了Buffer在不同场景中的应用,从基本的读写操作到复杂的协议处理,都是Node.js开发中常见的情况。

抱歉,评论功能暂时关闭!