Skip to content

I/O 流操作

I/O 流操作

在 Node.js 中,I/O 操作非常重要,流(Stream)是处理 I/O 的一种高效方式。流可以帮助我们处理大量数据,减少内存的消耗并提高性能。流是通过 Node.js 中的 stream 模块提供的,主要分为四种类型:可读流、可写流、双工流和转换流。

流的基本概念

流(Stream)是一种抽象的数据处理方式,数据通过流从源传递到目标。流通常是基于事件驱动的,它允许我们对数据进行逐步处理而不是一次性将其载入内存。

流有以下几个基本特点:

  • 按需加载:流数据是按块传输的,而不是一次性读取所有数据,避免了内存消耗过大的问题。
  • 高效:在处理大量数据时,流通过分块处理和事件驱动机制,提供了更高效的数据处理方式。

了解 Buffer

在流操作中,Node.js 使用 Buffer 来处理字节数据。Buffer 是一种用于处理二进制数据的对象,它存储原始内存数据,类似于数组,但不同于普通的 JavaScript 数组,它是直接操作内存的。

  • 创建 Buffer:

    javascript
    const buf = Buffer.from('Hello, Node.js!');
    console.log(buf.toString());  // 输出:Hello, Node.js!
  • Buffer 的用途:Buffer 用于处理文件读取、网络传输等二进制数据。

可读流的使用

可读流(Readable Stream)是从数据源中读取数据的流。常见的可读流有文件读取流、HTTP 请求等。

流的读取模式与状态

  • 流的模式:

    • 流动模式(Flowing Mode):数据自动从流中读取并触发 'data' 事件。
    • 非流动模式(Paused Mode):数据不会自动流动,需要通过调用 read() 方法显式读取数据。
  • 流的状态:

    • paused:流处于暂停状态,数据不会自动流动。
    • flowing:流处于流动状态,数据会自动流动。

可读流的创建

可读流可以通过 stream.Readable 类或者 fs.createReadStream()(文件读取流)等方式创建。

  • 通过 Readable 类创建可读流:

    javascript
    const { Readable } = require('stream');
    
    const readable = new Readable({
      read(size) {
        this.push('Hello, ');
        this.push('world!');
        this.push(null);  // 标记流结束
      }
    });
    
    readable.on('data', (chunk) => {
      console.log(chunk.toString());  // 输出:Hello, world!
    });
  • 通过 fs.createReadStream() 创建文件可读流:

    javascript
    const fs = require('fs');
    
    const readableStream = fs.createReadStream('example.txt');
    readableStream.on('data', (chunk) => {
      console.log(chunk.toString());
    });

可读流的属性、方法及事件

  • 常用属性:

    • readable:指示流是否是可读流。
    • readableHighWaterMark:指示流的高水位标记,决定了流的内部缓冲区大小。
  • 常用方法:

    • read(size):从流中读取指定大小的数据。
    • pipe(destination):将可读流的数据传递给目标可写流。
  • 常用事件:

    • 'data':每次读取到数据时触发。
    • 'end':流结束时触发。
    • 'error':发生错误时触发。

可读流的常见操作

  • 从流中读取数据并处理:

    javascript
    const fs = require('fs');
    
    const readableStream = fs.createReadStream('example.txt');
    readableStream.on('data', (chunk) => {
      console.log(`Received ${chunk.length} bytes of data.`);
    });
    
    readableStream.on('end', () => {
      console.log('Stream finished!');
    });
  • 使用 pipe() 方法将可读流传递给可写流:

    javascript
    const fs = require('fs');
    
    const readableStream = fs.createReadStream('example.txt');
    const writableStream = fs.createWriteStream('output.txt');
    
    readableStream.pipe(writableStream);

可写流的使用

可写流(Writable Stream)是向数据目标写入数据的流。常见的可写流有文件写入流、HTTP 响应流等。

可写流的创建

  • 通过 Writable 类创建可写流:

    javascript
    const { Writable } = require('stream');
    
    const writable = new Writable({
      write(chunk, encoding, callback) {
        console.log(`Writing: ${chunk.toString()}`);
        callback();
      }
    });
    
    writable.write('Hello, ');
    writable.write('world!');
    writable.end();
  • 通过 fs.createWriteStream() 创建文件可写流:

    javascript
    const fs = require('fs');
    
    const writableStream = fs.createWriteStream('output.txt');
    writableStream.write('Hello, Node.js!');
    writableStream.end();

可写流的属性、方法及事件

  • 常用属性:

    • writable:指示流是否是可写流。
    • writableHighWaterMark:指示流的高水位标记,决定了流的内部缓冲区大小。
  • 常用方法:

    • write(chunk, encoding, callback):将数据写入流。
    • end():标记流结束。
  • 常用事件:

    • 'drain':缓冲区已清空,可以继续写入。
    • 'finish':所有数据都已写入并关闭流。

可写流的常见操作

  • 向流中写入数据:

    javascript
    const fs = require('fs');
    
    const writableStream = fs.createWriteStream('output.txt');
    writableStream.write('Hello, ');
    writableStream.write('Node.js!');
    writableStream.end();
  • 通过 pipe() 方法将可读流传递给可写流:

    javascript
    const fs = require('fs');
    
    const readableStream = fs.createReadStream('example.txt');
    const writableStream = fs.createWriteStream('output.txt');
    
    readableStream.pipe(writableStream);

双工流与转换流介绍

双工流(Duplex Stream)

双工流是既可以读取数据又可以写入数据的流。例如,net.Socket 是一个双工流,它既可以接收数据,也可以发送数据。

  • 创建双工流:

    javascript
    const { Duplex } = require('stream');
    
    const duplexStream = new Duplex({
      read(size) {
        this.push('Hello, ');
        this.push('world!');
        this.push(null);  // 标记流结束
      },
      write(chunk, encoding, callback) {
        console.log(`Writing: ${chunk.toString()}`);
        callback();
      }
    });
    
    duplexStream.write('Test data');
    duplexStream.on('data', (chunk) => {
      console.log(`Received: ${chunk.toString()}`);
    });

转换流(Transform Stream)

转换流是一种特殊类型的双工流,它可以在读取数据时进行转换,也可以在写入数据时进行转换。例如,压缩流、解压缩流、加密流等都是转换流。

  • 创建转换流:

    javascript
    const { Transform } = require('stream');
    
    const transformStream = new Transform({
      transform(chunk, encoding, callback) {
        this.push(chunk.toString().toUpperCase());
        callback();
      }
    });
    
    process.stdin.pipe(transformStream).pipe(process.stdout);

在上述示例中,transformStream 将输入流中的所有数据转换为大写字母后输出。

编程洪同学服务平台是一个广泛收集编程相关内容和资源,旨在满足编程爱好者和专业开发人员的需求的网站。无论您是初学者还是经验丰富的开发者,都可以在这里找到有用的信息和资料,我们将助您提升编程技能和知识。
专业开发
高端定制
售后无忧
站内资源均为本站制作或收集于互联网等平台,如有侵权,请第一时间联系本站,敬请谅解!本站资源仅限于学习与参考,严禁用于各种非法活动,否则后果自行负责,本站概不承担!