nodejs学习(二)Buffer、fs

一、  Buffer(缓冲区)

1. JavaScript 语言没有读取或操作二进制数据流的机制。
2. Node.js 中引入了 Buffer 类型使我们可以操作 TCP流 或 文件流。
3. Buffer 类型的对象类似于整数数组,但 Buffer 的大小是固定的、且在 V8 堆外分配物理内存。 Buffer 的大小在被创建时确定,且无法调整。( buf.length 是固定的,不允许修改 )
4. Buffer 是全局的,所以使用的时候无需 require() 的方式来加载

 

  1.Buffer的操作

• 使用Buffer保存字符串
   let str = "你好";
   let buf = Buffer.from(str , "utf-8"); 
    
• 创建指定大小的Buffer对象
    let buf3 = Buffer.alloc(1024*8)

   2.Buffer的转换

• Buffer与字符串间的转换
  – 支持的编码:
    • ASCII、 UTF-8、 UTF-16LE/UCS-2、 Base64、Binary、 Hex
– 字符串转Buffer
  • Buffer.from(str , [encoding]);
– Buffer转字符串
  • buf.toString([encoding] , [start] , [end]);

  3.写入操作

• 向缓冲区中写入字符串
    – buf.write(string[, offset[, length]][, encoding])
• 替换指定索引位置的数据
    – buf[index]
• 将指定值填入到缓冲区的指定位置
    – buf.fill(value[, offset[, end]][, encoding])

  4.读取操作

• 将缓冲区中的内容,转换为一个字符串返回
    – buf.toString([encoding[, start[, end]]])
• 读取缓冲区指定索引的内容
    – buf[index]

  5.其他操作

• 复制缓冲区
    – buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])
• 对缓冲区切片
    – buf.slice([start[, end]])
• 拼接缓冲区
    – Buffer.concat(list[, totalLength])

 

二、fs(文件系统)

• 在Node中,与文件系统的交互是非常重要的,服务器的本质就将本地的文件发送给远程的客户端
• Node通过fs模块来和文件系统进行交互

• 该模块提供了一些标准文件访问API来打开、读取、写入文件,以及与其互。

• 要使用fs模块,首先需要对其进行加载
    – const fs = require("fs");

  1.同步和异步调用

• fs模块中所有的操作都有两种形式可供选择同步和异步。

• 同步文件系统会阻塞程序的执行,也就是除非操作完毕,否则不会向下执行代码。

• 异步文件系统不会阻塞程序的执行,而是
在操作完成时,通过回调函数将结果返回。

  2.打开和关闭文件

• 打开文件
    – fs.open(path, flags[, mode], callback)
    – fs.openSync(path, flags[, mode])
• 关闭文件
    – fs.close(fd, callback)
    – fs.closeSync(fd)

  3.打开状态

模式 说明
r 读取文件 , 文件不存在则出现异常
r+ 读写文件 , 文件不存在则出现异常
rs 在同步模式下打开文件用于读取
rs+ 在同步模式下打开文件用于读写
w 打开文件用于写操作 , 如果不存在则创建,如果存在则截断
wx 打开文件用于写操作, 如果存在则打开失败
w+ 打开文件用于读写, 如果不存在则创建, 如果存在则截断
wx+ 打开文件用于读写, 如果存在则打开失败
a 打开文件用于追加, 如果不存在则创建
ax 打开文件用于追加, 如果路径存在则失败
a+ 打开文件进行读取和追加, 如果不存在则创建该文件
ax+ 打开文件进行读取和追加,如果路径存在则失败

  4.写入文件

• fs中提供了四种不同的方式将数据写入文件
    – 简单文件写入
    – 同步文件写入
    – 异步文件写入
    – 流式文件写入

  1.简单文件写入

• fs.writeFile(file, data[, options], callback)
• fs.writeFileSync(file, data[, options])
• 参数:
– file 文件路径
    – data 被写入的内容,可以是String或Buffer
    – options 对象,包含属性(encoding、 mode、flag)
    – callback 回调函数
//注意:
    - 该操作采用异步执行
    - 如果文件已经存在则替换掉
    - 默认写入的文件编码为utf8
    - 回调函数有1个参数:err,表示在写入文件的操作过程中是否出错了。
    - 如果出错了`err != null`,否则 `err === null`

 

  demo:

/*
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])

    file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符/要操作的文件路径
    data <string> | <Buffer> | <TypedArray> | <DataView> | <Object> 要写入的数据
    options <Object> | <string> 选项,可以对写入进行一些设置
        encoding <string> | <null> 默认值: 'utf8'
        mode <integer> 默认值: 0o666
        flag <string> 请参阅对文件系统 flags 的支持。 默认值: 'w'。
    callback <Function>
            err <Error> | <AggregateError>
**/

//导入文件模块
var fs = require("fs");


//创建要写入的信息
var msg = "hello world! 你好,世界!";
var msg1 = "第二次写入会不会覆盖第一次的呢?"

//参数分别是文件路径,要写入的信息,编码,回调函数,回调函数需要有一个参数err
//这种是覆盖写入,文件不存在则新建文件后写入,文件存在则覆盖写入
fs.writeFile("./test.txt", msg1, "utf8", function (err) {
        console.log("+++++++++++++++++++++" + err + "============")
        if (err) {

            console.log("写入文件出错,详细信息" + err)
            throw err;

        } else {
            console.log("写入文件成功")

        }


    }
)

  2.同步文件写入

• fs.writeSync(fd, buffer, offset, length[, position])
• fs.writeSync(fd, data[, position[, encoding]])
• 要完成同步写入文件,先需要通过openSync()打开文件来获取
   一个文件描述符,然后在通过writeSync()写入文件。
• 参数
    – fd 文件描述符,通过openSync()获取
    – data 要写入的数据(String 或 Buffer)
    – offset buffer写入的偏移量
    – length 写入的长度
    – position 写入的起始位置
    – encoding 写入编码

  demo:

/*
  手动操作文件的步骤
    1.打开文件:
        fs.openSync(path[, flags[, mode]])
        - path 要打开文件的路径
        - flags 打开文件要操作的类型:默认为r
            r:只读
            w:可写的
         - mode 设置文件的操作权限,一般不传(默认可读可写)

   2.向文件中写入内容
    fs.writeSync(fd, string[, position[, encoding]])
        - fd 文件描述符
        - string <string> | <Object> 要写入的内容被
        - position <integer> 写入的其实位置
        - encoding <string> 编码
        返回: <number> 写入的字节数。
        如果 string 是普通的对象,则它必须具有自有的(不是继承的)toString 函数属性。

   3.保存关闭文件
    fs.closeSync(fd)
        fd <integer>关闭文件描述符。 返回 undefined。
*/

var fs = require("fs");


//w模式会覆盖写入
var fd = fs.openSync("test.txt", "w");
console.log("描述符:" + fd);

var length = fs.writeSync(fd, "这是同步写入的内容");
console.log("写入的长度:" + length);

fs.closeSync(fd);

  3.异步文件写入

• fs.write(fd, buffer, offset, length[, position], callback)
• fs.write(fd, data[, position[, encoding]], callback)
• 要使用异步写入文件,先需要通过open()打开文件,然后在回
调函数中通过write()写入。
• 参数:
    – fd 文件描述符
    – data 要写入的数据(String 或 Buffer)
    – offset buffer写入的偏移量
    – length 写入的长度
    – position 写入的起始位置
    – encoding 写入编码

  demo

/*
  手动操作文件的步骤
    1。异步打开文件:
        fs.open(path[, flags[, mode]], callback)
        - path 要打开文件的路径
        - flags 打开文件要操作的类型:默认为r
            r:只读
            w:可写的
         - mode 设置文件的操作权限,一般不传(默认可读可写)
         - callback 回调有两个参数 (err, fd)。
            err:错误对象,如果没有则为null
             fd:文件描述符
         返回值:该方法会返回一个文件描述符作为结果,我们可以通过该操作符来文件进行各种操作
    fs.write(fd, buffer[, offset[, length[, position]]], callback)
        用来异步写入一个文件
    fs.close(fd[, callback])
        -用来关闭文件
*/

var fs = require("fs");
fs.open("异步test.txt", "w", function (err, fd) {
    //判断是否出错
    if (!err) {
        fs.write(fd, "这是异步写入内容", function (err) {
            if (!err) {
                console.log("写入成功");
                fs.close(fd, function (err) {
                    if (!err) {
                        console.log("文件关闭成功");
                    } else {
                        console.log("文件关闭失败");
                    }

                })
            } else {
                console.log("写入失败");
            }

        })
    }

});

console.log("这个应该比异步的先执行完,对吧?")

  

  4.流式文件写入

• 往一个文件中写入大量数据时,最好的方法之一
是使用流。
• 若要将数据异步传送到文件,首需要使用以下语
法创建一个Writable对象:
    – fs.createWriteStream(path[, options])
• path 文件路径
• options {encoding:"",mode:"",flag:""}
• 一旦你打开了Writable文件流,就可以使用
write()方法来写入它,写入完成后,在调用end()
方法来关闭流。

  demo

//流式写入
//创建可写流
/*
  fs.createWriteStream(path[, options])
    - 可以用来创建一个可写流
    - path :文件路径
    - options 配置参数

 */

var fs = require("fs");
var ws = fs.createWriteStream("writerstream.txt");

//可以通过监听流的打开和关闭事件来监听流的打开和关闭
/*
    on(时间字符,回调函数)
        -可以为对象绑定一个事件
    once(事件字符串,回调函数)
        - 可以为对象绑定一个一次性事件,该事件会将在出发一次后自动回滚失效
 */

ws.once("open", function () {
    console.log("六打开了");

})

ws.on("close", function () {
    console.log("流关闭了");

})

//通过ws像文件输入内容
ws.write("第一次输入");
ws.write("第二次输入");
ws.write("第三次输入");

//关闭流
ws.end()

  

  5.读取文件

• fs中提供了四种读取文件的方式
    – 简单文件读取
    – 同步文件读取
    – 异步文件读取
    – 流式文件读取

    1.简单文件读取

• fs.readFile(file[, options], callback)
• fs.readFileSync(file[, options])
– 参数:
  • file 文件路径或文件描述符
  • options <Object> | <String>
    – encoding <String> | <Null> 默认 = null
    – flag <String> 默认 = 'r'
  • callback 回调函数,有两个参数err 、 data
    err 错误对象
    data 返回一个buffer,要转成字符串需要data.tostring

    demo1

var fs = require('fs');
fs.readFile("./test.txt", "utf-8", function (err, data) {
    console.log("data:" + data);
    console.log("err:" + err);
    if (err) {
        console.log("读取文件出错了:错误是" + err)
    } else {
        console.log("读取文件成功,以下为内容:")
        console.log(data)

        //当option的编码没有指定,返回的是一个buffer
        // console.log(data.toString())
    }
})

    demo2:读取并写入零一个文件

var fs = require('fs');
fs.readFile("C:\\Users\\tjp40922\\Desktop\\a.png", function (err, data) {
    console.log("err:" + err);
    if (err) {
        console.log("读取文件出错了:错误是" + err)
    } else {
        console.log("读取文件成功")
        fs.writeFile("copy.png",data,function (err) {
            if (!err){
                console.log("写入成功")

            }else {
                console.log("写入失败。。,原因是:");
                console.log(err)

            }

        })
        
    }
})

    2.同步文件读取

• fs.readSync(fd, buffer, offset, length,
position)
– 参数:
  • fd 文件描述符
  • buffer 读取文件的缓冲区
  • offset buffer的开始写入的位置
  • length 要读取的字节数
  • position 开始读取文件的位置

    3.异步文件读取

• fs.read(fd, buffer, offset, length,
position, callback)
– 参数:
    • fd 文件描述符
    • buffer 读取文件的缓冲区
    • offset buffer的开始写入的位置
    • length 要读取的字节数
    • position 开始读取文件的位置
    • callback 回调函数 参数err , bytesRead , buffer

    4.流式文件读取

• 从一个文件中读取大量的数据时,最好的方法之一就是流式读取,这样将把一个文件作为Readable流的形式打开。
• 要从异步从文件传输数据,首先需要通过以下语法创建一个Readable流对象: – fs.createReadStream(path[, options]) • path 文件路径 • options {encoding:
"",mode:"",flag:""}
• 当你打开Readable文件流以后,可以通过readable事件和read()请求,或通过data事件处理程序轻松地从它读出。

  demo1

var fs = require("fs");

//创建一个可读流
var rs = fs.createReadStream("writerstream.txt");

//监听流的开启和关闭
rs.once("open", function () {
    console.log("可读流打开了");

})

rs.on("close", function () {
    console.log("可读流关闭了");
})

//如果要读取一个刻度流中的数据,必须为可读流绑定一个data事件,data事件绑定完毕,他会自动开始读取数据
rs.on("data",function (data) {
    console.log(data.toString())
    
})

  demo2:从一个流到另一个流

var fs = require("fs");

//创建一个可读流
var rs = fs.createReadStream("writerstream.txt");
var ws = fs.createWriteStream("tttt.txtt");

//监听流的开启和关闭
rs.once("open", function () {
    console.log("可读流打开了");

})

rs.on("close", function () {
    console.log("可读流关闭了");
    // 在可读流关闭后也要关闭可写流
    ws.end();
})

ws.once("open", function () {
    console.log("可写流打开了");

})

ws.on("close", function () {
    console.log("可写流关闭了");
})


//如果要读取一个刻度流中的数据,必须为可读流绑定一个data事件,data事件绑定完毕,他会自动开始读取数据
rs.on("data", function (data) {
    console.log(data.toString())
    //把可读流的数据写入可写流
    //这边要注意,不能再这里关闭可写流,要不然只会昔日如一次
    ws.write(data);

})

    可以用更加简单的pipe

var fs = require("fs");

//创建一个可读流
var rs = fs.createReadStream("writerstream.txt");
var ws = fs.createWriteStream("xdxx.txtt");

rs.pipe(ws);

  6.其他操作

• 删除目录
    – fs.rmdir(path, callback)
    – fs.rmdirSync(path)
• 重命名文件和目录
    – fs.rename(oldPath, newPath, callback)
    – fs.renameSync(oldPath, newPath)
• 监视文件更改写入
    – fs.watchFile(filename[, options], listener)

   注意:

1. 异步操作无法通过 try-catch 来捕获异常,要通过判断 error 来判断是否出错。
2. 同步操作可以通过 try-catch 来捕获异常。
3. 不要使用 `fs.exists(path, callback)` 来判断文件是否存在,直接判断 error 即可
4. 文件操作时的路径问题
   - 在读写文件的时候 './' 表示的是当前执行node命令的那个路径,不是被执行的js文件的路径
   - __dirname, 表示的永远是"当前被执行的js的目录"
   - __filename, 表示的是"被执行的js的文件名(含路径)"
5. error-first 介绍(错误优先)

 

posted @ 2022-03-20 21:22  阿布_alone  阅读(590)  评论(0编辑  收藏  举报
TOP