文件系统

@FileSystem
文件的读写操作
需要引入文件系统fs;通常全部引入,也可以解构引入某个具体业务,如仅仅需要读文件操作
更多信息,请访问 FS
const fs = require('fs')
const { readFile } = require('fs')
相关的API分为三类;我们主要采用回调风格的异步API;部分需要立刻拿到结果的场景,使用同步API
Callback API - 回调|异步API
The callback APIs perform all operations asynchronously, without blocking the event loop, then invoke a callback function upon completion or error.
const { unlink } = require('node:fs');

unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('successfully deleted /tmp/hello');
});        
Synchronous API - 同步API
The synchronous APIs perform all operations synchronously, blocking the event loop until the operation completes or fails.
const { unlinkSync } = require('node:fs');

try {
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}        
Promises API - Promises风格的API
The fs/promises API provides asynchronous file system methods that return promises.
const { unlink } = require('node:fs/promises');

(async function(path) {
  try {
    await unlink(path);
    console.log(`successfully deleted ${path}`);
  } catch (error) {
    console.error('there was an error:', error.message);
  }
})('/tmp/hello');
或使用.then()链式调用
常用函数
读文件
函数 说明
fs.readFile(path[, options], callback) 读取文件内容
fs.readFileSync(path[, options]) 同步读取文件内容
filehandle.createReadStream([options]) 以流方式读取文件内容
1. fs.readFile(path[, options], (err, data)=>{})
读文件;如果正常,读出文件内容;否则抛出错误信息
callback是异常信息err和督导的数据data
data默认是二进制流;可以使用toString()转换或JSON.parse()解析为可读或特定格式
使用选项指定编码为utf-8可以直接解析为可读信息;默认就是utf-8
普通文件 txt
const fs = require('fs')
fs.readFile('./data/demo.txt', (err, date) => {
  if (err) throw err;//res.send({msg:404})
  console.log(date);
  console.log(date.toString());
})
2. fs.readFileSync(path[, options])
只能读取本地文件系统中的文件,不能直接读取网络 URL
同步方式 - 适合小文件;否则会造成阻塞
以同步方式读取json文件,可以马上拿到结果,再根据后续的业务进行操作,如分页返回
let file = fs.readFileSync('./public/data/')
console.log(file)
console.log(file.toString())
const fs = require('fs');
let data = fs.readFileSync('./data/rank2024.json')
console.log(data);
let json = JSON.parse(data)
console.log(json);
如果有数据请求,可以定制路由返回解析的数据
server.get('/data', (req, res) => {
  res.send(data)
})
3. filehandle.createReadStream([options])
还可以使用流的方式访问文件 - createStream(),使用事件监听读取的过程
const fs = require('fs');
const file = fs.createReadStream('./public/data/food - 副本.json');
file.on('data', function (chunk) {
  console.log(chunk, '12345');
})
file.on('end', function () {
  console.log('end');
})      
Promises方式
const { readFile, writeFile } = require('fs/promises')
readFile('./public/data/todo.json')
  .then(res => console.log(res.toString()))
路径异常时抛出错误信息
read file [Error: ENOENT: no such file or directory, open 'C:\Users\cnplaman\Desktop\server\data1\demo.txt'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'open',
  path: 'C:\\Users\\cnplaman\\Desktop\\server\\data1\\demo.txt'
}
用户登录时,读取用户数据文件的业务
let file = fs.readFile('./public/data/' + req.query.usn + '.json', 'utf8', (err, data) => {
  if (err) {
    res.json({
      "errno": 2,
      "msg": 'user not exist'
    })
  } else {
    let jsonFile = JSON.parse(data)
    console.log('jsonFile', jsonFile);
    if (req.query.upass === jsonFile.upass) {
      res.json({
        "errno": 0,
        "msg": 'login ok'
      })
    } else {
      res.json({
        "errno": 1,
        "msg": 'password not match'
      })
    }
  }
})      
写文件
函数 说明
fs.writeFile(path[, options], callback) 写文件内容
fs.writeFileSync(path[, options]) 同步写文件内容
filehandle.createWriteStream([options]) 以流方式写文件内容
1. fs.writeFile(file, data[, options], err=>{})
默认以覆盖的方式写文件
data是要写入的数据
options中,指定写标记 flag 和编码 encoding 等选项;默认写标记是w - 覆盖,编码'utf8'
callback是异常信息err
路径必须存在:系统不会显示/自动创建路径;但是如果写入文件不存在,会创建
可以写入回车\n、制表位\t等转义符号
以追加 a 的方式,在文件最后写文件:先换行\n再输入数据888;如果文件不存在,就创建
const fs = require('fs')
fs.writeFile('./data/demo.txt', '\n888', { flag: 'a' }, (err) => {
if (err) throw err//res write('404')
  console.log('write ok');
})
2. fs.appendFile(path, data[, options], callback)
3. fs.appendFileSync(path, data[, options])
fs.stat(path[, options], callback)
文件/路径是否存在
早期使用fs.existsSync(path);该接口目前已经废弃
fs.access(path[, mode], callback)
用户对文件或目录的访问,可以用来判断目标是否存在
__dirname:获取js文件所在目录
fs.mkdir(path[, options], callback)
创建文件夹
如果存在,抛出异常,否则创建
const fs = require('fs')
if (fs.existsSync('./wwww')) throw err
fs.mkdirSync('./www')      
fs.rmdir(path[, options], callback)
删除文件夹:fs.rmdir(path[, options], err=>{})
fs.unlink(path, callback)
删除文件:fs.unlink(path, err=>{})
删除前,先判断文件是否存在
删除成功,callback返回null;可以根据这个进行业务再判断
const fs = require('fs')
if (fs.existsSync('./wwww/demo.txt')) throw err
fs.unlink('./www/demo.txt', (err) => {
  console.log(err);
})      
fs.rename(oldPath, newPath, callback)
改名
路径使用
join()
路径拼接
dirname()
获取路径名
extname()
获取扩展名
parse()
解析为对象,包括路径、文件扩展名、文件名等
{
  root: '',
  dir: '.',
  base: 'resource.js',
  ext: '.js',
  name: 'resource'
}
__filename
当前文件绝对路径
__dirname
当前目录绝对路径
注意
读写文件的路径,以引用当前文件的文件为准,不是以当前文件为准
test.js内容如下,读取一个json文件
index.js主文件引入并使用test.js
test.js中指定的文件位置以index.js为参考
  fs.readFile('./public/data/form.json', (err, data) => {
  })