前言

  node中有一组流api,它们可以像处理网络流一样处理文件。流api用起来非常方便,本节学习介绍文件处理基础和流的概念。

目录

  1. 处理文件路径
  2. fs核心模块简介
  3. 操作流
  4. 慢客户端问题

1. 处理文件路径

  处理文件路径需要用到一个核心模块(path),path模块可以规范化、连接、解析路径,还可以将绝对路径转换为相对路径,提取路径的组成以及判断路径是否存在。

1.1. 规范化路径

在存储和使用路径前最好能够将其进行规范化,这里使用path模块的normalize()函数

 //规范化路径
var path=require('path');
path.normalize('/pathstudy//path1')
// =>'/pathstudy/path1'
1.2. 连接路径

通过path.join()函数可以连接多个路径字符串,如下所示:

 //连接路径
var path=require('path');
path.join('/pathstudy','path1','test');
// => '/pathstudy/path1/test'
1.3. 解析路径

使用path.resolve()函数将多个路径解析为一个规范化的路径

 //解析路径
var path=require('path');
path.resolve('/foo/bar','./dd');
// =>/foo/bar/dd
1.4. 提取路径的组成部分
 //提取路径组成部分
var path=require('path');
path.dirname('/foo/bar/dd/a1.txt');//获取文件路径的目录 => /foo/bar/dd
path.basename('/foo/bar/dd/a1.txt');//获取文件名 => a1.txt
path.basename('/foo/bar/dd/a1.txt','.txt');//获取不包含文件类型的文件名 => a1
path.extname('/foo/bar/dd/a1.txt','.txt');//获取文件扩展类型 =>.txt
1.5. 判断路径是否存在

使用path.exists()函数判断路径是否存在,0.8版本以后使用fs.exists()函数代替,只需将导入模块替换为fs即可。

 //判断路径是否存在
var path=require('path');
path.exists('/foo/bar/dd',function(exists){
console.log('是否存在:',exists);
})

2. fs模块简介

fs核心模块内置查询文件信息和打开/读写/关闭文件操作

查询文件信息

使用fs.stat()函数查询文件特征,例如大小、创建时间、权限等

//查询文件信息
var fs=require('fs');
fs.stat('/foo/bar/dd',function(stats){
console.log(stats);//打印出文件信息
stats.isFile();//判断是否文件
stats.isDirectory();//判断是否目录
stats.isSocket();//判断是否UNIX套接字
//...
});
打开/读写/关闭文件
 var fs=require('fs');
//打开文件,‘r’表示模式类型
fs.open('/foo/bar/dd/a1.txt','r',function(err,fd){
//获取文件描述符 fd
}); //读取文件
fs.open('/foo/bar/dd/a1.txt','r',function(err,fd){
if(err){
throw err;
}
var readbuffer=new Buffer(1024),//设置缓冲区
bufferOffset=0,
filePosition=100,//从100字节开始
bufferLength=readbuffer.length;//读取随后的1024字节数据;
fs.read(fd,readbuffer,bufferOffset,bufferLength,filePosition,
function (err, readBytes){
if(err){
throw err;
}
if(readBytes>0){
console.log(readbuffer.slice(0,readBytes));//获取读入缓冲区的字节数
}
});
}); //写入文件
fs.open('/foo/bar/dd/a1.txt','a',function(err,fd){
if(err){
throw err;
}
var writebuffer=new Buffer('准备写入缓冲区的数据'),//设置缓冲区
bufferPosition=0,//写入起始位置
filePosition=null,//从文件什么位置开始写
bufferLength=readbuffer.length;//长度
fs.write(fd,writebuffer,bufferPosition,bufferLength,filePosition,
function (err, write){
if(err){
throw err;
}
console.log('write bytes:',write);//获取读入缓冲区的字节数
});
}); //关闭文件
fs.open('/foo/bar/dd/a1.txt','a',function(err,fd){
if(err){
throw err;
}
//write...
//close
fs.close(fd,function(){
//...
})
});

文件模式类型:

r——数据流的位置从起始处打开文件读取

r+——数据流的位置从起始处打开文件读写

w——如果文件存在则清零,不存在则创建文件并写入数据,数据流的位置从文件起始处

w+——打开文件进行读写,如果文件存在则清零,不存在则创建文件并写入数据,数据流的位置从文件起始处

a——打开文件写入数据,如果文件存在则清零,不存在则创建文件,数据流的位置从文件结尾处,写操作都将追加到文件后面

a+——打开文件读写数据,如果文件存在则清零,不存在则创建文件,数据流的位置从文件结尾处,写操作都将追加到文件后面

需要注意,在读写文件操作回调函数执行之后,不要使用提供的缓冲区,不然可能会导致读写数据不完整。

3. 操作流

流是由几个node对象实现的抽象概念,创建或读取流的方式取决于使用流的类型,流的特性包含可读流可写流,通过监听data事件,在流每次提交数据时,都能够得到通知。

3.1. 创建文件系统流
 var fs=require('fs');
//根据文件路径创建一个可读流
fs.createReadStream('/foo/bar/file'); fs.open('/foo/bar/file','r',function(err,fd){
fs.createReadStream(null,{fd:fd,encoding:'utf8'});
fs.on('data',function(data){
console.log('data:',data);
});
}); //创建可写流
fs.createWriteStream('/foo/bar/file'); fs.createWriteStream('/foo/bar/file',option);
//option表示第二个参数,默认值为{flags:'w',encoding:null,mode:0666}

可以指定createReadStream和createWriteStream函数的第二个参数,用来设置文件的起始结束位置、编码格式等等,参数选项如下所示:

  • encoding——data事件发送的编码格式
  • fd——如果已经有一个打开文件描述符则可以传入该参数选项
  • bufferSize——要被读取的每个文件块大小,单位是字节,默认64kb
  • start——设置文件中第一个被读取的字节位置,用来限制读取数据范围
  • end——与start相反
  • flags——表示用于打开文件的模式类型
  • mode——指定要打开文件的权限

4. 慢客户端问题

当客户端的网络连接速度较慢时,可写流也就慢速,可读流会快速产生data事件并监听,数据被发送到可写流,导致node不得不缓存数据导致缓冲区被快速填满。

一般情况可以通过暂停数据生产者来避免这个问题:

 var http=require('http');
var fs=require('fs');
http.createServer(function(req,res){
var rs= fs.createReadStream('/foo/bar/file'); rs.on('data',function(data){
if(!res.write(data)){
rs.pause();//暂停可读流
}
}); rs.on('drain',function(){
rs.resume();//恢复可读流
}); rs.on('end',function(){
res.end();//结束操作
}); }).listen('8080');

扩展:使用pipe函数操作上述暂停/恢复操作

 var http=require('http');
var fs=require('fs');
http.createServer(function(req,res){
var rs= fs.createReadStream('/foo/bar/file');
rs.pipe(res);//由传输源调用并接受目标可写流作为参数
}).listen('8080'); http.createServer(function(req,res){
var rs= fs.createReadStream('/foo/bar/file');
//默认情况下end()在可读流结束时在可写流上被调用,设置第二个参数end选项为false表示不让pipe函数进行end操作
rs.pipe(res,{end:false}); rs.on('end',function(){
res.write('endend~~');
res.end();//结束操作
});
}).listen('8080');

总结

对于流我表示比较懵逼,对概念理解的还不是很透彻。。

nodejs操作文件和数据流的更多相关文章

  1. nodejs操作文件

    var fs = require('fs'); var txt = "以上程序使用fs.readFileSync从源路径读取文件内容,并使用fs.writeFileSync将文件内容写入目标 ...

  2. nodejs遍历文件夹下并操作HTML/CSS/JS/PNG/JPG

    需求描述,由于工作的需要,需要将原本用于1280 720的网页改为1920 1080的网页(电视端页面).需求可以拆分为两部分,代码部分的修改以及图片的修改.在代码部分,需要将所有位置以及大小相关的值 ...

  3. nodejs操作mongodb

    一.下载地址 https://www.mongodb.com/download-center#community 二.控制台操作mongodb 1.安装完后添加环境变量. 2.在某个根目录下新建dat ...

  4. C#操作文件夹及文件的方法的使用

    本文收集了目前最为常用的C#经典操作文件的方法,具体内容如下:C#追加.拷贝.删除.移动文件.创建目录.递归删除文件夹及文件.指定文件夹下面的所有内容copy到目标文件夹下面.指定文件夹下面的所有内容 ...

  5. NodeJs之文件上传

    NodeJs之文件上传 一,介绍与需求 1.1,介绍 1,multer模块 multer用于处理文件上传的nodejs中间件,主要跟express框架搭配使用,只支持表单MIME编码为multipar ...

  6. 初入 nodejs -遍历文件夹

    //操作文件 /* 1.fs.stat 获取文件状态 2.fs.readdir 读取文件夹数据 3.fs.access 判断文件夹是否存在 4.path.join 拼路径 */ //操作文件 cons ...

  7. NodeJS静态文件访问性能测试

    受益于JavaScript语言优秀特点,使NodeJS开发服务端应用很方便,配合NPM官方提供的大量第三方组件,让NodeJS更加如虎添翼.最近,需要使用NodeJS做一个服务端HTML5的游戏服务器 ...

  8. MongoDB入门 和nodejs操作

    简介 MongoDB 开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序:高伸缩性: NoSQL毕竟还处于发展阶段,也有说它的各种问题的:http://coolshel ...

  9. nodejs操作excel并配合edatagrid使用

    nodejs读取文件夹下子文件(夹)名称: /** * 查询tmp文件夹下子文件夹名称 */ router.post("/tmpList", function (req, res) ...

随机推荐

  1. dll签名两种方法

    以下两种签名方法,都是对csp.dll签名,都不是CA颁发的,且效果不同, 一:通过自建证书签名 下载windows sdk,成功安装后,包括makecert.exe, cert2spc.exe, p ...

  2. hadoop-03-安装java

    hadoop-03-安装java 1,su root 2, rpm -qa|grep jdk #查看已经安装的jdk 3,rpm -e --nodeps `rpm -qa|grep jdk ` #删除 ...

  3. (数据结构整理)NJUPT1054

    这一篇博客以一些OJ上的题目为载体,整理一下数据结构.会陆续的更新. .. 我们都知道,数据结构的灵活应用有时能让简化一些题目的解答. 一.栈的应用 1.NJUPT OJ 1054(回文串的推断) 回 ...

  4. excle查找操作-vlookup的使用心得

    百度了一下vlookup的语法规则: 该函数的语法规则例如以下: VLOOKUP(lookup_value,table_array,col_index_num,range_lookup) 參数 简单说 ...

  5. JNI 资源释放

    JNI 编程实现了 native code 和 Java 程序的交互,因此 JNI 代码编程既遵循 native code 编程语言的编程规则,同时也遵守 JNI 编程的文档规范.在内存管理方面,na ...

  6. 4.C语言文件操作

    总论 1.fopen r以只读方式打开文件,该文件必须存在 r+以可读写方式打开文件,文件必须存在 rb+读写打开一个二进制文件,允许读写数据,文件必须存在 rw+读写打开一个文本文件,允许读和写 w ...

  7. P3227 [HNOI2013]切糕

    题目描述 经过千辛万苦小 A 得到了一块切糕,切糕的形状是长方体,小 A 打算拦腰将切糕切成两半分给小 B.出于美观考虑,小 A 希望切面能尽量光滑且和谐.于是她找到你,希望你能帮她找出最好的切割方案 ...

  8. CentOS7下安装二进制MYSQL8

    早看到MySQL8发布, 性能相比MySQL7提升2倍,今天准备安装下试试看 1.先卸载当前系统中已安装的mariadb rpm -qa | grep mariadb rpm -e mysql*/ma ...

  9. TPC-C测试

    TPC发布的测试标准之一,是专门针对联机事务处理系统(OLTP)的测试标准.1992年发布1.0版本.最新版本5.11,2010年发布. 测试规范中模拟了一个比较复杂并具有代表意义的OLTP应用环境, ...

  10. <Sicily>Brackets Matching

    一.题目描述 Let us define a regular brackets sequence in the following way: Empty sequence is a regular s ...