NodeJS笔记: 文件操作大全
为什么80%的码农都做不了架构师?>>>
文件I/O fs模块的基本用法
开发中我们经常会有文件I/O的需求,node.js中提供一个名为fs的模块来支持I/O操作,fs模块的文件I/O是对标准POSIX函数的简单封装。
writeFile函数的基本用法
文件I/O,写入是必修课之一。fs模块提供writeFile函数,可以异步的将数据写入一个文件, 如果文件已经存在则会被替换。用法如下:
例:fs.writeFile(filename, data, callback)
var fs= require("fs");fs.writeFile('test.txt', 'Hello Node', function (err) {if (err) throw err;console.log('Saved successfully'); //文件被保存
});
appendFile函数的基本用法
writeFile函数虽然可以写入文件,但是如果文件已经存在,我们只是想添加一部分内容,它就不能满足我们的需求了,很幸运,fs模块中还有appendFile函数,它可以将新的内容追加到已有的文件中,如果文件不存在,则会创建一个新的文件。使用方法如下:
例:fs.appendFile(文件名,数据,编码,回调函数(err));
var fs= require("fs");fs.appendFile('test.txt', 'data to append', function (err) {if (err) throw err;//数据被添加到文件的尾部console.log('The "data to append" was appended to file!');
});
编码格式默认为"utf8"
exists函数的基本用法
如何检查一个文件是否存在呢?我想exists函数可以帮助你,用法如下:
例:fs.exists(文件,回调函数(exists));
exists的回调函数只有一个参数,类型为布尔型,通过它来表示文件是否存在。
var fs= require("fs");fs.exists('/etc/passwd', function (exists) {console.log(exists ? "存在" : "不存在!");
});
rename函数的基本用法
修改文件名称是我们经常会遇见的事情,rename函数提供修改名称服务:
var fs= require("fs");
fs.rename(旧文件,新文件,回调函数(err)){if (err) throw err;console.log('Successful modification,');
});
移动文件也是我们经常会遇见的,可是fs没有专门移动文件的函数,但是我们可以通过rename函数来达到移动文件的目的,示例如下。
var fs = require('fs');fs.rename(oldPath,newPath,function (err) {if (err) throw err;console.log('renamed complete');
});
readFile函数的基本用法
读取文件是最常用到的功能之一,使用fs模块读取文件语法如下: 例:fs.readFile(文件,编码,回调函数)
;
var fs = require('fs');fs.readFile(文件名, function (err, data) {if (err) throw err;console.log(data);
});
回调函数里面的data,就是读取的文件内容。
unlink函数的基本用法
面对一堆垃圾的文件总是有想删除的冲动,我有强迫症?你才有呢。 好在有unlink函数,终于得救了,示例如下:
例:fs.unlink(文件,回调函数(err))
;
var fs = require('fs');fs.unlink(文件, function(err) {if (err) throw err;console.log('successfully deleted');
});
mkdir函数的基本用法
除了针对文件的操作,目录的创建、删除也经常遇到的,下面我们来看看node.js中如何创建目录:
fs.mkdir(路径,权限,回调函数(err))
;
参数
路径:新创建的目录。
权限:可选参数,只在linux下有效,表示目录的权限,默认为0777,表示文件所有者、文件所有者所在的组的*用户、*所有用户,都有权限进行读、写、执行的操作。
回调函数:当发生错误时,错误信息会传递给回调函数的err参数。
rmdir函数的基本用法
删除目录也是必不可少的功能,rmdir函数可以删除指定的目录:
例:fs.rmdir(路径,回调函数(err));
var fs = require('fs');fs.rmdir(path, function(err) {if (err) throw err;console.log('ok');
});
文件拷贝
小文件拷贝
var fs = require('fs');function copy(src, dst) {fs.writeFileSync(dst, fs.readFileSync(src));
}function main(argv) {copy(argv[0], argv[1]);
}main(process.argv.slice(2));
以上程序使用 fs.readFileSync 从源路径读取文件内容,并使用 fs.writeFileSync 将文件内容写入目标路径。
豆知识: process 是一个全局变量,可通过 process.argv
获得命令行参数。由于 argv[0]
固定等于 NodeJS 执行程序的绝对路径,argv[1]
固定等于主模块的绝对路径,因此第一个命令行参数从 argv[2]
这个位置开始。
大文件拷贝
上边的程序拷贝一些小文件没啥问题,但这种一次性把所有文件内容都读取到内存中后再一次性写入磁盘的方式不适合拷贝大文件,内存会爆仓。对于大文件,我们只能读一点写一点,直到完成拷贝。因此上边的程序需要改造如下。
ar fs = require('fs');function copy(src, dst) {fs.createReadStream(src).pipe(fs.createWriteStream(dst));
}function main(argv) {copy(argv[0], argv[1]);
}main(process.argv.slice(2));
以上程序使用 fs.createReadStream 创建了一个源文件的只读数据流,并使用 fs.createWriteStream 创建了一个目标文件的只写数据流,并且用 pipe 方法把两个数据流连接了起来。连接起来后发生的事情,说得抽象点的话,水顺着水管从一个桶流到了另一个桶。
遍历目录
遍历目录是操作文件时的一个常见需求。比如写一个程序,需要找到并处理指定目录下的所有JS文件时,就需要遍历整个目录。
递归算法
遍历目录时一般使用递归算法,否则就难以编写出简洁的代码。递归算法与数学归纳法类似,通过不断缩小问题的规模来解决问题。以下示例说明了这种方法。
function factorial(n) {if (n === 1) {return 1;} else {return n * factorial(n - 1);}
}
上边的函数用于计算 N 的阶乘(N!)。可以看到,当 N 大于 1 时,问题简化为计算 N 乘以 N-1 的阶乘。当 N 等于 1 时,问题达到最小规模,不需要再简化,因此直接返回 1。
陷阱: 使用递归算法编写的代码虽然简洁,但由于每递归一次就产生一次函数调用,在需要优先考虑性能时,需要把递归算法转换为循环算法,以减少函数调用次数。
遍历算法
目录是一个树状结构,在遍历时一般使用深度优先+先序遍历算法。深度优先,意味着到达一个节点后,首先接着遍历子节点而不是邻居节点。先序遍历,意味着首次到达了某节点就算遍历完成,而不是最后一次返回某节点才算数。因此使用这种遍历方式时,下边这棵树的遍历顺序是 A > B > D > E > C > F。
A/ \B C/ \ \
D E F
同步遍历
了解了必要的算法后,我们可以简单地实现以下目录遍历函数。
function travel(dir, callback) {fs.readdirSync(dir).forEach(function (file) {var pathname = path.join(dir, file);if (fs.statSync(pathname).isDirectory()) {travel(pathname, callback);} else {callback(pathname);}});
}
可以看到,该函数以某个目录作为遍历的起点。遇到一个子目录时,就先接着遍历子目录。遇到一个文件时,就把文件的绝对路径传给回调函数。回调函数拿到文件路径后,就可以做各种判断和处理。因此假设有以下目录:
- /home/user/- foo/x.js- bar/y.jsz.css
使用以下代码遍历该目录时,得到的输入如下。
travel('/home/user', function (pathname) {console.log(pathname);
});
/home/user/foo/x.js
/home/user/bar/y.js
/home/user/z.css
异步遍历
如果读取目录或读取文件状态时使用的是异步API,目录遍历函数实现起来会有些复杂,但原理完全相同。travel函数的异步版本如下。
function travel(dir, callback, finish) {fs.readdir(dir, function (err, files) {(function next(i) {if (i < files.length) {var pathname = path.join(dir, files[i]);fs.stat(pathname, function (err, stats) {if (stats.isDirectory()) {travel(pathname, callback, function () {next(i + 1);});} else {callback(pathname, function () {next(i + 1);});}});} else {finish && finish();}}(0));});
}
利用async模块异步递归拷贝文件夹
var async = require("async");
var fs = require("fs");
var path = require("path");
// cursively make dir
function mkdirs(p, mode, f, made) { if (typeof mode === 'function' || mode === undefined) { f = mode; mode = 777 & (~process.umask()); } if (!made) made = null; var cb = f || function () {}; if (typeof mode === 'string') mode = parseInt(mode, 8); p = path.resolve(p); fs.mkdir(p, mode, function (er) { if (!er) { made = made || p; return cb(null, made); } switch (er.code) { case 'ENOENT': mkdirs(path.dirname(p), mode, function (er, made) { if (er) { cb(er, made); } else { mkdirs(p, mode, cb, made); } }); break; // In the case of any other error, just see if there's a dir // there already. If so, then hooray! If not, then something // is borked. default: fs.stat(p, function (er2, stat) { // if the stat fails, then that's super weird. // let the original error be the failure reason. if (er2 || !stat.isDirectory()) { cb(er, made); } else { cb(null, made) }; }); break; } });
}
// single file copy
function copyFile(file, toDir, cb) { async.waterfall([ function (callback) { fs.exists(toDir, function (exists) { if (exists) { callback(null, false); } else { callback(null, true); } }); }, function (need, callback) { if (need) { mkdirs(path.dirname(toDir), callback); } else { callback(null, true); } }, function (p, callback) { var reads = fs.createReadStream(file); var writes = fs.createWriteStream(path.join(path.dirname(toDir), path.basename(file))); reads.pipe(writes); //don't forget close the when all the data are read reads.on("end", function () { writes.end(); callback(null); }); reads.on("error", function (err) { console.log("error occur in reads"); callback(true, err); }); } ], cb); } // cursively count the files that need to be copied function _ccoutTask(from, to, cbw) { async.waterfall([ function (callback) { fs.stat(from, callback); }, function (stats, callback) { if (stats.isFile()) { cbw.addFile(from, to); callback(null, []); } else if (stats.isDirectory()) { fs.readdir(from, callback); } }, function (files, callback) { if (files.length) { for (var i = 0; i < files.length; i++) { _ccoutTask(path.join(from, files[i]), path.join(to, files[i]), cbw.increase()); } } callback(null); } ], cbw); }
// wrap the callback before counting
function ccoutTask(from, to, cb) { var files = []; var count = 1; function wrapper(err) { count--; if (err || count <= 0) { cb(err, files) } } wrapper.increase = function () { count++; return wrapper; } wrapper.addFile = function (file, dir) { files.push({ file : file, dir : dir }); } _ccoutTask(from, to, wrapper);
} function copyDir(from, to, cb) { if(!cb){ cb=function(){}; } async.waterfall([ function (callback) { fs.exists(from, function (exists) { if (exists) { callback(null, true); } else { console.log(from + " not exists"); callback(true); } }); }, function (exists, callback) { fs.stat(from, callback); }, function (stats, callback) { if (stats.isFile()) { // one file copy copyFile(from, to, function (err) { if (err) { // break the waterfall callback(true); } else { callback(null, []); } }); } else if (stats.isDirectory()) { ccoutTask(from, to, callback); } }, function (files, callback) { // prevent reaching to max file open limit async.mapLimit(files, 10, function (f, cb) { copyFile(f.file, f.dir, cb); }, callback); } ], cb);
} var start = new Date().getTime(); var src = "D:\\MyWork\\wepass_wx\\platform\\wpwx\\WebRoot";
var dist = "D:\\servers\\apache-tomcat-8.0.35\\webapps\\wpwx"
copyDir(src, dist, function (err) {if (err) { console.log("error ocur"); console.dir(err); } else { console.log("copy ok"); console.log("consume time:" + (new Date().getTime() - start)) }
});
转载于:https://my.oschina.net/wolfx/blog/713990
NodeJS笔记: 文件操作大全相关推荐
- java中文件,java中文件操作大全
java中文件操作大全 一.获得控制台用户输入的信息 view plaincopy to clipboardprint? / //获得控制台用户输入的信息 return throws ioexcept ...
- 读取Java文件到byte数组的三种方式及Java文件操作大全(包括文件加密,String加密)
读取Java文件到byte数组的三种方式 package zs;import java.io.BufferedInputStream; import java.io.ByteArrayOutputSt ...
- C++Builder文件操作大全
C++Builder文件操作大全 在编程的过程中,文件的操作是一个经常用到的问题,在C++Builder中,可以使用多种方法对文件操作,下面我就按以下几个部分对此作详细介绍,就是: 1.基于C的文件操 ...
- PHP学习笔记-文件操作1
转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/52294237 本文出自:[顾林海的博客] 前言 PHP支持文件上传功能 ...
- 野生葫芦娃用心写的nodejs 内置模块------文件操作
文件操作 Node中的文件系统: 文件具体操作 文件的写入 fs.writeFile() 文件的追加 fs.appendFile() 文件的读取 fs.readFile() 文件的复制 fs.copy ...
- VC 文件操作大全,打开,保存,复制,删除,查找等
各种关于文件的操作在程序设计中十分常见,如果能对这些操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而可以在较短的时间内编写出高效 的代码.本文对Visual C++中有关文件操作进行了全面的 ...
- MFC文件操作大全,打开,保存,复制,删除,查找等
各种关于文件的操作在程序设计中十分常见,如果能对这些操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而可以在较短的时间内编写出高效 的代码.本文对Visual C++中有关文件操作进行了全面的 ...
- Java文件操作大全(绝对的经典,值得收藏!)
Java文件操作 //1.创建文件夹 //import java.io.*; File myFolderPath = new File(str1); try { if (!myFolderPath.e ...
- C、C++文件操作大全
基于C的文件操作 在ANSI C中,对文件的操作分为两种方式,即流式文件操作和I/O文件操作,下面就分别介绍之. 一.流式文件操作 这种方式的文件操作有一个重要的结构FILE,FILE在stdio ...
- Python3文件操作详解 Python3文件操作大全
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 #Author:sking 4 """ 5 test_file.tx ...
最新文章
- early EOF fatal: index-pack failed
- html三列布局中间固定,常见的三列布局(左右固定宽度,中间自适应)
- php 面向对象学习
- cannot import name ‘compare_ssim‘
- mongodb简单的函数
- Ubuntu下载连接(阿里云镜像)
- Some cloud foundry deployment screenshot
- cad页面布局快捷键_炸裂“图纸集”功能、高手都在偷偷用的CAD图纸管理神器
- 请不要叫我“程序员”,我是一名软件工程师--读《走出软件作坊》1
- 将字符串转为16进制数_Python 如何将字符串转为字典
- SQLyog 注册码记录
- 【NLP】cs224n课程笔记
- a标签的href属性 download属性
- 常见的SQL面试题: 经典50题
- 这个macOS神器,让爱怀旧的人直呼:“爷青回!”
- go-kit入门指南
- 51 nod 1010
- 百度贴吧和微博爬虫好用的开源库
- Intel 快速存储蓝屏
- 运营商大数据的作用有哪些