一、 文件操作
文件操作分为两个部分,一部分是操作文件中的数据,对文件的读取和写入。另一部分是文件的解构操作,对文件夹的读取、创建、删除和对文件的删除、移动、更名。
文件操作基于fs核心模块,所有的方法都有两个,一个同步一个异步。
区别:同步方法在使用的时候在异步方法后面加上Sync,他比异步方法多一个返回值。
异步方法比同步方法多传递一个参数(回调函数)
1、文件的数据操作
1.文件的读取
readFile();异步文件读取方法。
参数有两个或三个:
- 文件的路径。
- 可选参。字符集。若传递返回字符串,不传返回时buffer(一般读取图片时不会传递)
- 回调函数,内置两个参数,第一个是读取的错误,第二个是读取成功的数据。
readFileSync():同步文件读取方式。
参数有一个或两个:
- 文件的路径。
- 可选参。字符集。若传递返回字符串,不传返回时buffer(一般读取图片时不会传递)
注: 同步没有回调函数,返回值是读取成功获得的数据。
同步方法在使用的时候在异步方法后面加上Sync,他比异步方法多一个返回值。
异步方法比同步方法多传递一个参数(回调函数)。
下面只介绍一种方法,但都有两种方式,区别一样
const fs = require('fs');
// console.log(fs);
/*
读取文件使用readFile方法
内置两个或者三个参数
第一个参数是文件的路径
第二个参数可选 是字符集 如果说传递第二个参数 返回字符串 如果说 不传递 那么返回是Buffer
一般情况下 我们读取图片的时候 不会传递第二个参数
第三个参数是回调函数 回调内置两个参数 第一个参数是读取的错误 第二个参数是读取的数据
*/
// 内置三个参数的时候
fs.readFile('../text/document.txt','utf-8',(error,data)=>{
// if (error) console.log('读取失败');
// else console.log(data);
error ? console.log('读取失败') : console.log(data);
})
// 内置两个参数的时候
fs.readFile('../text/document.txt',(error,data)=>{
if (error) console.log('读取失败');
else console.log(data.toString());
})
// 使用同步方法
let result = fs.readFileSync('../text/document.txt','utf-8');
console.log(result);
2.文件的写入
1.同步写入 最直观
涉及到三个方法
openSync : 打开文件
writeSync : 写入文件
closeSync : 关闭文件
const fs = require('fs');
/*
openSync : 打开文件
内置三个参数
第一个参数是文件的路径
第二个参数是打开的方式 r w a
r : 只读方式打开
w : 写入方式打开 覆盖写
a : 写入方式打开 追加写
第三个参数是打开文件的权限 一般不会传递
返回值是资源句柄
*/
let fd = fs.openSync('../text/sync.txt', 'w');
// let fd = fs.openSync('../text/sync.txt','a');
// console.log(fd);
// 编辑一个写入的内容
let str = "我爱北京天安门 天安门上红旗升\n";
/*
writeSync : 写入文件
内置四个参数
第一个参数是资源句柄
第二个参数是写入的内容
第三个参数字符集
第四个参数是是写入的起始位置 一般不会传递 因为一般情况下覆盖写比较多
*/
fs.writeSync(fd, str, 'utf-8');
/*
closeSync : 关闭文件
内置一个参数
参数是资源句柄
*/
fs.closeSync(fd);
2.异步写入 最Node
涉及到三个方法
open : 打开文件
write : 写入文件
close : 关闭文件
const fs = require('fs');
/*
open : 打开文件
内置四个参数
第一个参数是文件的路径
第二个参数是打开的方式 r w a
r : 只读方式打开
w : 写入方式打开 覆盖写
a : 写入方式打开 追加写
第三个参数是打开文件的权限 一般不会传递
第四个参数是回调函数 回调内置两个参数
第一个参数是错误
第二个参数是资源句柄
*/
// 定义一句写入的内容
let str = "葡萄酒 金魄罗 无极十五级孖拖";
fs.open('../text/async.txt', 'w', (error, fd) => {
if (error) {
console.log('打开失败');
} else {
/*
write : 写入文件
内置五个参数
第一个参数是资源句柄
第二个参数是写入的内容
第三个参数字符集
第四个参数是是写入的起始位置 一般不会传递 因为一般情况下覆盖写比较多
第五个参数是回调函数 回调内置一个参数 参数是错误
*/
fs.write(fd, str, 'utf-8', error => {
if (error) {
console.log('写入失败');
} else {
console.log('写入成功');
}
})
/*
close : 关闭文件
内置两个个参数
第一个参数是资源句柄
第二个参数是回调 回调内置一个参数 参数是错误
*/
fs.close(fd,error=>{
if (error) console.log('关闭失败');
else console.log('关闭成功');
})
}
})
3.简单写入 最简单
简单写入的方式是最常用的方式 因为简单写入和读取差不多 只是涉及到一个方法,而且不需要关闭资源和打开资源 直接使用就可以
涉及到的方法 writeFile
同步方法 writeFileSync
const fs = require('fs');
/*
涉及到的方法 writeFile
同步方法 writeFileSync
内置四个参数
第一个参数是文件的路径
第二个参数是写入的内容
第三个参数是描述 描述是一个对象 对象中有打开方式 字符集
第四个参数是回调函数
回调内置一个参数 参数是错误
*/
let book = [
{book_id:1,book_name:'史记',book_price:66,book_page:600,book_author:'司马迁'},
{book_id:2,book_name:'资治通鉴',book_price:88,book_page:1200,book_author:'司马光'},
{book_id:3,book_name:'全球通史',book_price:72,book_page:800,book_author:'斯塔夫里阿诺斯'},
{book_id:4,book_name:'万历十五年',book_price:36,book_page:700,book_author:'黄仁宇'},
{book_id:5,book_name:'本草纲目',book_price:76,book_page:900,book_author:'李时珍'},
{book_id:6,book_name:'论语',book_price:32,book_page:360,book_author:'曾参,有若'}
];
// 写入的数据必须是一个字符串
// fs.writeFile('../text/easy.json',JSON.stringify(book),{flag:'w',encoding:'utf-8'},error=>{
// if (error){
// console.log('写入失败');
// }else{
// console.log('写入成功');
// }
// })
let obj = {book_id:7,book_name:'孙子兵法',book_price:25,book_page:350,book_author:'孙武子'};
// 选获取出所有数据
let bookArr = JSON.parse(fs.readFileSync('../text/easy.json','utf-8'));
bookArr.push(obj);
fs.writeFileSync('../text/easy.json',JSON.stringify(bookArr),{flag:'w',encoding:'utf-8'});
4.流式写入 最特殊
流式写入方式相对来说最为特殊 因为流式写入方式需要创建一个可写的流,平时流式应用特别少 只要在特定的时候 才会使用流式操作
一般情况下 前三种方式不适合大规模数量的数据写入操作 一般都是使用前三中方式,在大规模数据写入的时候 一般情况下都会选择流式写入。所以说 使用流式写入方式 我们一般都选择使用追加写
流式写入使用事件驱动 open事件和close事件
涉及到方法三个
createWriteStream : 创建一个可写的流
write : 写入方法
end : 结束方法
open事件 : 打开可写的流
close事件 : 关闭可写的流
const fs = require('fs');
// 使用createWriteStream该方法创建一个可写的流
// 内置两个参数 第一个参数是文件的路径 第二个参数是描述 字符集和打开方式
// 返回值是一个对象资源
let ws = fs.createWriteStream('../text/staeam.txt',{encoding:'utf-8',flags:'a'});
// 使用ws中的on方法触发open事件
ws.on('open',()=>{
console.log('打开了流');
})
// 写入操作
// 使用write方法进行写入数据
// ws.write('第1次想你');
for (let i = 1; i <= 100000; i++){
ws.write(`今天是我第${i}次想你\n`);
}
// 关闭了流
ws.on('close',()=>{
console.log('关闭了流');
})
// 结束必须调用end方法 要不然程序一直都不会进行结束
ws.end();
2.文件的解构操作
1.读取文件夹
方法 : readdir读取文件夹信息
const fs = require('fs');
/*
方法 : readdir读取文件夹信息
内置两个参数
第一个参数是文件夹的路径
第二个参数是回调函数
回调内置两个参数 第一个参数是错误 第二个参数是读取的结果
返回的是一个数组 数组中的数据是文件夹中所有的文件和文件夹
*/
// 异步方法
fs.readdir('../text',(error,data)=>{
if (error){
console.log('读取失败');
}else{
console.log(data);
}
})
// 同步方法
let result = fs.readdirSync('../text/aa');
console.log(result);
2.读取文件或文件夹
方法 : 使用stat方法读取文件或者文件夹的信息
const fs = require('fs');
/*
方法 : stat读取文件或者文件夹信息
内置两个参数
第一个参数是文件或者文件夹的路径
第二个参数是回调函数
回调内置两个参数 第一个参数是错误 第二个参数是读取的结果
返回的是一个对象 对象是信息
*/
// fs.stat('../text/staeam.txt',(error,data)=>{
fs.stat('../text',(error,data)=>{
if (error){
console.log('读取失败');
}else{
console.log(data);
console.log(data.isFile());
}
})
let result = fs.statSync('../text/aa/aa.txt');
console.log(result);
console.log(result.isFile());
3.创建文件夹
方法 : mkdir创建文件夹 但是不能层级创建
const fs = require('fs');
/*
方法 : mkdir创建文件夹 但是不能层级创建
内置两个或者三个参数
第一个参数是创建文件夹的路径
第二个参数是 可选 是否递归创建
第三个参数是回调函数 回调内置一个参数 参数是错误
*/
// 传递两个参数 创建单层目录
// fs.mkdir('../text/bb',error=>{
// if (error) console.log('创建失败');
// else console.log('创建成功');
// })
// 传递三个参数 创建层级目录
fs.mkdir('../text/cc/dd/ee/ff',{recursive:true},error=>{
if (error) console.log('创建失败');
else console.log('创建成功');
})
4.删除文件夹
方法 : rmdir创建文件夹 但是不能层级删除 只能删除空文件夹
const fs = require('fs');
/*
方法 : rmdir删除文件夹 但是不能层级删除
内置两个或者三个参数
第一个参数是删除文件夹的路径
第二个参数是 可选 是否递归删除 可以删除非空目录
第三个参数是回调函数 回调内置一个参数 参数是错误
*/
// 传递两个参数 删除单层目录
// fs.rmdir('../text/bb',error=>{
// if (error) console.log('删除失败');
// else console.log('删除成功');
// })
// 传递三个参数 删除层级目录
fs.rmdir('../text/cc',{recursive:true},error=>{
if (error) console.log('删除失败');
else console.log('删除成功');
})
5.删除文件
方法 : unlink
const fs = require('fs');
/*
方法 : unlink
内置两个参数
第一个参数是删除的文件路径
第二个参数是回调函数
回调内置一个参数 参数是错误
*/
// 异步方法
// fs.unlink('../text/aa/aa.txt',error=>{
// if (error) console.log('删除失败');
// else console.log('删除成功');
// })
// 同步方法
fs.unlinkSync('../text/aa/a.txt');
6.文件移动更名
方法 : rename移动文件或者对文件更名 或者移动+更名
const fs = require('fs');
/*
方法 : rename移动文件或者对文件更名 或者移动+更名
内置三个参数
第一个参数是移动前的路径 + 文件名
第二个参数是要移动到的路径 + 文件名
第三个参数是回调函数
回调内置一个参数 参数是错误
*/
// fs.rename('../text/aa.jpg','./1.jpg',error=>{
// if (error) console.log('移动失败');
// else console.log('移动成功');
// })
fs.renameSync('./1.jpg','../text/aa.jpg');
二.url模块
URL模块是核心模块,URL模块主要有一个方法 其实就是使用URL中的parse方法。这个方法 主要就是将我们URL转化成对象形式 方便我们解析参数、解析路径、解析请求位置
url : 统一资源定位符 统一资源定位器 统一资源定位系统
URL共分为六个部分
协议 : http:// https://
域名 : www.baidu.com www.ujiuye.com www.offcn.com
端口 : :3000 : 5000
路径 : /index.html
参数 : ?name=zhang ?name=kang&age=18
锚点 :
const url = require('url');
// console.log(url);
// 定义两个路径
let str1 = 'https://www.baodu.com:443/index.html?name=kang';
let str2 = 'http://www.ujiuye.com:80/jiaoxue/pxsz/index.html?name=Eric';
console.log(url.parse(str1));
/*
Url {
protocol: 'https:',
host: 'www.baodu.com:443',
port: '443',
hostname: 'www.baodu.com',
search: '?name=kang',
query: 'name=kang',
pathname: '/index.html',
path: '/index.html?name=kang',
href: 'https://www.baodu.com:443/index.html?name=kang'
}
*/
console.log(url.parse(str2));
/*
Url {
protocol: 'http:',
host: 'www.ujiuye.com:80',
port: '80',
hostname: 'www.ujiuye.com',
search: '?name=Eric',
query: 'name=Eric',
pathname: '/jiaoxue/pxsz/index.html',
path: '/jiaoxue/pxsz/index.html?name=Eric',
href: 'http://www.ujiuye.com:80/jiaoxue/pxsz/index.html?name=Eric'
}
*/
三.path模块
basename : 获取路径最后一部分
delimiter : 返回语句的定界符
isAbsolute : 判断路径是否为绝对路径
dirname : 获取路径中文件夹部分
extname : 获取路径中文件扩展名
parse : 格式化路径, 获取每一部分的值
join : 连接路径 连接成相对路径
resolve : 连接路径 连接成绝对路径
const path = require('path');
const url = require('url');
let str1 = 'https://www.baodu.com:443/index.html?name=kang';
let str2 = 'http://www.ujiuye.com:80/jiaoxue/pxsz/index.html?name=Eric';
let str3 = 'https://www.baodu.com:443/index.html';
// basename: 获取路径最后一部分 其实就是请求的文件名字加上路径
console.log(path.basename(str1));
console.log(path.basename(str2));
console.log(path.basename(str3));
console.log('*'.repeat(66));
// delimiter : 返回语句的定界符 最鸡肋
console.log(path.delimiter);
console.log('*'.repeat(66));
// isAbsolute : 判断路径是否为绝对路径 这个方法判定的时候 只有从盘符开始的才算绝对路径
console.log(path.isAbsolute(str1));
console.log(path.isAbsolute(str2));
console.log(path.isAbsolute(str3));
console.log(path.isAbsolute('C:/a/b'));
console.log(path.isAbsolute('Z:/a/b'));
console.log(path.isAbsolute('A:/a/b'));
console.log('*'.repeat(66));
// dirname: 获取路径中文件夹部分 他和basename组成了完整的URL
console.log(path.dirname(str1));
console.log(path.dirname(str2));
console.log(path.dirname(str3));
console.log('*'.repeat(66));
// extname: 获取路径中文件扩展名 取出字符串中最后一个点右面的内容
console.log(path.extname(str1));
console.log(path.extname(str2));
console.log(path.extname(str3));
console.log(path.extname('ABC.jpg'));
console.log(path.extname('ABC.'));
console.log(path.extname('ABC'));
console.log(path.extname(url.parse(str2).pathname));
console.log('*'.repeat(66));
// parse: 格式化路径, 获取每一部分的值
console.log(path.parse(str2));
console.log('*'.repeat(66));
// join : 连接路径 连接成相对路径 若干参数 把所有参数连接在一起 组成一个新的路径
console.log(path.join('./a/b','c','d'));
console.log(path.join('./a/b','../c','d'));
console.log(path.join(__dirname,'./a/b','../c','d'));
console.log('*'.repeat(66));
// resolve : 连接路径 连接成绝对路径
console.log(path.resolve('./a/b','../c','d'));
console.log(path.resolve(__dirname,'./a/b','../c','d'));