node 文件I/o fs模块

363 阅读3分钟

I/O input / output

  1. 对外部设备的输入输出
  2. 外部设备
    • 磁盘,网卡,显卡,打印机,其他...
  3. IO的速度往往低于内存和cpu的速度 《现代操作系统》-- 英文版
    • 所以其中fs方法大部分是回调函数或者promise

fs -- 文件系统 模块常用的api

模块支持以标准 POSIX 函数建模的方式与文件系统进行交互
要使用基于 promise 的 APIimport * as fs from 'fs/promises';
要使用回调和同步的 APIimport * as fs from 'fs';

基本 都有 promise 和 回调的一异步 和同步方法 promise 示例

  • 对同一文件执行多个并发修改时必须小心,否则可能会损坏数据
import { unlink } from 'fs/promises';

try {
  await unlink('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (error) {
  console.error('there was an error:', error.message);
}

回调函数 示例

  • 当需要最大性能(在执行时间和内存分配方面)时,fs 模块 API 的基于回调的版本比使用 promise API 更可取。
import { unlink } from 'fs';

unlink('/tmp/hello',(error, content) => {
    if(error) throw error
    console.log(content) // content 一般会用十六进制表示
});

同步示例 会导致js运行阻塞(使用场景一般在 初始化时使用)

import { unlinkSync } from 'fs';

try {
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // 处理错误
}
  1. fs.readFile(path[, options], callback) 异步读取文件全部内容
const fs = require("fs")
const path = require("path")

// 因为 node运行时会取当前所在文件的路径而不是运行文件路径,所以需要取绝对路径
const filename = path.resolve(__dirname,"./index.js") 
fs.readFile(filename,(error,content) => {
    if(error) throw error
    console.log(conetent)  // 获取的数据时buffer(实际是二进制) 打印出来十六进制的数字
    
    // 可以用toString("utf-8")方法转为字符串
    // h或者fs.readFile(filename,"utf-8",callback) 第二个参数传类型
})
  1. fsPromises.writeFile(file, data[, options])
    • 异步地将数据写入文件,如果文件已经存在,则替换该文件
    • 不想覆盖options 传对象{ flag: "a" // 追加内容 }
const fsPromise = require("fs/promises");
const path = require("path")

const filename = path.resolve(__dirname,"./a.js")
fs.readFile(filename,"utf-8",( error, content ) => {
  console.log(content, filename)
})

async function writeString() {
// 如果目录找不到则会报错,文件找不到会添加该文件,后面加上options 参数会在文件后面添加,否则时覆盖
  await fsPromise.writeFile(filename, "系统插入", { flag: "a" })
}
  1. fs.stat(path[, options]) 获取文件状态内容
async function getStat() {
  const stat = await fsPromise.stat(filename);
  stat.isDirectory() // 判断是不是目录 返回Boolean
  stat.isFile() // 判断是不是文件
  console.log(stat);
}
// 打印
Stats {
  dev: 1452664113,
  mode: 16822,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: 4096,
  ino: 1688849860267985,
  size: 0,     // 占用字节数,如果是文件的size是有的,目录原因是里面只存指向文件的指针
  blocks: 8,
  atimeMs: 1648478262769.7976, // 上次访问的时间戳
  mtimeMs: 1648477427945.434, // 上次修改的时间戳
  ctimeMs: 1648477427945.434, // 上次修改文件状态的时间戳
  birthtimeMs: 1646749596576.3237, // 文件创建的时间戳
  atime: 2022-03-28T14:37:42.770Z,
  mtime: 2022-03-28T14:23:47.945Z,
  ctime: 2022-03-28T14:23:47.945Z,
  birthtime: 2022-03-08T14:26:36.576Z
}
  1. fs.readdir(path[, options], callback) 返回一个存放文件名的数组(不能嵌套)
async function getList() {
  const list = await fsPromise.readdir(path.resolve(__dirname));
  console.log(list);
}
  1. fs.mkdir(path[, options]) 创建目录
async function createDir() {
  await fsPromise.mkdir(path.resolve(__dirname, './first'));
}
  1. fs.access(path[, mode]) 判断文件权限
// 用stat的isDirectory() 和 isFile() 
const stat = fs.statSync(path);  
// stat.isDirectory() 为true的话那么存在,如果为false不存在
try{
  stat.isFile() //走到这表示存在
}catch(e){
    // 走到这表示不存在
}
// 检查当前目录中是否存在该文件。
access(file, constants.F_OK, (err) => {
  console.log(`${file} ${err ? 'does not exist' : 'exists'}`);
});

// 检查文件是否可读。
access(file, constants.R_OK, (err) => {
  console.log(`${file} ${err ? 'is not readable' : 'is readable'}`);
});

// 检查文件是否可写。
access(file, constants.W_OK, (err) => {
  console.log(`${file} ${err ? 'is not writable' : 'is writable'}`);
});

// 检查文件是否可读可写。
access(file, constants.R_OK | constants.W_OK, (err) => {
  console.log(`${file} ${err ? 'is not' : 'is'} readable and writable`);
});
  1. fs.unlink(path, callback) 删除文件
  2. fs.rmdir(path[, options], callback) 删除目录
  3. fs.rm(path[, options], callback) 删除目录和文件