NodeJS学习之文件操作
NodeJS -- 文件操作
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>
Buffer与字符串一个重要区别:字符串是只读的,并且对字符串的任何修改得到的都是一个新字符串,原字符串保持不变。至于Buffer,更像是可以做指针操作的C语言数组。例可以使用[index]方式直接修改某个位置的字节:
bin[0] = 0x48;
而.slice方法也不是返回一个新的Buffer,而更像是反回了指向原Buffer中间某个位置的指针:

因此对.slice方法返回的Buffer的修改会作用于原Buffer。
Stream(数据流)
var rs = fs.createReadStream(pathName);
rs.on('data', function(chunk) {
doSomething(chunk);
});
rs.on('end', function() {
cleanUp();
});
注:Stream基于事件机制工作,所有Stream实例都继承于NodeJS提供的EventEmitter
上边的代码中data事件会源源不断地被触发,不管doSomething()函数是否处理得过来。代码可以继续作如下改造,以解决这个问题:
var rs = fs.createReadStream(src);
rs.on('data', function(chunk) {
rs.pause();
doSomething(chunk, function() {
rs.resume();
});
});
rs.on('end', function() {
cleanUp();
});
var rs = fs.createReadStream(src);
var ws = fs.createWriteStream(dst); rs.on('data', function(chunk) {
ws.write(chunk);
}); rs.on('end', function(chunk) {
ws.end():
});
以上代码看起来就像是一个文件拷贝程序了,不过,依然存在写入速度跟不上读取速度,会导致缓存爆仓的问题,我们可以根据.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();
}); rs.on('drain', function() {
rs.resume();
});
实现了数据从只读数据流到只写数据流的搬运,并包括了放爆仓控制,NodeJS直接提供了.pipe方法来做这件事,内部实现方式与上述代码类似
File System(文件系统)
fs.readFile(pathName, function(err, data) {
if(err) {
// Deal with error.
} else {
// Deal with data
}
});
Path(路径)
操作文件时难免与文件路径打交道,NodeJS提供了path内置模块来简化路径相关操作,并提升代码可读性。
path.normalize
将传入的路径转换为标准路径,具体讲的话,除了解析路径中的.与..之外,还能去掉多余的斜杠,如果程序需要使用路径作为某些数据的索引,但有允许用户随意输入路径时,就需要使用该方法保证路径的唯一性,例:
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}
注意:标准化之后的路径里的斜杠在Window系统下是\,而在linux系统下是/,若想保证任何系统都使用/作为路径分隔符的话,需要.replace(/\\/g, '/')再替换下标准路径
path.join
将传入的多个路径拼接为标准路径,该方法可避免手工拼接字符串的繁琐,并且能在不同系统下正确使用相应路径分隔符。例:
path.join('foo/', 'baz/', '../bar'); // => "foo/bar"
path.extname
可获取文件的扩展名,当我们需要根据不同文件扩展名做不同操作时,该方法就显得很好用,例:
path.extname('foo/bar.js'); // => ".js"
遍历目录
文本编码
常用的文本编码有UTF8和GBK两种,并且UTF8还可能带有BOM,在读取不同编码的文本文件时,需要将文件内容转换为JS使用的UTF8编码字符串后才能正常处理
BOM的移除
BOM用于标记一个文件使用Unicode编码,其本身是一个Unicode字符(“\uFEFF”),位于文本文件头部,在不同Unicode编码下,BOM字符对应的二进制字节如下:

因此我们可以根据文本文件头几个字节等于啥来判断文件是否包含BOM,以及使用哪种Unicode编码,但BOM并不属于文件的一部分,需要去掉,否则在某些应用场景下会有问题。以下代码实现了识别和去除UTF8 BOM的功能
function readText(pathName) {
var bin = fs.readFileSync(pathName);
if(bin[0] === 0xEF && bin[1] === 0xBB && bin[2] === 0xBF) {
bin = bin.slice(3);
}
return bin.toString('utf-8');
}
NodeJS学习之文件操作的更多相关文章
- HTML5学习之文件操作(九)
之前我们操作本地文件都是使用flash.silverlight或者第三方的activeX插件等技术,由于使用了这些技术后就很进行跨平台的处理,另外就是让我们的web应用依赖了第三方的插件,而不是很独立 ...
- python学习笔记:文件操作和集合(转)
转自:http://www.nnzhp.cn/article/16/ 这篇博客来说一下python对文件的操作. 对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句 ...
- python学习总结---文件操作
# 文件操作 ### 目录管理(os) - 示例 ```python # 执行系统命令 # 清屏 # os.system('cls') # 调出计算器 # os.system('calc') # 查看 ...
- erlang学习笔记(文件操作)
参考这里和这里了解到的文件操作的模块有很多:kernel下有:file,stdlib下有:filelib,filename,file_sorter.(具体查看官方文档)
- Smart210学习记录-------文件操作
一.linux文件操作(只能在linux系统上用) 创建:int creat(const char* filename, mode_t mode) filename 表示要创建的文件名,mode表示对 ...
- python学习day8 文件操作(深度学习)
文件操作 (day7内容扩展) 1 文件基本操作 obj = open('路径',mode='模式',encoding='编码')obj.write()obj.read()obj.close() 2 ...
- python学习日记(文件操作)
文件操作概述 计算机系统分为:操作系统,计算机硬件,应用程序. 我们用python或其他语言编写的应用程序若想要把数据永久保存下来,必须要保存于硬盘中,这就涉及到应用程序要操作硬件,众所周知,应用程序 ...
- nodejs笔记之文件操作
文件操作包含: 读取文件 写入文件 删除文件 创建目录 删除目录 读取文件: // 异步操作 var fs = require("fs"); fs.readFile(". ...
- python 学习分享-文件操作篇
文件操作 f_open=open('*.txt','r')#以只读的方式(r)打开*.txt文件(需要与py文件在同一目录下,如果不同目录,需写全路径) f_open.close()#关闭文件 打开文 ...
随机推荐
- (剑指Offer)面试题36:数组中的逆序对
题目: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路: 1.顺序扫描 顺序扫描整个数组,每扫描到一个数字,就将该数 ...
- cocos2d-x 2.2 资源更新AssetsManager例子代码
转自:http://www.58player.com/blog-2327-601.html // // UpgradeLayer.h // AmazeDemo // // Created by lsw ...
- C++之类型转换
说明:本文仅供学习交流,转载请标明出处,欢迎转载! 实现将A类的对象转换为B类对象的方法有3种:(A类对象<-------B类对象) 方法一:如果A为基类,B为派生类,能够将派生类的对象转 ...
- 百度语音识别REST API——通过使用Http网络请求方式获得语音识别功能
百度语音识别通过REST API的方式给开发人员提供一个通用的HTTP接口,基于该接口,开发人员能够轻松的获取语音识别能力,本文档描写叙述了使用语音识别服务REST API的方法. 长处: 较之开发人 ...
- javascript优化
javaScript是一门解释性的语言.它不像java.C#等程序设计语言.由编译器先进行编译再运行.而是直接下载到用户的客户端进行执行.因此代码本身的优劣就直接决定了代码下载的速度以及执行的效率. ...
- Looksery Cup 2015 A. Face Detection 水题
A. Face Detection Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/549/pro ...
- SQL Server数据库大型应用解决方案总结
随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的互联网应用,每天百万级甚至上亿的PV无疑对数据库造成了相当高的负载.对于系统的稳定性和扩展性造成了极大的问题. 一 ...
- 分享 Java微信开发SDK
分享 Java微信开发SDK •发布于 4周前 •作者 朋也 •432 次浏览 •最后一次编辑是 2周前 •来自 分享 给大家分享两个java开发微信公众号的sdk jfinal-weixin ...
- 定时导出Oracle数据表到文本文件的方法
该实例实现了通过windows定时任务来实现了将数据库中指定数据表数据导出为txt文本格式.其思路是通过可执行的bat文件去调用导出数据脚本,然后再在windows定时任务中调用该bat文件来实现.该 ...
- SVM多分类
http://www.matlabsky.com/thread-9471-1-1.htmlSVM算法最初是为二值分类问题设计的,当处理多类问题时,就需要构造合适的多类分类器.目前,构造SVM多类分类器 ...