Node.js之文件及文件流(fs,path,buffer,stream)

2023-11-10

文件操作

1 文件模块fs

fs模块---》操作文件---》io----》node的特长
fs模块是node非常重要的模块,能体现出node的优势
  • fs.readFile() 读文件
  • fs.writeFile() 写文件
  • fs.appendFile() 在文件的内部去追加写一些内容
  • fs.mkdir() 创建文件夹
  • fs.readdir() 读文件夹
  • fs.access() 判断路径(文件或者文件夹是都存在)
  • fs.stat()
    isFile:用于判断被查看的对象是否为一个文件,如果是返回true,否则,返回false;
    isDirectory:用于判断被查看的对象是否为一个目录,如果是的话则返回true,否则,返回false;
    isSymbolicLink:用于判断被查看的文件是否为一个符号链接文件,如果是的话则返回true,否则,返回false。该方法仅在lstat方法的回调函数中有效;

访问文件路径问题:

//目录结构:
lujing
    lib
        lujingTest.js
        foo.txt
    test.js
    foo.txt


//lujing\foo.txt
外层的foo.text

//lujing\lib\foo.txt
内层的foo.text

-----------------
//示例一

//lujing\test.js
var rf = require('./lib/lujingTest.js');

rf('./foo.txt',function(data){
    console.log(data);
})

//lujing\lib\lujingTest.js
var fs = require('fs');
var rf = function(path,callback){
    fs.readFile(path,'utf-8',(err,data)=>{
        callback(data)
    })
}
module.exports = rf;

测试以上代码:node test.js,输出结果:外层的foo.text

总结:require引入模块,路径是相对于调用的模块的。可以理解为,把require进来的模块拿到调用的模块执行,仿require.js的代码可以看上篇博客
但要是想访问内层的foo.text,可以使用全局变量__dirname,代码如下:

//示例二

//lujing\test.js
var rf = require('./lib/lujingTest2.js'); //!!!改为lujingTest2.js

rf('./foo.txt',function(data){
    console.log(data);
})

//lujing\lib\lujingTest2.js
//使用__dirname获取当前文件的文件夹路径
var fs = require('fs');
var rf = function(path,callback){
    fs.readFile(__dirname+'/foo.txt','utf-8',(err,data)=>{
        callback(data)
    })
}
module.exports = rf;

问题: 上面代码在拼接路径时使用__dirname+'/foo.txt',有时写成__dirname+',/foo.txt',就会出现问题。可以使用path.join(__dirname,'./foo.text'),就会为我们解决这个问题.

var fs =require('fs');
var path=require('path');
var rf=function(cb){
    console.log(path.join(__dirname,'./foo.text'));
    fs.readFile(path.join(__dirname,'./foo.text'),'utf8',(err,data)=>{
            cb(data);
    })
}
module.exports=rf;

path下面详解。

writeFile:

//第一参数路径
//第二个写的内容
//第三个编码格式
//第四个回调函数 

//多次写入会把原来的内容覆盖
//文件不存在的时候会创建文件,但是不会创建文件夹(找不到报错!)

var fs = require('fs');
fs.writeFile('./foo.txt', '我是写入的内容write', 'utf-8', (err)=>{
    if (err) {
        console.log(err);
    } else {
        fs.readFile('./foo.txt', 'utf-8', (err, data) => {
            console.log(data);
        })
    }
})

//找不到a文件夹,报错
fs.writeFile('./a/foo.txt', '我是写入的内容write', 'utf-8', (err)=>{
    if (err) {
        console.log(err);
    } else {
        。。。
    }
})

fs.appendFile('./foo.txt','我是追加的内容','utf-8',(err)=>{
    if (err) {
        console.log(err);
    } else {
        fs.readFile('./foo.txt', 'utf-8', (err, data) => {
            console.log(data);
        })
    }
})

创建、读取文件夹(Linux命令)

fs.mkdir('./a',(err)=>{

})

//callback 里面的参数多了一个files
//files以数组的形式呈现
fs.readdir('../file',(err,files)=>{
    console.log(files);
})
//结果:[foo.txt,a,writeFile.js]

fs.readdir('../file',(err,files)=>{
    console.log(files+"1");
})
//结果:foo.txt,a,writeFile.js1

access:

//access不光可以判断文件还可以判断文件夹
fs.access('./a',(err)=>{
})

fs.stat

fs.stat(path,callback)
//获取文件信息对象Stats,包括文件大小,gid等信息

//文件信息对象Stats的一个方法,判断当前文件是不是一个文件

stats.isDirectory()
//文件信息对象Stats的一个方法,判断当前文件是不是一个文件夹

fs.stat('./a',(err,stats)=>{
   if(stats.isDirectory()){
      console.log("是文件夹");
   }
   else{
       console.log("不是文件夹");
   }   
})

2 path:

var path=require('path');

path.resolve('../../test');
//一个路径或路径片段解析成一个绝对路径,返回解析后的路径字符串

console.log(path.join(__dirname,'./foo.text'));
//假如__dirname为‘\a’,则结果为:\a\foo.txt

console.log(path.basename('C:\\temp\\myfile.html')); 
//(文件名称+后缀名)myfile.html

console.log(path.basename('/foo/bar/baz/asdf/quux.html', '.html'));
//(文件名称)quux

console.log(path.dirname('/foo/bar/baz/asdf/quux.js'));
//结果(文件路径):/foo/bar/baz/asdf

console.log(path.extname('/foo/bar/baz/asdf/index.js.css.html'));
//结果(后缀名): .html

实例:深度遍历文件夹下所有文件:

const fs = require('fs');
const path = require('path');

//解析需要遍历的文件夹,获取绝对路径 
var filePath = path.resolve('../../test');
fileDisplay(filePath); //

function fileDisplay(filePath) {
    fs.readdir(filePath, function(err, files) {
        if (err) {
            console.log(err);
        } else {
            files.forEach(function(filename) {
                //获取当前文件的绝对路径
                var filedir = path.join(filePath, filename);
                fs.stat(filedir, function(err, stats) {
                    if (err) {
                        console.warn('获取文件stats失败');
                    } else {
                        if (stats.isFile()) {
                            console.log(filedir);
                        }
                        if (stats.isDirectory()) {
                            //递归,如果是文件夹,就继续遍历该文件夹下面的文件
                            fileDisplay(filedir);
                        }
                    }
                })
            })
        }
    })
}

运行结果:

G:\html\mysuccesstest\node\node-biji\test\新建文本文档.txt
G:\html\mysuccesstest\node\node-biji\test\.vscode\launch.json
G:\html\mysuccesstest\node\node-biji\test\debug\01.js
G:\html\mysuccesstest\node\node-biji\test\debug\mytest.js
G:\html\mysuccesstest\node\node-biji\test\file\foo.txt
G:\html\mysuccesstest\node\node-biji\test\file\path.js
G:\html\mysuccesstest\node\node-biji\test\file\writeFile.js
G:\html\mysuccesstest\node\node-biji\test\fileStream\test.js
G:\html\mysuccesstest\node\node-biji\test\fileTraverse\fileDisplay.js
G:\html\mysuccesstest\node\node-biji\test\fileTraverse\fileTraverse.js
G:\html\mysuccesstest\node\node-biji\test\lujing\foo.txt
G:\html\mysuccesstest\node\node-biji\test\lujing\test.js
G:\html\mysuccesstest\node\node-biji\test\lujing\test2.js
G:\html\mysuccesstest\node\node-biji\test\myFS\index.js
G:\html\mysuccesstest\node\node-biji\test\myFS\text.js
G:\html\mysuccesstest\node\node-biji\test\lujing\lib\foo.txt
G:\html\mysuccesstest\node\node-biji\test\lujing\lib\lujingTest.js
G:\html\mysuccesstest\node\node-biji\test\lujing\lib\lujingTest2.js
G:\html\mysuccesstest\node\node-biji\test\myFS\node_modules\readf\index.js
G:\html\mysuccesstest\node\node-biji\test\myFS\node_modules\readf\package.json

3 Buffer:

在Node中,用用需要处理网络协议、操作数据库、处理图片、接收上传文件等,在网络流和文件的操作中,还要大量处理二进制数据,js自有的字符串远远不能满足这些需求,于是Buffer对象应运而生。

Buffer类似于Array对象,但它主要操作字节。Buffer是一个典型的使用js和C++结合的模块,性能相关部分使用C++,费性能相关部分使用js。

Buffer所占用的内存不是通过V8分配的,属于堆外内存。由于V8垃圾回收性能的影响,将常用的操作对象用更高效和专有的内存分配回收策略来管理是个不错的思路。

1汉字=2字节  00100010 00000000
1字节(Byte)=8字位=8个二进制数 
1字位(bit)=1个二进制数 
1B=8b 
1KB=1024B 
1MB=1024KB 
1GB=1024MB 

3.1 创建Buffer

Buffer在Node启动时就加载了它,并将其放在全局对象上。所以不需要使用require()即可使用

Buffer类似于数组,元素为16进制的两位数,表示0-255之间的数值。

new Buffer(size)
new Buffer(str,[encoding])
var buf = new Buffer(100);
buf[1] = 0x6E;
buf[0] = 0x61;
console.log(buf);
console.log(buf.toString());

若元素赋值小于0,则逐次加256,直到为0-255的数值;若元素大于255,就逐次减256,直到为0-255的数值;如果是小数,则舍弃小数部分,保留整数部分。

3.2 Buffer的一些属性和方法

buf[index] 通过下标访问 buffer 的某个字节的数据
- buf.indexOf(value,[byteOffset],[encoding]) 查找某个字符在 buffer 内存中的字节下标
- buf.includes(value,[byteOffset],[encoding])
- buf.length
- buf.slice([start,[end]])
- buf.toString([encoding],[start], [end])
- buf.write(string,[offset],[length],[encoding])

3.3 造成乱码的原因

  • 什么是字符集编码
  • 为什么要有编码
    • 计算机只能识别二进制
    • 为了让计算机可以识别字符,人类做了一个字典 二进制 -> 字符 的映射关系
  • 为什么会产生乱码
    • 文件编码和读取该文件的编码不一致导致的
  • 如何解决乱码
    • 让文件和读取的字符编码集一致即可
  • 如何解决 Node 原生不支持的一些编码
    • 通过 第三方包:iconv-lite
    • 该第三方包可以解决 gbk 等编码不支持的问题

4 文件流

  • 流对象 stream
  • fs.readFile()和fs.writeFile()问题?
    • 对大文件的处理,例如下载
  • 通过文件流的形式传输大文件
  const rs = fs.createReadStream(path1);
  const ws = fs.createWriteStream(path1);
  rs.pipe(ws);
  • 如何去控制流。
    我们可以通过监听stream对象里面的事件,去控制读写流。
const fs = require('fs');

const rs = fs.createReadStream('./1203上午.wmv');
const ws = fs.createWriteStream('./2.wmc');
rs.on('data', function(chunk) {
    console.log(chunk.length);
    ws.write(chunk);
})
rs.on('end', function() {
    console.log('结束了');
    ws.end();
})
//执行结果:
65536
65536
...
65536
65536
55661
结束了

传输时显示进度:

const fs = require('fs');

const rs = fs.createReadStream('./1204上午.wmv');
const ws = fs.createWriteStream('./2.wmc');
// rs.pipe(ws);

//取文件对相应的stats对象
var stats = fs.statSync('1204上午.wmv');
//文件大小
var count = stats.size;

var sumSize = 0;
rs.on('data', function(chunk) {
    // 每得到一个chunk(buffer),取一次长度并且加到data的值里面去
    sumSize = sumSize + chunk.length;
    console.log('传输进度:' + parseInt(sumSize / count * 100) + "%");
    ws.write(chunk);
})
rs.on('end', function() {
    console.log('结束了');
    ws.end();
})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Node.js之文件及文件流(fs,path,buffer,stream) 的相关文章

随机推荐

  • Kubernetes[k8s] 最新版1.27.3安装教程,使用containerd模式

    背景 公司使用的是交老的k8s版本 1 16 由于老版本的K8s对于现在很多新特性不支持 所以需要升级到新版本 目前2023年7月11日最新版本的k8s是v1 27 3 通过参考官方文档进行k8s部署工作 其中涉及到操作系统配置 防火墙配置
  • ES6 中的let、const与var的区别

    首先需要明确的是let const var都是用来定义变量的 在ES6之前 我们一般都用var来定义变量 例如 function test var i 1 console log i console log j var j 2 test c
  • xgboost的优势是什么,为什么能在人工智能竞赛中取得好成绩

    XGBoost eXtreme Gradient Boosting 是一种高效的集成学习算法 它是在基于决策树的梯度提升算法的基础上进行改进 它的优势在于 高效 XGBoost使用了并行化处理 能够快速训练大规模的数据集 稳定 XGBoos
  • vscode 无法连接远程服务器 .vscode-server Permission denied

    错误log 用 VScode直接连接服务器 遇到这个问题 我的终端ssh是可以直接登上服务器的 VScode不行 18 41 45 067 Server installation process already in progress wa
  • Python操作mongodb数据库详解

    数据库的分类 数据库可以简单的分为 MySQL 和 NOSQL 两类 这里的 NOSQL 不是 NO SQL 的意思 他的意思是 Not Only MySQL MySQL与NoSQL之间的区别 1 MySQL是一个基于表格设计的关系数据库
  • 线性代数学习笔记——第七十一讲——正交矩阵

    1 正交矩阵引例 2 正交矩阵的定义 3 正交矩阵的充要条件是其行 列 向量组都是规范正交向量组 4 正交矩阵判定示例 5 正交矩阵的应用示例1 6 正交矩阵的应用示例2
  • 【MacOS】SSH 设置别名+免密登录

    设置别名 首先 进入ssh的config文件 vim ssh config 按I写入 Host my name User zmq HostName 1xx xx xx xxx Port 22 输入 x保存退出 设置别名成功 可以直接 ssh
  • 朴素贝叶斯算法_朴素贝叶斯算法介绍(补充)

    朴素贝叶斯是基于贝叶斯决策理论和特征属性独立假设的生成方法 朴素贝叶斯中的朴素是指特征条件独立假设 贝叶斯定理是用来描述两个条件概率之间的关系 上一篇有做一些介绍 朴素贝叶斯算法介绍 这次做一些补充 1 贝叶斯原理 先验概率 通过经验来判断
  • log4net使用

    说明 本程序演示如何利用log4net记录程序日志信息 log4net是一个功能著名的开源日志记录组件 利用log4net可以方便地将日志信息记录到文件 控制台 Windows事件日志和数据库 包括MS SQL Server Access
  • 2023年全国职业院校技能大赛-高职组“区块链技术应用”赛项赛卷(1卷)

    目录 模块一 区块链产品方案设计及系统运维 35分 任务1 1 区块链产品需求分析与方案设计 区块链食品溯源系统概要设计说明书 1 引言 1 1编写目的 2 总体设计 2 1需求规定 2 1 2输入输出要求 2 2运行环境 2 2 1支持架
  • 30-Docker-常用命令详解-docker cp

    Docker 常用命令详解 docker cp 前言 docker cp 语法格式 options说明 SRC PATH 和 DEST PATH 说明 使用示例 从容器复制文件到主机 从主机复制目录到容器 前言 本篇来学习docker cp
  • SpringBoot自动配置原理

    自动装配简单来说就是自动把第三方组件的bean装载到IOC容器里面 不需要开发人员再去写bean相关的配置 在springboot应用里面只需要在启动类中加上 springbootapplication注解就可以实现自动注解配置 他是一个复
  • uni-app开发小程序无需https接口即可上线

    云函数的使用 使用uniCloud创建云函数 具体使用见官方说明https uniapp dcloud io uniCloud quickstart 调用方法 在开通云函数的时候 uni官方给出两种方案 一种腾讯云 基本与微信小程序的云开发
  • 使用Java定时执行shell脚本

    执行shell脚本 Runtime getRuntime exec 可以直接执行部分命令 不过执行一个shell脚本的话更方便修改 public static void runshell String path try String get
  • python基础(第四章)函数+对象方法(下)

    对象方法 1 对象的方法 这个对象类型在标准库里面就有的方法 2 对象的方法调用 对象 方法 3 字符串 str 1 count 计算字符串中包含的多少个指定的子字符串 str1 abcaaa str1 count a 结果 4 2 end
  • C++ ROS串口通信serial库使用

    来源是使用UWB开发板时 希望能够ubuntu中通过ros话题的方式获得UWB测距信息 开发板通过串口接收AT指令 来进行控制 发送也通过串口 给大家一个参考 使用的是安信可的NodeMCU BU01开发板 修改了固件源码 提升频率为10h
  • ValueError: invalid literal for int() with base 10: ‘cuda:0‘

    detectron2 转onnx时出现的问题 升级torch就好了
  • 大模型微调之P-tuning方法解析

    转载 原文链接 大模型微调之P tuning方法解析 Part1前言 Bert时代 我们常做预训练模型微调 Fine tuning 即根据不同下游任务 引入各种辅助任务loss和垂直领域数据 将其添加到预训练模型中 以便让模型更加适配下游任
  • 【C++】: 隐式构造函数和显示构造函数的实验和讨论

    1 先放一段实验代码及编译结果 include
  • Node.js之文件及文件流(fs,path,buffer,stream)

    文件操作 1 文件模块fs fs模块 操作文件 io node的特长 fs模块是node非常重要的模块 能体现出node的优势 fs readFile 读文件 fs writeFile 写文件 fs appendFile 在文件的内部去追加