目录
一.fs文件模块
nodejs是服务端的程序,必须要有读写文件的功能,但是原生js中并没有这些功能,在node中我们想要完成这样的功能,就必须使用node中的文件系统(fs)模块,fs模块提供了文件操作的所有功能.
JavaScript在浏览器端是不能进行I/O 操作的,这样做是为了保护客户端的安全,node 的内置模块 fs 模块,能让JavaScript 在执行的时候可以操作服务器上的资源文件,也是就给了JavaScript I/O 操作的能力
1.读取文件
读取文件的方式有同步读取和异步读取.
1.1 异步读取
fs.rendFile(文件路径, 回调函数)
const fs = require('fs');
fs.readFile('./1.txt',function(err,data) {
console.log(arguments)
})
通过打印实参列表我们可以知道:
如果文件读取成功,回调函数会接受两个参数,
第一个实参是报错,值为null , 第二个实参是读取的数据
文件读取成功的时候第一个参数的值是null,转化为布尔值就是 false ,如果文件读取失败,第一个参数值就是一个对象,转化为布尔值就是一个 true.
data 是Buffer数据流,如果需要显示数据通过data.toString
读取文本文件
//创建服务器
const server = http.createServer (function (req,res) {
//设置响应头
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' });
//读取文本文件
fs.readFile('./1.txt',function (err,data) {
//如果文件读取失败,返回错误原因
if(err) {
console.log(err);
return;
}
//文件读取成功,显示数据
res.end(data.toString());
})
})
//监听服务器端口
server.listen(3000);
console.log('server start at 3000');
访问localhost的3000端口就可看到1.txt中的内容已经栽浏览器页面中了.
读取外部的文本文件
//创建服务器模块
const http = require('http');
//创建文件读取模块
const fs = require('fs');
//尝试读取外部的文件
//创建服务器
const server = http.createServer (function (req,res) {
//设置响应头
res.writeHead(200,{'Content-Type': 'text/html;charset=UTF-8' });
//读取文本文件
fs.readFile('./public/public.txt',function (err,data) {
//如果文件读取失败,返回错误原因
if(err) {
console.log(err);
return;
}
//文件读取成功,显示数据
res.end(data.toString());
})
})
//监听服务器端口
server.listen(3000);
console.log('server start at 3000');
这个时候没有路由 ,你在任何一个路径先访问的都是这个页面
1.2 同步读取文件
同步读取文件采用复制的方式返回数据,几乎所有的fs函数都有同步版本,只需要在一部版本的函数后面添加Sync 即可
fs.readFileSync(文件路径)
const fs = require('fs');
const data = fs.readFileSync('./1.txt');
console.log(data);
console.log(data.toString())
从打印结果中可以看到读取到的数据也是数据流的形式,如果需要显示数据通过data.toString.
单数同步读取文件有一个很严重的问题,如果我们的文件读取失败.它会直接导致程序奔溃,这是我们最不想要看到的结果,所以我们需要自己捕获错误,然后处理错误,不让程序奔溃.
try {
const fs = require('fs');
const data = fs.readFileSync('./2.txt');
console.log(data.toString());
}catch (e) {
console.log('读取文件出现错误')
}
1.3 流式读取
将数据从硬盘中读取一节就触发一次回调函数,也就是读取一节数据处理一节数据 实现大文件操作
2.写入文件
写入文件也有同步和异步梁总方式
2.1异步写入文件
fs.writeFile('文件名','数据',function(err){ /* 数据写入失败时的回调函数*/ })
需要注意的是writeFile是一种覆盖式的写入
//引入fs模块
const fs = require('fs');
//异步写入
let data = "红红火火恍恍惚惚";
fs.writeFile('./write1.txt',data,function (err) {
// console.log(arguments);
// 回调函数只接受一个参数,写入成功返回null, 写入失败返回对象
if(err) {
console.log('数据写入失败');
}else {
console.log('数据写入成功');
}
})
事先我没有创建write1.txt.当我执行完这段代码之后他会自动的在我的文件夹中创建一个write1.txt.
2.2 同步写入文件
fs.writeFileSync(文件路径, 数据)
写入文件
let data = '普普通通娉娉袅袅';
fs.writeFileSync('./write2.txt',data);
console.log('文件写入成功');
和读取文件相同,我们依旧需要捕获错误来防止程序奔溃.
let data = '普普通通娉娉袅袅';
try {
fs.writeFileSync('./write2.txt',dat);
console.log('文件写入成功');
}catch (e) {
console.log('文件写入失败');
}
3. 追加式写入
3.1 异步追加
fs.appendFile(文件路径, 数据, 回调函数)
//引入fS模块
const fs = require('fs');
let data = '虽不能至,心向往之';
fs.appendFile('./write1.txt',data,function (err) {
if(err) {
console.log('数据写入失败');
}else{
console.log('数据写入成功');
}
})
3.2 同步追加
// 同步步写入的方式,数据是通过返回值赋值给变量
// 同步写入函数返回undefined. 所以一般异步同步写入数据不需要返回值
let data = "我就是一个普通的字符串"
fs.appendFileSync("index2.txt",data)
4. 读取文件/文件夹信息
4.1语法方式
异步读取:
fs.stat("文件名",function(err,stats){
//state是文件的信息对象,包含了常用个文件信息
})
同步读取:
const stat = fs.statSync("./node")
4.2 读取信息示例
const fs = require('fs');
fs.stat('index.txt',function (err,stats) {
// console.log(arguments)
console.log(stats)
})
打印结果
Stats {
dev: 2691606309,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: 4096,
ino: 5066549581201378,
//文件大小,字节数
size: 13,
blocks: 0,
atimeMs: 1587351338733.8674,
mtimeMs: 1587351338733.8674,
ctimeMs: 1587351338733.8674,
birthtimeMs: 1587351318740.8376,
// 上一次文件访问时间
atime: 2020-04-20T02:55:38.734Z,
// 文件内容修改时间
mtime: 2020-04-20T02:55:38.734Z,
// 文件状态改变时间
ctime: 2020-04-20T02:55:38.734Z,
//// 第一次创建时间
birthtime: 2020-04-20T02:55:18.741Z
}
4.3 文件信息对象的方法
语法:
stats.isFile()
判断是不是文件
stats.isDirectory()
判断是不是文件夹(目录)
const fs = require('fs');
fs.stat('index.txt',function (err,state) {
//判断是不是文件
console.log(state.isFile());
})
打印的结果为true
4.4 修改文件名rename
const fs = require("fs");
fs.rename("./index.txt", '123.txt', err => {
if(err) throw err
console.log("done!")
})
5.删除目录
fs.unlink(path,callback)
// 断开连接式的删除文件
示例:
const fs = require("fs");
fs.unlink("123.txt", function (err) {
if (err) {
throw err
} else {
console.log("删除成功")
}
})
6.新增目录
fs.mkdir(path,callback)
示例代码:
fs.mkdir("./test",function(err){
if (err) {
throw err
} else {
console.log("删除成功")
}
})
7.读取目录中的文件列表
fs.readdir(path,callback)
示例代码:
fs.readdir("../read",function(err,list){
console.log(list)
// list 是读取文件夹列表
})
// 如果文件夹存在的话,list是 一个node文件夹下所有文件以及文件夹的数组集合
// 如果文件夹不存在就是err
8.删除空文件夹
fs.rmdir(path,callback)
示例代码:
fs.rmdir("../null",function(err){
// err 报错信息
})
9.监听文件是否发生改变
// watch是监听 文件夹内所有的文件变化
fs.watch("./",{
recursive: false // 默认是flase 是否递归监听
}, (changeType, filename) => {
console.log(chaneType) // 改变的类型 ,是修改一个文件 还是新增文件亦或是删除文件
console.log(filename) // 修改的文件名字
})
// watchFile 是监听一个文件的变化
fs.watchFile('./node/1.txt',(c,p) => {
console.log(p);
console.log(c)
})
二.fs流式读写
1.Stream介绍
用read读取文件 方法,会将文件整体读入缓存区,然后使用,用write方法写入文件的时候,会将文件整体读入缓存区,在修改后整体写入文件, 也就是说在node中无论read还是write都是把文件视为一个整体.Node需要在内存中开辟与文件相同大小的缓存空间,如果文件小,的确没有什么问题,如果是一个非常大的文件,超过内存大小怎么办?
所有互联网传输的数据都是以流的方式传输的.
2. 有关流的操作
2.1 流式读取
// 1. 创建读取流
var stream = fs.createReadStream(path)
// 2. 绑定data事件接受数据
stream.on("data",function(data){
console.log(data)
console.log(1) // 打印几次,表示数据分了几次流
})
// 3. 绑定end事件表示读取完毕
end 表示在读取流读取完毕后触发的时间
stream.on("end",function(){
console.log("数据流读取完毕")
})
// 4. 绑定error错误事件
读取流事件:error 表示在读取流读取错误时后触发的时间
stream.on("error",function(err){
throw err
})
示例:
// 2.1 创建一个可读流
let stream = fs.createReadStream("./index2.txt")
// console.log(stream)
let data = "";
// 2.2 绑定接受数据的事件
stream.on("data", function(buf){
// console.log(2);
// console.log(buf.toString());
data += buf;
})
// 2.3 当数据读取完毕以后会触发end事件
stream.on("end", function(){
console.log("数据读取完毕");
})
2.2 流失写入:
// 1. 创建写入流
var stream = fs.createWriteStream(path)
// 2. 写入数据
stream.write("数据1")
// 3. 写入完毕后结束写入流
stream.end()
// 4. 数据写入完成事件
stream.on("finish",function(){
})
// 5. 绑定error出错事件
stream.on("error",function(err){
})
示例:
const fs = require("fs");
// 创建一个写入流
var stream = fs.createWriteStream("./index1.txt");
// 写入数据
stream.write("太阳当空照");
stream.write("花儿对我笑");
stream.write("小鸟说:早早早");
stream.write("你为什么背上小书包");
stream.write("我要上学校");
stream.end(); // 已流的方式写入数据必须显示的声明结束
三. fs管道方式
1.管道的概念
管道是Node.Js中流的实现机制. 管道(pipe)提供了一个输出流到输入流传入数据的一个机制.通常我们用于一个流中获取数据并将数据传递到另外一个流中.
2.管道的语法
语法
输出流.pipe(输入流)
作用
管道可以实现对大文件的操作(文件 大小超过内存)
2.1 不采用管道方式复制文件
//引入fs模块
const fs = require('fs');
//创建读取流和写入流
let s1 = fs.createReadStream('./index1.txt');
let s2 = fs.createReadStream('./index2.txt');
//读入完成后,写入完成
s1.on('data',function (d) {
s2.write(d);
})
//引入fs模块
s1.on('end',function () {
s2.end();
console.log("复制完成")
})
2.2 采用管道流的方式复制文件
const fs = require("fs");
// 创建读取流和写入流
let s1 = fs.createReadStream("./index1.txt");
let s2 = fs.createWriteStream("./index2.txt");
s1.pipe(s2);