node实现文件拷贝2
https://www.cnblogs.com/coding4/p/7495968.html
文件拷贝
NodeJS 提供了基本的文件操作 API,但是像文件拷贝这种高级功能就没有提供,因此我们先拿文件拷贝程序练手。与 copy 命令类似,我们的程序需要能接受源文件路径与目标文件路径两个参数。
小文件拷贝
我们使用 NodeJS 内置的 fs 模块简单实现这个程序如下。
1
2
3
4
5
6
7
8
9
10
11
|
var fs = require( 'fs' ); function copy(src, dst) { fs.writeFileSync(dst, fs.readFileSync(src)); } function main(argv) { copy(argv[0], argv[1]); } main(process.argv.slice(2)); |
以上程序使用 fs.readFileSync 从源路径读取文件内容,并使用 fs.writeFileSync 将文件内容写入目标路径。
豆知识: process 是一个全局变量,可通过 process.argv 获得命令行参数。由于 argv[0] 固定等于 NodeJS 执行程序的绝对路径,argv[1] 固定等于主模块的绝对路径,因此第一个命令行参数从 argv[2] 这个位置开始。
大文件拷贝
上边的程序拷贝一些小文件没啥问题,但这种一次性把所有文件内容都读取到内存中后再一次性写入磁盘的方式不适合拷贝大文件,内存会爆仓。对于大文件,我们只能读一点写一点,直到完成拷贝。因此上边的程序需要改造如下。
var fs = require( 'fs' ); function copy(src, dst) { fs.createReadStream(src).pipe(fs.createWriteStream(dst)); } function main(argv) { copy(argv[0], argv[1]); } main(process.argv.slice(2)); |
以上程序使用 fs.createReadStream 创建了一个源文件的只读数据流,并使用 fs.createWriteStream 创建了一个目标文件的只写数据流,并且用 pipe 方法把两个数据流连接了起来。连接起来后发生的事情,说得抽象点的话,水顺着水管从一个桶流到了另一个桶。
遍历目录
遍历目录是操作文件时的一个常见需求。比如写一个程序,需要找到并处理指定目录下的所有JS文件时,就需要遍历整个目录。
递归算法
遍历目录时一般使用递归算法,否则就难以编写出简洁的代码。递归算法与数学归纳法类似,通过不断缩小问题的规模来解决问题。以下示例说明了这种方法。
function factorial(n) { if (n === 1) { return 1; } else { return n * factorial(n - 1); } } |
上边的函数用于计算 N 的阶乘(N!)。可以看到,当 N 大于 1 时,问题简化为计算 N 乘以 N-1 的阶乘。当 N 等于 1 时,问题达到最小规模,不需要再简化,因此直接返回 1。
陷阱: 使用递归算法编写的代码虽然简洁,但由于每递归一次就产生一次函数调用,在需要优先考虑性能时,需要把递归算法转换为循环算法,以减少函数调用次数。
遍历算法
目录是一个树状结构,在遍历时一般使用深度优先+先序遍历算法。深度优先,意味着到达一个节点后,首先接着遍历子节点而不是邻居节点。先序遍历,意味着首次到达了某节点就算遍历完成,而不是最后一次返回某节点才算数。因此使用这种遍历方式时,下边这棵树的遍历顺序是 A > B > D > E > C > F。
A / \ B C / \ \ D E F |
同步遍历
了解了必要的算法后,我们可以简单地实现以下目录遍历函数。
function travel(dir, callback) { fs.readdirSync(dir).forEach( function (file) { var pathname = path.join(dir, file); if (fs.statSync(pathname).isDirectory()) { travel(pathname, callback); } else { callback(pathname); } }); } |
可以看到,该函数以某个目录作为遍历的起点。遇到一个子目录时,就先接着遍历子目录。遇到一个文件时,就把文件的绝对路径传给回调函数。回调函数拿到文件路径后,就可以做各种判断和处理。因此假设有以下目录:
- /home/user/ - foo/ x.js - bar/ y.js z.css |
使用以下代码遍历该目录时,得到的输入如下。
travel( '/home/user' , function (pathname) { console.log(pathname); });
|
1
2
3
|
/home/user/foo/x.js /home/user/bar/y.js /home/user/z.css |
异步遍历
如果读取目录或读取文件状态时使用的是异步API,目录遍历函数实现起来会有些复杂,但原理完全相同。travel函数的异步版本如下。
function travel(dir, callback, finish) { fs.readdir(dir, function (err, files) { ( function next(i) { if (i < files.length) { var pathname = path.join(dir, files[i]); fs.stat(pathname, function (err, stats) { if (stats.isDirectory()) { travel(pathname, callback, function () { next(i + 1); }); } else { callback(pathname, function () { next(i + 1); }); } }); } else { finish && finish(); } }(0)); }); } |
这里不详细介绍异步遍历函数的编写技巧,在后续章节中会详细介绍这个。总之我们可以看到异步编程还是蛮复杂的。
node实现文件拷贝2的更多相关文章
- node实现文件拷贝1
nodeJS对文件的复制: 一般对于小型文件的复制操作使用的是流的管道运输操作, 首先需要加载引入的文件:var fs = require('fs'); 1.同步创建文件夹 fs.mkdirSync( ...
- Node复制文件
本人开发过程中,经常遇到,要去拷贝模板到当前文件夹,经常要去托文件,为了省事,解决这个问题,写了一个node复制文件. // js/app.js:指定确切的文件名.// js/*.js:某个目录所有后 ...
- Linux系统下远程文件拷贝scp命令
在Linux系统下,不同机器上实现文件拷贝 一.将本地文件拷贝到远程机器: scp /home/administrator/news.txt root@192.168.6.129:/etc/squid ...
- PC windows mobile 文件拷贝
在windows 系统中提供 RAPI.DLL,只需将RAPI.DLL中的,函数导出就可以实现文件拷贝.
- Java学习-045-目录中文件拷贝
挺晚的了,直接上码.敬请各位小主参阅,若有不足之处,敬请指正,非常感谢! 目录文件拷贝源码: /** * <strong>目录拷贝</strong><br> * & ...
- Dos命令完成文件拷贝
Dos命令初阶--文件拷贝 1.XCOPY命令 可以在cmd中录入:XCOPY /? 即可查看帮助 帮助: XCOPY Microsoft Windows [版本 6.2.9200] (c) 2012 ...
- linux或者windows下的文件拷贝
# 上代码 #!/usr/bin/env python # -*- coding:utf-8 -*- import os import shutil import tarfile base_dir ...
- Linux下不同机器之间的文件拷贝
通过 scp 命令实现不同机器之间的文件拷贝. (1)本机考到目标机器:scp 本机文件 目的地: 如:scp /home/odp-web.war root@192.168.6.137:/usr/ ...
- Android——模拟文件拷贝
模拟文件拷贝:要求:要用progressDialog和子线程来模拟显示拷贝进度:进度完成后在主界面提示拷贝完成,分别使用普通方式和消息机制编写. layout文件: <?xml version= ...
随机推荐
- 微服务实践之路--RPC
微服务实践之路--RPC 重点来了,本文全面阐述一下我们的RPC是怎么实现并如何使用的,跟Kubernetes和Openstack怎么结合. 在选型一文中说到我们选定的RPC框架是Apache Thr ...
- Opencv中SVM样本训练、归类流程及实现
支持向量机(SVM)中最核心的是什么?个人理解就是前4个字--"支持向量",一旦在两类或多累样本集中定位到某些特定的点作为支持向量,就可以依据这些支持向量计算出来分类超平面,再依据 ...
- springmvc 与 springfox-swagger2整合
一.pom.xml引入基于maven的swagger依赖 <dependency> <groupId>io.springfox</groupId> <arti ...
- sdut 5-1 继承和派生
5-1 继承与派生 Time Limit: 1000MS Memory limit: 65536K 题目描写叙述 通过本题目的练习能够掌握继承与派生的概念.派生类的定义和用法.当中派生类构造函数的定义 ...
- html5 模糊匹配搜索框
使用bootstrap3-typeahead.js 文件在这里 引用: <script type="text/javascript" src="@Url.Conte ...
- H3C交换机配置ACL禁止vlan间互访
1.先把基础工作做好,就是配置VLAN,配置Trunk,确定10个VLAN和相应的端口都正确.假设10个VLAN的地址分别是192.168.10.X,192.168.20.X......192.168 ...
- MVC基架生成的Create视图
@model MyMusicStore.Models.Album @{ ViewBag.Title = "Create"; } <h2>Create</h ...
- jquery li练习
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- WPF中类似使用tab键功能,可以向上向下定位
原文:WPF中类似使用tab键功能,可以向上向下定位 private void tbYyrs_KeyUp(object sender, KeyEventArgs e) { UIElement elem ...
- .net core api 跨域
什么是跨域? 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制. 所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子: h ...