文件操作

相关模块

Node内核提供了很多与文件操作相关的模块,每个模块都提供了一些最基本的操作API,在NPM中也有社区提供的功能包

  • fs:基础的文件操作 API

  • path:提供和路径相关的操作 API

  • readline:用于读取大文本文件,一行一行读

  • fs-extra(第三方):https://www.npmjs.com/package/fs-extra

同步或异步调用

fs模块对文件的几乎所有操作都有同步和异步两种形式。例如:readFile() 和 readFileSync()

调用方式阻塞代码执行什么时候回调异常处理
同步 - readFileSync阻塞try catch
异步 - readFile不阻塞将读取任务下达到任务队列,直到任务执行完成才会回调通过回调函数的第一个参数
// 同步
console.time('sync');
try {
  var data = fs.readFileSync(path.join('C:\\Users\\iceStone\\Downloads', 'H.mp4'));
} catch (error) {
  throw error;
}
console.timeEnd('sync');
// 异步
console.time('async');
fs.readFile(path.join('C:\\Users\\iceStone\\Downloads', 'H.mp4'), (error, data) => {
  if (error) throw error;
});
console.timeEnd('async');

路径模块

在文件操作的过程中,都必须使用物理路径(绝对路径),path模块提供了一系列与路径相关的 API

  • path.join:拼接多个路径部分,并转化为正常格式
  • path.basename(temp):获取路径中的文件名
  • path.basename(temp, '.lrc'):获取路径中的文件名并排除扩展名
  • process.platform:操作系统
  • path.delimiter:路径分隔符
  • process.env.PATH.split(path.delimiter):一般用于分割环境变量
  • path.dirname(temp):获取一个路径中的目录部分
  • path.extname(temp):获取一个路径中最后的扩展名
  • path.parse(temp):将一个路径解析成一个对象的形式
  • path.format(pathObject):将一个路径对象再转换为一个字符串的形式
  • path.isAbsolute(temp):获取一个路径是不是绝对路径
  • path.normalize('.../a.txt'):将一个路径转换为当前系统默认的标准格式,并解析其中的./和…/
  • path.relative(__dirname, temp):获取第二个路径相对第一个路径的相对路径
  • path.resolve(temp, 'c:/', './develop', '../application'):以类似命令行cd命令的方式拼接路径
  • path.sep:获取不同平台中路径的分隔符(默认)
  • path === path.win32:允许在任意平台下以WIN32的方法调用PATH对象
  • path === path.posix:允许在任意平台下以POSIX的方法调用PATH对象

源码地址:
https://github.com/nodejs/node/blob/master/lib/path.js

文件读取

readFile

fs.readFile(file[, options], callback(error, data))

fs.readFile('c:\\demo\1.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});
readFileSync

fs.readFileSync(file[, options])

try {
  const data = fs.readFileSync('c:\\demo\1.txt', 'utf8');
  console.log(data);
} catch(e) {
  // 文件不存在,或者权限错误
  throw e;
}
createReadStream

fs.createReadStream(path[, options])

const stream = fs.createReadStream('c:\\demo\1.txt');
let data = ''
stream.on('data', (trunk) => {
  data += trunk;
});
stream.on('end', () => {
  console.log(data);
});

由于Windows平台下默认文件编码是GBK,在Node中不支持,可以通过iconv-lite解决

Readline模块逐行读取文本内容

const readline = require('readline');
const fs = require('fs');

const rl = readline.createInterface({
  input: fs.createReadStream('sample.txt')
});

rl.on('line', (line) => {
  console.log('Line from file:', line);
});

文件写入

writeFile

fs.writeFile(file, data[, options], callback(error))

fs.writeFile('c:\\demo\a.txt', new Date(), (error) => {
  console.log(error);
});
writeFileSync

fs.writeFileSync(file, data[, options])

try {
  fs.writeFileSync('c:\\demo\a.txt', new Date());
} catch (error) {
  // 文件夹不存在,或者权限错误
  console.log(error);
}
createWriteStream

fs.createWriteStream(path[,option])

var streamWriter = fs.createWriteStream('c:\\demo\a.txt');
setInterval(() => {
  streamWriter.write(`${new Date}\n`, (error) => {
    console.log(error);
  });
}, 1000);
appendFile

fs.appendFile(file,data[,options],callback(err))

// 相比较之前文件流的方式,这种方式不会占用文件资源,append完成就会释放
setInterval(() => {
  fs.appendFile('c:\\demo\a.txt',`${new Date}\n`, (error) => {
    console.log(error);
  });
}, 1000);
appendFileSync

fs.appendFileSync(file,data[,options])

setInterval(() => {
  fs.appendFileSync('c:\\demo\a.txt',`${new Date}\n`);
}, 1000);

其他常见文件操作

文件操作异步同步
验证路径是否存在fs.exists(path,callback(exists))fs.existsSync(path) 返回布尔类型 exists
获取文件信息fs.stat(path,callback(err,stats))fs.statSync(path) 返回一个fs.Stats实例
移动文件或重命名文件或目录fs.rename(oldPath,newPath,callback)fs.renameSync(oldPath,newPath)
删除文件fs.unlink(path,callback(err))fs.unlinkSync(path)

其他常见文件夹操作

文件夹操作异步同步
创建一个目录fs.mkdir(path[,model],callback)fs.mkdirSync(path[,model])
删除一个空目录fs.rmdir(path,callback)fs.rmdirSync(path)
读取一个目录fs.readdir(path,callback(err,files))fs.readdirSync(path) 返回files

文件监视

利用文件监视实现自动 markdown 文件转换
  • 相关链接:

    1. https://github.com/chjj/marked
    2. https://github.com/Browsersync/browser-sync
  • 实现思路:

    1. 利用fs模块的文件监视功能监视指定MD文件
    2. 当文件发生变化后,借助marked包提供的markdown to html功能将改变后的MD文件转换为HTML
    3. 再将得到的HTML替换到模版中
    4. 最后利用BrowserSync模块实现浏览器自动刷新
const fs = require('fs');
const path = require('path');
var marked = require('marked');
var bs = require('browser-sync').create();

var target = path.join(__dirname, process.argv[2] || './README.md');
var filename = path.basename(target, path.extname(target)) + '.html';
var targetHtml = path.join(path.dirname(target), filename);

bs.init({
  server: path.dirname(target),
  index: filename,
  notify: false
});

bs.reload(filename);

var template = `<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <style>{{{styles}}}</style>
</head>
<body>
  <article class="markdown">
    {{{body}}}
  </article>
</body>
</html>
`;

fs.readFile(path.join(__dirname, './markdown.css'), 'utf8', (error, css) => {
  if (error) throw error;
  template = template.replace('{{{styles}}}', css);
  var handler = (current, previous) => {
    fs.readFile(target, 'utf8', (error, content) => {
      var html = template.replace('{{{body}}}', marked(content));
      fs.writeFile(targetHtml, html, (error) => {
        if (!error) {
          console.log(`updated@${new Date()}`);
          bs.reload(filename);
        }
      });
    });
  };
  handler();
  fs.watchFile(target, { interval: 100 }, handler);
});
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐