很久没搞nodejs了 , node版本从4升到7 , 迭代很快,现在过来复习一下文件相关的api,虽说有些api不推荐使用或者说过时了,但是还能跑 :)

  • readFile 和 readFileSync
    同步读取文件和异步读取文件,在官方文档上已经说的很清晰了,API也讲的很明白,只要玩好API就行。
"use strict";
const fs = require('fs');

// 简单的异步读取
fs.readFile('yourFilePath','utf8',function(err,data){
    if(err) throw err;
    console.log(data);
});

// 简单的同步读取
try{
    var data = fs.readFileSync('yourFilePath','utf8');
    console.log(data); // 文件数据
}catch(e){
    console.log(e);
}
  • writeFile 和 writeFileSync
    同步和异步读写文件
"use strict";
const fs = require('fs');
const path = require('path');

// 注意这两种方式都会对文件造成覆盖写入。
// 且只能针对小文件。

// 异步写入
fs.writeFile(path.join(__dirname,'yourFileName'),'hello',function(err){
    if(err) console.log(err.code);
    console.log('文件异步写入成功!');
});

// 同步写入
try {
    fs.writeFileSync(path.join(__dirname, 'yourFileName'),'world');
    console.log('文件同步写入成功!');
} catch(e) {
    console.log('文件同步写入失败!');
}
  • exists 和 existsSync
    判断文件是否存在,同步和异步方式 , 验证文件是否存在api
"use strict";
const fs = require('fs');
const path = require('path');

let _path = path.join(__dirname,'yourFileName');
// 异步
fs.exists(_path,(exists)=>{
    console.log('exists ' + exists);
});

// 同步判断文件是否存在
var flag = fs.existsSync(_path);
console.log('flag ' + flag);
  • stat 和 statSync
    获取文件信息API
"use strict";
const fs = require('fs');
const path = require('path');

let _path = path.join(__dirname,'yourFileName');

// 异步获取文件信息API
fs.stat(_path,(err,stats)=>{
    if (err) throw err;
    console.log(`文件大小: ${stats.size} 字节`);
    console.log(`文件创建时间: ${stats.ctime} `);
    console.log(`文件最后访问时间: ${stats.atime} `);

    // 判断路径是文件或者是文件夹
    if(stats.isFile()){
        console.log('该路径代表一个文件');
    }else if(stats.isDirectory()){
        console.log('该路径代表一个目录');
    }
});

// fs 同步读取文件信息
let stats = fs.statSync(_path);

if(stats.isFile()){
    console.log('同步方式,该路径代表一个文件');
}else if(stats.isDirectory()){
    console.log('同步方式,该路径代表一个目录');
}
  • rmdir 和 rmdirSync
    删除文件夹,同步和异步方式
"use strict";

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

let _path = path.join(__dirname,'yourDir');

// 进行删除和创建文件夹的时候都要先判断文件是否存在

// 异步方式删除
fs.exists(_path,(exists)=>{
  if(exists){
      // 如果存在,则删除目录
      return fs.rmdir(_path,(err)=>{
          if(err) return console.log('文件删除失败!');
          console.log('文件删除成功');
      });
  }
  // 如果不存在,才去创建目录
  fs.mkdir(_path,(err)=>{
      if (err) return console.log('目录未创建成功!');
      console.log('目录创建成功!');
  });
});

// 同步方式 (如果存在,删除;不存在,创建)
var flag = fs.existsSync(_path);
flag ? fs.rmdirSync(_path) : fs.mkdirSync(_path);
  • watchFile 和 unwatchFile 以及 watch
    监听文件变化和停止监听
"use strict"

const fs = require('fs');
const path = require('path');
let filePath = path.join(__dirname,'yourFileName');
let filePath2 = path.join(__dirname,'yourFileName2');

// 参数
var json = {
  persistent:true,
  interal:100
};

// 监听器
var listener = function(cur,pre){
console.log(`当前文件修改时间:${cur.mtime}`);
console.log(`上次文件修改时间:${pre.mtime}`);
};

// 监视文件的变化
fs.watchFile(filePath,json,listener);

// 3s 后停止监听文件变化
setTimeout(function(){
  console.log('go');    
  fs.unwatchFile(filePath,listener);
},3000);

// 使用watch监听----------------------------

// 参数
var option = {
    persistent:true,
    recursive:true,
    encoding:'utf8'
}

// 监视器
var watchListener = function(eventType, filename){
   console.log('eventType ' + eventType);
   console.log('filename ' + filename);
}

// 开始监听
var watcher = fs.watch(filePath2,option,watchListener);

// 1s 后停止监听
setTimeout(function(){
  console.log('goes');    
  watcher.close();
},1000);
  • 备注: The fs.watch API is not 100% consistent across platforms, and is unavailable in some situations. The recursive option is only supported on OS X and Windows.
  • readStream 和 writeStream
    文件读取流和文件写入流
"use strict";

const fs = require('fs');
const path = require('path');
let filePath = path.join(__dirname, 'yourFileName') ;
let distPath =  path.join(__dirname, 'fileNameYouWant');

// 创建一个文件读取流
let readStream = fs.createReadStream(filePath);

// 创建一个文件写入流
let writeStream = fs.createWriteStream(distPath);

// 读取流的 data 事件会被不停触发
readStream.on('data', function (chunk) {
  writeStream.write(chunk); // 读一点,写一点儿
});

// 读取结束将会触发 end 事件
readStream.on('end', function (chunk) {
  console.log('拷贝结束');
});
  • 使用pipe管道来边读边写
"use strict";

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

let filePath = path.join(__dirname,'yourFileName');
let distPath = path.join(__dirname,'fileNameYouWant');

fs.createReadStream(filePath).pipe(fs.createWriteStream(distPath));
  • readline 按行来读取
"use strict";

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

let json = {
    input:fs.createReadStream(path.join(__dirname,'theFileYouWantCopy'),'utf8')
}

let distPath = path.join(__dirname,'fileYouWantGenerate');

const rl = readline.createInterface(json); // 创建一个行文件读取接口

// 读取行事件
rl.on('line',(line)=>{
    // fs.appendFile 不会覆盖原文件
    fs.appendFile(distPath,'\n' + line,'utf8',(err)=>{
        if(err) return console.log(err);
        console.log('do line copy');
    });
});

// 读取完毕事件
rl.on('close',()=>{
    console.log('读取完成!'); // 上面fs.appendFile是异步,此处可能会先输出,没有什么影响。
});
  • 其他问题
  • 文件编码转换 ,在nodejs中有个插件:iconv-lite
  • 首先安装插件: npm i --save iconv-lite
  • 示例代码:
"use strict";

const fs = require('fs');
const iconv = require('iconv-lite');
const path = require('path');

let filePath = path.join(__dirname,'gbk.txt'); // 假设这是你的gbk编码的文件
let distPath = path.join(__dirname,'utf8.txt'); // 假设这是你想重新输出的utf8文件

fs.readFile(filePath,function (err, data) {
  if (err) throw err;
  // iconv的decode方法就可以用来解码,需指定一个原始的二进制数据和字符集编码
  let res =iconv.decode(data, 'gbk');
  // 先判断是否存在,存在则append , 不存在,直接写。
  fs.exists(distPath,(exists)=>{
    if(exists){
      fs.appendFile(distPath,'\n' + res,'utf8',(err)=>{
        if(err) throw err;
        console.log('追加成功!');
      });
    }else{
      fs.writeFile(distPath,res,'utf8',(err)=>{
        if(err) throw err;
        console.log('写入完成!');
      });
    }
  });
});