Node基礎篇(文件操作)


文件操作

相關模塊

Node內核提供了很多與文件操作相關的模塊,每個模塊都提供了一些最基本的操作API,在NPM中也有社區提供的功能包

fs:

基礎的文件操作 API

path:

提供和路徑相關的操作 API

readline:

用於讀取大文本文件,一行一行讀

fs-extra(第三方):

https://www.npmjs.com/package/fs-extra

同步或異步調用

  • fs模塊對文件的幾乎所有操作都有同步和異步兩種形式
  • 例如:readFile() 和 readFileSync()
  • 區別:
    • 同步調用會阻塞代碼的執行,異步則不會
    • 異步調用會將讀取任務下達到任務隊列,直到任務執行完成才會回調
    • 異常處理方面,同步必須使用 try catch 方式,異步可以通過回調函數的第一個參數

路徑模塊

在文件操作的過程中,都必須使用物理路徑(絕對路徑),path模塊提供了一系列與路徑相關的 API

console.log('join用於拼接多個路徑部分,並轉化為正常格式');
const temp = path.join(__dirname, '..', 'lyrics', './友誼之光.lrc');
console.log(temp);

console.log('獲取路徑中的文件名');
console.log(path.basename(temp));

console.log('獲取路徑中的文件名並排除擴展名');
console.log(path.basename(temp, '.lrc'));

console.log('====================================');

console.log('獲取不同操作系統的路徑分隔符');
console.log(process.platform + '的分隔符為 ' + path.delimiter);

console.log('一般用於分割環境變量');
console.log(process.env.PATH.split(path.delimiter));

console.log('====================================');

console.log('獲取一個路徑中的目錄部分');
console.log(path.dirname(temp));

console.log('====================================');

console.log('獲取一個路徑中最后的擴展名');
console.log(path.extname(temp));

console.log('====================================');

console.log('將一個路徑解析成一個對象的形式');
const pathObject = path.parse(temp);
console.log(pathObject);

console.log('====================================');

console.log('將一個路徑對象再轉換為一個字符串的形式');
// pathObject.name = '我終於失去了你';
pathObject.base = '我終於失去了你.lrc';
console.log(pathObject);

console.log(path.format(pathObject));

console.log('====================================');

console.log('獲取一個路徑是不是絕對路徑');
console.log(path.isAbsolute(temp));
console.log(path.isAbsolute('../lyrics/愛的代價.lrc'));

console.log('====================================');

console.log('將一個路徑轉換為當前系統默認的標准格式,並解析其中的./和../');
console.log(path.normalize('c:/develop/demo\\hello/../world/./a.txt'));

console.log('====================================');

console.log('獲取第二個路徑相對第一個路徑的相對路徑');
console.log(path.relative(__dirname, temp));

console.log('====================================');

console.log('以類似命令行cd命令的方式拼接路徑');
console.log(path.resolve(temp, 'c:/', './develop', '../application'));

console.log('====================================');

console.log('獲取不同平台中路徑的分隔符(默認)');
console.log(path.sep);

console.log('====================================');

console.log('允許在任意平台下以WIN32的方法調用PATH對象');
// console.log(path.win32);
console.log(path === path.win32);

console.log('====================================');

console.log('允許在任意平台下以POSIX的方法調用PATH對象');
console.log(path === path.posix);

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

文件讀取

Node中文件讀取的方式主要有:

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

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

fs.readFileSync(file[, options])

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

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);
});

文件寫入

Node中文件寫入的方式主要有:

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

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

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

try {
  fs.writeFileSync('c:\\demo\a.txt', new Date());
} catch (error) {
  // 文件夾不存在,或者權限錯誤
  console.log(error);
}

fs.createWriteStream(path[,option])

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

文件寫入

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

// 相比較之前文件流的方式,這種方式不會占用文件資源,append完成就會釋放
setInterval(() => {
  fs.appendFile('c:\\demo\a.txt',`${new Date}\n`, (error) => {
    console.log(error);
  });
}, 1000);

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

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

其他常見文件操作

驗證路徑是否存在(過時的API)

  • 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);
});

緩沖區處理

什么是緩沖區

  • 緩沖區就是內存中操作數據的容器
  • 只是數據容器而已
  • 通過緩沖區可以很方便的操作二進制數據
  • 而且在大文件操作時必須有緩沖區

為什么要有緩沖區

  • JavaScript是比較擅長處理字符串,但是早期的應用場景主要用於處理HTML文檔,不會有太大篇幅的數據處理,也不會接觸到二進制的數據。
  • 而在Node中操作數據、網絡通信是沒辦法完全以字符串的方式操作的,簡單來說
  • 所以在Node中引入了一個二進制的緩沖區的實現:Buffer

原文鏈接:http://blog.wedn.net/node-essential-file-system/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM