本文介绍: 在node中,与文件系统交互是非常重要的,服务器本质就是将本地文件发送给远程客户端node通过fs模块来和文件系统进行交互,该模块提供了一些标准文件访问API来打开读取写入文件,以及与其交互。要使用这个模块需要对齐进行导入fs模块是核心模块,直接引入,无需下载

初学Nodejs

文件系统

1、概述

node中,与文件系统交互是非常重要的,服务器的本质就是将本地文件发送给远程客户端。

node通过fs模块来和文件系统进行交互,该模块提供了一些标准文件访问API来打开读取写入文件,以及与其交互。要使用这个模块就需要对齐进行导入const fs = require('fs');

fs模块是核心模块,直接引入,无需下载
官网fs模块地址

2、文件系统的使用

2.2 文件写入

2.2.1 同步文件的写入

从上往下依次执行,并且只有当文件写入完成时才会继续执行下面的代码

如果要打开的文件不存在,那么会先创建文件

// 引入fs模块
var fs = require('fs');
// 打开指定文件,指定权限
var fd = fs.openSync('hello.txt','w');
// 向文件中写内容
fs.writeSync(fd,'你好呀');
// 保存关闭文件
fs.closeSync(fd);
2.2.2 异步文件的写入

{flag:‘xxx’},xxx的可选择的值如下

模式 说明
r 读取文件,文件不存在出现异常
r+ 读写文件,文件不存在出现异常
rs 同步模式下打开文件用于读取
rs+ 同步模式下打开文件用于读写
w 打开文件用于操作,如果不存在创建,如果存在替换内容
wx 打开文件用于操作,如果存在则打开失败
w+ 打开文件用于读写,如果不存在创建,如果存在则截断
wx+ 打开文件用于读写,如果存在则打开失败
a 打开文件用于追加,如果存在则打开失败
ax 打开文件用于追加,如果路径存在则失败
a+ 打开摁键进行读取和追加,如果不存在则创建该文件
ax+ 打开文件进行读取和追加,如果路径存在则失败
var fs = require('fs');

// 打开文件
/**
fs.open('world.txt','w',function(){
	console.log(arguments); // [Arguments] { '0': null, '1': 3 }
})
*/

fs.open('world.txt', 'w', function (err, fd) {
	// 判断是否出错,没出错就进行写入操作
    if (!err) {
        fs.write(fd, '这是异步写入的内容', function (err) {
            if (!err) {
                console.log('写入成功!');
            }

            // 关闭文件
            fs.close(fd, function (err) {
                if (!err) {
                    console.log('文件已关闭');
                }
            })
        })
    } else {
        console.log(err)
    }
})

异步不会阻塞程序的向下执行

2.2.3 简单文件写入

其实就是对上面两个写法进行了依次封装,将openwrite封装到了一个函数里面

API:

同步fs.writeFile(file,data[,options],callback)
异步fs.writeFileSync(file,data[,options])
options参数表示什么格式写入文件内容,默认utf8

// 导入fs模块
var fs = require('fs');

// 同步写入
// fs.writeFileSync('java.txt','这是通过writeFileSync')

// 异步写入
fs.writeFile('javascript.txt','这是通过writeFile写入的内容',{flag:'a'},function(err){
    if(!err){
        console.log('写入成功');
    }else{
        console.log(err);
    }
})

// {flag:'a'}表示写入文档的内容会自动追加文档后面
2.2.4 流式文件写入

前面几个写入方式都是一次性将要写入的内容写入,都不适合大文件的写入,性能较差,容易导致内存溢出,而流式文件写入可以连续写入内容。

API

创建一个可写流
fs.creataWriteStream(path[,options])

var fs = require('fs')

// 创建一个可写流
var ws = fs.createWriteStream('what.txt')

// 通过监听流的open和close事件监听流的打开和关闭
ws.once('open',function(){
	console.log('流打开了')
})

ws.once('close',function(){
	console.log('流打开了')
})

// 通过ws向文件中输出内容
ws.write('通过可写流写入文件的内容1')
ws.write('通过可写流写入文件的内容2')
ws.write('通过可写流写入文件的内容3')

// 关闭
ws.end();

2.3 文件读取

2.3.1 同步/异步文件读取

API

同步:只有当文件读取完成时才会执行后面的代码
(1)fs.readSync(fd, buffer, offset, length[, position])
(2)fs.readSync(fd, buffer[, options])


异步:文件没有读取完时也可以执行后面的代码
(1)fs.read(fd, buffer, offset, length, position, callback)
(2)fs.read(fd[, options], callback)
(3)fs.read(fd, buffer[, options],callback)

  • 同步
const fs = require('fs')

var fd = fs.openSync('hello.txt','r')

// 创建一个buffer数组存储读取到的内容
var buf = Buffer.alloc(10)
console.log(buf); // <Buffer 00 00 00 00 00 00 00 00 00 00&gt;

// 将读取到的内容放到创建buffer中,返回值一个number数字表示文档中的字节
var readContent = fs.readSync(fd,buf)

console.log(buf); //  <Buffer e4 bd a0 e5 a5 bd e5 91 80 00&gt;
console.log(buf.toString()); // 你好呀

console.log(readContent); // 9

fs.closeSync(fd)
2.3.2 简单文件读取

API

(1)同步:fs.readFileSync(path[,options])
(2)异步:fs.readFile(path[,options],callback)
options参数表示什么格式写入文件内容,默认utf8

以异步简单读取为例(常用):

const fs = require('fs')
fs.readFile('hello.txt',function(err,data){
  if(err){
      console.log(err);
  }else{
    //   console.log(data); // 十六进制结果
      console.log(data.toString()); // 你好呀
      // 把读取到的数据再写入到text.txt文件中
      fs.wirteFile('text.txt',data,function(err){
	      if(err){
	      	console.log(err);
	      }else{
	      	console.log('文件写入成功');
	      }
  })
})
2.3.3 流式文件读取

适合读取大文件,分多次读取大文件到内存

const fs = require('fs')

// 创建流式文件读取对象
const rs = fs.createReadStream('hello.txt')
// 创建流式文件写入对象
const ws = fs.createWriteStream('hello2.txt')

// 监听流的开启关闭
rs.once('open',function(){
    console.log('可读流打开了');
})
rs.once('close',function(){
    console.log('可读流关闭了');

    // 关闭可写流
    ws.end()
})

ws.once('open',function(){
    console.log('可写流打开了');
})
ws.once('close',function(){
    console.log('可写流关闭了');
})


// 如果要读取一个可读流中的数据,必须要为可读流绑定一个data事件,data事件绑定完毕,他会自动开始读取数据
rs.on('data',function(data){
    console.log(data);
    console.log(data.toString());
    // 写入数据
    ws.write(data)
})

结果
可读流打开了
可写流打开了
<Buffer e4 bd a0 e5 a5 bd e5 91 80>
你好呀
可读流关闭了
可写流关闭了

适合读取大文件,每次分批读取文件内容(一次大概读取65536个字节

简单写法

const fs = require('fs')

// 创建流式文件读取对象
const rs = fs.createReadStream('hello.txt')
// 创建流式文件写入对象
const ws = fs.createWriteStream('hello2.txt')

// pipe()方法可以将可读流中的内容,直接输出到可写流中
rs.pipe(ws)

2.4 文件系统的其他常用方法

fs.stat('text.txt',function(err,stat){
	console.log(stat); // 一个对象
	console.log(stat.size); // 文件大小
	console.log(stat.isFile());
	console.log(stat.isDirectory);
	...
})
fs.readdir('.',function(err,files){
	if(!err){
		console.log(files); // files是一个字符串数组,每一个元素就是一个文件夹或文件的名字
	}
})

同样可以作为剪切功能

path模块

1、路径动态拼接问题

问题描述

在使用fs模块操作文件时,如果提供的操作路径是以./或者…/开头相对路径时,很容易出现路径拼接错误问题

原因

错误原因是:代码运行时候,会以执行node命令所处的目录为基准动态拼接出被操作文件的完整路径

证明

假设绝对路径C:UsersDesktopnodeTesttxt下有一个test.txt文件,nodeTest下创建一个test.js文件,现在使用fs模块读取这个文件。

const fs = require('fs')

fs.readFile('./txt/test.txt','utf8',function(err,data){
    if(err){
        return console.log('文件读取失败! ' + err);
    }
    
    console.log('文件读取成功! ' + data)
})

这里设置的是相对路径,如果直接test.js目录下使用命令node test.js是可以读取成功的。


但如果我们不是在test.js当前目录下,而是在当前目录的上一级目录C:UsersDesktop下呢?那我们需要node命令后面接上node nodeTest/test.js,但此时会发现报错文件读取失败! Error: ENOENT: no such file or directory, open 'C:UsersDesktoptxttest.txt',因为设置的是相对路径,所以直接将要读取的相对于当前路径下了,而test.txt文件是在nodeTest/txt下的,这里直接略过了nodeTest目录。

解决

在使用fs模块操作文件时,直接提供完整的路径(使用绝对路径或者使用__dirname拼接,__dirname表示当前文件所处目录),不要提供相对路径,以此防止路径动态拼接

const fs = require('fs')

fs.readFile(__dirname+'/txt/test.txt','utf8',function(err,data){
    if(err){
        return console.log('文件读取失败! ' + err);
    }
    
    console.log('文件读取成功! ' + data)
})

2、路径模块

path路径模块就是使用Node.js官方提供的、用来处理路径的模块。它提供了一系列方法属性用来满足用户对路径的处理需求

例如

使用:

// 引入模块
const path = require('path')

// ================================= 
// - join的使用
// ..会抵消前面的路径,例如这里把c抵消掉了
// 并且使用join方法时,也同时会消除./d前面的'.'
const pathStr = path.join('/a','b/c','../','./d','e')

console.log(pathStr) // abde

// =================================
// -basename()的使用
const fpath = '/a/b/c/index.html'

var fullName = path.basename(fpath)
console.log(fullName); // index.html

var nameWithoutExt = path.basename(fpath,'.html')
console.log(nameWithoutExt) // index

// =================================
console.log(path.extname(fpath)); // .html

3、应用html文件拆分

描述
html文档< script> < /script >,< style> < /style>标签中的内容抽离成单独的css文件和js文件,并且通过link标签引入对应css和js文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .father{
            width: 300px;
            height: 300px;
            background-color: skyblue;
        }

        .son{
            width: 100px;
            height: 100px;
            background-color: pink;
        }
    </style>
</head>
<body>
    <div class="father">
        <div class="son">

        </div>
    </div>

    <script>
        window.onload = function(){
			var father = document.getElementsByClassName('father')[0];
	        father.onclick = function(){
	            alert('天蓝色')
	        }
	        var son = document.getElementsByClassName('son')[0]
	        son.onclick = function(event){
            alert('粉色')
            event.stopPropagation()// 阻止事件冒泡
        	}
		}
    </script>
</body>
</html>

在这里插入图片描述

实现如下
目录如下
在这里插入图片描述

// 1】导入模块
// 导入fs模块
const fs = require('fs')
// 导入path模块
const path = require('path')

// 2】定义正则表达式,分别匹配style标签和script标签

const regStyle = /<style>[sS]*</style>/ // s匹配任意空白字符,S匹配任意非空白字符

const regScript = /<script>[sS]*</script>/

// 3】调用fs.readFile()方法读取文件
fs.readFile(path.join(__dirname,'./main.html'),'utf8',function(err,data){
    // 读取失败时
    if(err) return console.log('读取HTML文件失败!'+ err.message)

    // 读取成功时,调用对应的三个方法,分别拆解出css,js,html文件
    resolveCSS(data)
    resolveJS(data)
    resolveHTML(data)
})

// 处理css样式
function resolveCSS(htmlStr){
    // 使用正则提取页面中的style标签
    const r1 = regStyle.exec(htmlStr)

    // 将提取出来的样式字符串做进一步的处理:用空格替代标签style
    const newCSS = r1[0].replace('<style>','').replace('</style>','')

    // 将提取出来的css样式写入到main.css中
    fs.writeFile(path.join(__dirname,'../decoration/main.css'),newCSS,function(err){
        if(err) return console.log('写入CSS样式失败!' + err.message)
        console.log('写入CSS样式成功!');
    })
}

// 处理js样式
function resolveJS(htmlStr){
    // 使用正则提取页面中的style标签
    const r2 = regScript.exec(htmlStr)

    //将提取出来的js代码字符串做进一步的处理:用空格替代标签script
    const newJS = r2[0].replace('<script>','').replace('</script>','')

    // 将提取出来的js代码写入到main.js中
    fs.writeFile(path.join(__dirname,'../decoration/main.js'),newJS,function(err){
        if(err) return console.log('写入JS脚本失败!' + err.message)
        console.log('写入JS脚本成功');
    })
}

// 处理html文件
function resolveHTML(htmlStr){
    // 使用字符串的replace方法,把内嵌的style和script标签替换为外联引入的形式
    const newHTML = htmlStr
    .replace(regStyle,'<link rel="stylesheet" href="../decoration/main.css">')
    .replace(regScript,'<script src="../decoration/main.js"></script>')

    fs.writeFile(path.join(__dirname,'../decoration/main.html'),newHTML,function(err){
        if(err) return console.log("写入HTML文件失败!" + err.message);
        console.log("写入HTML页面成功!");
    })
}

结果如下
在这里插入图片描述

原文地址:https://blog.csdn.net/lalala_dxf/article/details/126374738

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_35034.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注