node.js整理 02文件操作-常用API
NodeJS不仅能做网络编程,而且能够操作文件。
拷贝
小文件拷贝
var fs = require('fs');
function copy(src, dst) {
fs.writeFileSync(dst, fs.readFileSync(src));
}
function main(path) {
copy(path[0], path[1]);
}
main(process.argv.slice(2));
process
是一个全局变量,可通过process.argv
获得命令行参数。argv[0]
固定等于NodeJS执行程序的绝对路径,argv[1]
固定等于主模块的绝对路径,因此第一个命令行参数从argv[2]
这个位置开始。- 使用
fs.readFileSync
从源路径读取文件内容,并使用fs.writeFileSync
将文件内容写入目标路径;
大文件拷贝
- 这种一次性把所有文件内容都读取到内存中后再一次性写入磁盘的方式不适合拷贝大文件,内存会爆仓。
- 对于大文件,只能读一点写一点,直到完成拷贝。
var fs = require('fs');
function copy(src, dst) {
fs.createReadStream(src).pipe(fs.createWriteStream(dst));
}
function main(path) {
copy(path[0], path[1]);
}
main(process.argv.slice(2));
fs.createReadStream
创建了一个源文件的只读数据流,并使用fs.createWriteStream
创建了一个目标文件的只写数据流- 用
pipe
方法把两个数据流连接了起来。
常用API
Buffer(数据块)
- JS语言自身只有字符串数据类型,没有二进制数据类型,因此NodeJS提供了一个与String对等的全局构造函数Buffer来提供对二进制数据的操作。
- 除了可以读取文件得到Buffer的实例外,还能够直接构造:
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
Buffer
与字符串类似,除了可以用.length
属性得到字节长度外,还可以用[index]
方式读取指定位置的字节:
bin[0]; // => 0x68;
Buffer
与字符串能够互相转化, 可以使用指定编码将二进制数据转化为字符串:
var str = bin.toString('utf-8'); // => "hello"
- 或者反过来,将字符串转换为指定编码下的二进制数据:
var bin = new Buffer('hello', 'utf-8'); // => <Buffer 68 65 6c 6c 6f>
Buffe
r与字符串有一个重要区别- 字符串是只读的,并且对字符串的任何修改得到的都是一个新字符串,原字符串保持不变。
Buffer
更像是可以做指针操作的C语言数组。例如,可以用[index]
方式直接修改某个位置的字节。bin[0] = 0x48;
- 而
.slice
方法也不是返回一个新的Buffer,而更像是返回了指向原Buffer中间的某个位置的指针
[ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]
^ ^
| |
bin bin.slice(2)
- 因此对
.slice
方法返回的Buffer
的修改会作用于原Buffer
- 因此对
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
var sub = bin.slice(2);
sub[0] = 0x65;
console.log(bin); // => <Buffer 68 65 65 6c 6f>
- 如果想要拷贝一份
Buffer
,得首先创建一个新的Buffer
,并通过.copy
方法把原Buffer中
的数据复制过去。这个类似于申请一块新的内存,并把已有内存中的数据复制过去
- 如果想要拷贝一份
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
var dup = new Buffer(bin.length);
bin.copy(dup);
dup[0] = 0x48;
console.log(bin); // => <Buffer 68 65 6c 6c 6f>
console.log(dup); // => <Buffer 48 65 65 6c 6f>
Stream(数据流)
- 当内存中无法一次装下需要处理的数据时,或者一边读取一边处理更加高效时,就需要用到数据流。
- NodeJS中通过各种
Stream
来提供对数据流的操作。 Stream
基于事件机制工作,所有Stream
的实例都继承于NodeJS提供的EventEmitter。- 以大文件拷贝程序为例, 为数据来源创建一个只读数据流,
copy
函数中
var rs = fs.createReadStream(pathname);
rs.on('data', function (chunk) {
doSomething(chunk);
});
rs.on('end', function () {
cleanUp();
});
- 上边的代码中data事件会源源不断地被触发,不管doSomething函数是否处理得过来。代码可以继续做如下改造,
var rs = fs.createReadStream(src);
rs.on('data', function (chunk) {
rs.pause();
doSomething(chunk, function () {
rs.resume();
});
});
rs.on('end', function () {
cleanUp();
});
给doSomething函数加上了回调,因此可以在处理数据前暂停数据读取,并在处理数据后继续读取数据。
可以为数据目标创建一个只写数据流
var rs = fs.createReadStream(src);
var ws = fs.createWriteStream(dst);
rs.on('data', function (chunk) {
ws.write(chunk);
});
rs.on('end', function () {
ws.end();
});
- 把doSomething换成了往只写数据流里写入数据后,以上代码看起来就像是一个文件拷贝程序了。
- 但是如果写入速度跟不上读取速度的话,只写数据流内部的缓存会爆仓;可以根据
.write
方法的返回值来判断传入的数据是写入目标了,还是临时放在了缓存了,并根据drain
事件来判断什么时候只写数据流已经将缓存中的数据写入目标,可以传入下一个待写数据了。
var rs = fs.createReadStream(src);
var ws = fs.createWriteStream(dst);
rs.on('data', function (chunk) {
if (ws.write(chunk) === false) {
rs.pause();
}
});
rs.on('end', function () {
ws.end();
});
ws.on('drain', function () {
rs.resume();
});
File System(文件系统)
NodeJS通过
fs
内置模块提供对文件的操作。fs
模块提供的API基本上可以分为以下三类:文件属性读写: 常用的有
fs.stat
、fs.chmod
、fs.chown
等等。文件内容读写: 常用的有
fs.readFile
、fs.readdir
、fs.writeFile
、fs.mkdir
等等。底层文件操作: 常用的有
fs.open
、fs.read
、fs.write
、fs.close
等等。
NodeJS最精华的异步IO模型在fs模块里有着充分的体现, 以fs.readFile为例:
fs.readFile(pathname, function (err, data) {
if (err) {
// Deal with error.
} else {
// Deal with data.
}
});
//基本上所有fs模块API的回调参数都有两个。第一个参数在有错误发生时等于异常对象,第二个参数始终用于返回API方法执行结果。
- fs模块的所有异步API都有对应的同步版本; 同步API除了方法名的末尾多了一个Sync之外,异常对象与执行结果的传递方式也有相应变化。同样以fs.readFileSync为例:
try {
var data = fs.readFileSync(pathname);
// Deal with data.
} catch (err) {
// Deal with error.
}
Path(路径)
NodeJS提供了path内置模块来简化路径相关操作,并提升代码可读性。
path.normalize
: 将传入的路径转换为标准路径;除了解析路径中的.与..外,还能去掉多余的斜杠。如果有程序需要使用路径作为某些数据的索引,但又允许用户随意输入路径时,就需要使用该方法保证路径的唯一性。
var path = require('path');
var cache = {};
function store(key, value) {
cache[path.normalize(key)] = value;
}
store('foo/bar', 1);
store('foo//baz//../bar', 2);
console.log(cache); // => { "foo/bar": 2 }
// 标准化之后的路径里的斜杠在Windows系统下是\,而在Linux系统下是/。如果想保证任何系统下都使用/作为路径分隔符的话,需要用.replace(/\\/g, '/')再替换一下标准路径。
path.join
: 将传入的多个路径拼接为标准路径。
path.join('foo/', 'baz/', '../bar'); // => "foo/bar"
path.extname
: 需要根据不同文件扩展名做不同操作时
path.extname('foo/bar.js'); // => ".js"
node.js整理 02文件操作-常用API的更多相关文章
- node.js整理 03文件操作-遍历目录和文本编码
遍历目录 递归算法 遍历目录时一般使用递归算法,否则就难以编写出简洁的代码. 递归算法与数学归纳法类似,通过不断缩小问题的规模来解决问题 function factorial(n) { if (n = ...
- node.js整理 04网络操作
简介 var http = require('http'); http.createServer(function (req, res) { res.writeHead(200, {'Content- ...
- php中文件操作常用函数有哪些
php中文件操作常用函数有哪些 一.总结 一句话总结:读写文件函数 判断文件或者目录是否存在函数 创建目录函数 file_exists() mkdir() file_get_content() fil ...
- 使用Node.JS监听文件夹变化
使用Node.JS监听文件夹改变有许多应用场合,比如: 构建自动编绎工具 当源文件改变时,自动运行build过程,比如当你写CoffeeScript文件或SASS CSS文件时,保存之后可即时生成对应 ...
- C#文件操作常用相关类(Directory类、File类、Path类)
1.文件操作常用相关类 1)File //操作文件,静态类,对文件整体操作.拷贝.删除.剪切等 2)Directory //操作目录(文件夹),静态类 3)DirectoryInfo //文件夹的一个 ...
- node.js编译less文件
大多数文章对于到底怎样编译less文件并没有一个详细的说明,清一色的grunt命令,看得也是晕晕的,所以也就有了这篇手记的存在. 步入正题 1.安装配置好sublime text3(包括各种实用插件) ...
- Linux文件操作常用命令整理
收集.整理日常系统管理或维护当中的,常用到的一些关于文件操作的命令或需求,后续会慢慢补充.完善! 查看.生成指定目录的目录树结构? [root@DB-Server ~]#tree #当前目录 ...
- node.js整理 05进程管理
简介 NodeJS可以感知和控制自身进程的运行环境和状态,也可以创建子进程并与其协同工作,这使得NodeJS可以把多个程序组合在一起共同完成某项工作,并在其中充当胶水和调度器的作用 常用API Pro ...
- node 学习笔记 - fs 文件操作
本文同步自我的个人博客:http://www.52cik.com/2015/12/03/learn-node-fs.html 最近看到群里不少大神都开始玩 node 了,我感觉跟他们步伐越来越大了, ...
随机推荐
- jquery中使用event.target的几点
jquery中使用event.target的几点 1.this和event.target的区别: js中事件是会冒泡的,所以this是可以变化的,但event.target不会变化,它永远是直接接受事 ...
- LeetCode 231 Power of Two
Problem: Given an integer, write a function to determine if it is a power of two. Summary: 判断一个数n是不是 ...
- codeforces gym 100286 H - Hell on the Markets (贪心算法)
题目链接 题意:n个数分别为a[i],问是否存在一组对应的b[i],b[i]=1 || b[i]=-1,使得ai*bi的n项和为0. 题解: 先证明一个结论吧,对于1≤ai≤i+1,前面ai个数一定可 ...
- iOS-运行时机制
这里的两篇运行时的文章感觉还不错. 收藏: 初识iOS运行时RunTime | // TODO: http://www.saitjr.com/ios/objc-runtime.html Objecti ...
- 解决java.lang.SecurityException: Access to default session denied
原先使用的代码如下: Session session = Session.getDefaultInstance(properties, null); 后来把代码修改为: Session session ...
- 无根树转有根树(dfs,tree)
#include <bits/stdc++.h> #include <iostream> #include <queue> #include <stdio.h ...
- Loadrunner之API测试
//API函数 web_submit_data web_custom_request //支持https请求 web_set_sockets_option("SSL_VERSION&qu ...
- Lattice 的 DDR IP核使用调试笔记之工程建立
DDR3的IP核的使用相当重要,尤其是对视频处理方面. 下面接收DDR3 的IP 核的生成步骤. 1. 选择DDR IP核的生成路径.名字以及哪种语言之后就可以设置DDR IP 的参数了. 2.选择存 ...
- EF – 5.DbSet与DbContext,数据更新奥秘
5.6.4 <DbSet与DbContext> 介绍DbSet与DbContext中的核心属性及重要方法. 5.6.5 <数据更新的奥秘> 这一讲极为重要,因为它揭示出了En ...
- Linux下Vi/Vim使用笔记
启动和关闭vim vi 打开 Vi/Vim 打开 Vi/Vim 并加载文件 <file> vi <file> vim编辑器的三种模式:一般模式.编辑模式和命令行模式在一般模式中 ...