使用nodejs进行了简单的文件分卷工具
关键词:node fs readline generator
(在这之前需要声明的是这篇博客的应用范围应该算是相当狭隘,写出来主要也就是给自己记录一下临时兴起写的一个小工具,仅从功能需求上来说我相信是不适用于大多数读者的,欢迎有兴趣看的朋友给我做一次review)
最近沉迷漫画,收集了一堆野生资源,偶尔会遇到一些四格漫画,观看体验不是很好,因为每话篇幅比较短,就独立成了一个目录,譬如这样:


const fs = require('fs');
const readline = require('readline');
/**
* @description 获取questtion的返回
* @param {String} question 用户提示
* @param {Function} handler 验证用户输入
* @returns {Promise} rl.question方法本身是通过回调来处理用户输入的,所以选择了返回promise来做阻塞,有序地抛出question并接收answer
*/
function getQuestionResult(question,handler){
return new Promise((res)=>{
// 创建一个可读流,用来读取在cmd中的输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
/**
* 考虑到即使用户输入异常,question方法都会在监听到换行之后结束,所以把handleResult的结构设计成一个对象,
* 由一个状态值success来表示是否通过handler的校验,success为false时应再次执行并且获取用户输入 */
rl.question(question, async (ans)=>{
const handleResult = handler(ans)
if (handleResult.success){
rl.close()
res(handleResult.value)
} else {
//handleResult.success为false时,handleResult.value是handler中设置的错误提示
rl.close()
const rejecthandle = await getQuestionResult(handleResult.value,handler)
res(rejecthandle)
}
})
})
}
// 这里创建一个generator实例,我觉得generator的yield单向有序的特性很适合我这个需求
function*gen(){
function getChangeSettingsFlag(ans){
return ans==="Y"?{success:true,value:true}:{success:true,value:false}
}
const getPath = function (ans) {
/**
* @description 验证路径(是否是目录)
* @param {String} path
*/
const validatePath = function (path) {
try {
// node10.x及以下版本不支持readdirSync,需要你需要这种写法,在运行之前需要切换node版本
const dir = fs.readdirSync(path)
if (dir) {
return {success:true,value:path}
}
} catch(err){
return {success:false,value:"提供的地址不合理,请重新输入:"}
}
}
return validatePath(ans)
}
// yield并不会返回值,这里声明的changeSettingFlag的值实际上是接收的next方法的参数
const changeSettingFlag = yield getChangeSettingsFlag
const settings = {
volumeSize: 10,
dirName: "新建分卷"
}
// 改变预设
if (changeSettingFlag){
const volumeSize = yield function(volumeSize){
return Number(volumeSize)>0&&Number(volumeSize)!==Infinity?{success:true,value:volumeSize}:{success:false,value:"输入的数字不合理,请重新输入:"}
}
settings.volumeSize = Number(volumeSize)||settings.volumeSize
const dirName = yield function(dirName){
return dirName.trim()?{success:true,value:dirName}:{success:false,value:"输入的目录名不合理,请重新输入:"}
}
settings.dirName = dirName.trim()||settings.dirName
}
// 接收路径
const pathInfo = {
input: "",
output: ""
}
const inputPath = yield getPath
pathInfo.input = inputPath;
const outputPath = yield getPath
pathInfo.output = outputPath;
const conf = {
pathInfo,
settings
}
console.log("conf",conf)
yield conf
}
// run it
async function workflow(generator){
const func0 = generator.next().value
const changeSettingFlag = await getQuestionResult("当前预设置如下:\n\t输出的分卷名:“新建分卷”;\n\t容量:10话/卷;\n希望调整预设吗?(Y/n) ",func0)
let getvolumeSize,getdirName
if (changeSettingFlag){
const func1 = generator.next(changeSettingFlag).value
getvolumeSize = await getQuestionResult("期望的卷容量(话/卷)是: ",func1)
const func2 = generator.next(getvolumeSize).value
getdirName = await getQuestionResult("期望的分卷名是:",func2)
}
const func3 = generator.next(getdirName).value
const inputPath = await getQuestionResult("选择的源路径是:",func3)
const func4 = generator.next(inputPath).value
const outputPath = await getQuestionResult("期望的输出路径是:",func4)
const conf = generator.next(outputPath).value
// 当前计数,通过在文件名中添加count来保持排序
let currentCount = 0;
// 当前分卷
let currentVolume = 0;
/**
* @param {String} path
* @param {String} newFolderName
*/
async function letsdance(path,newFolderName="") {
const childs = fs.opendirSync(path)
let chunkNum = 0 let newFolderPath = newFolderName
for await (const dirent of childs) {
if (dirent.isDirectory()) {
// 填充满一个目录之后创建一个新目录
if (currentVolume%conf.settings.volumeSize===0) {
chunkNum+=1;
newFolderPath = conf.pathInfo.output+"/"+conf.settings.dirName+"_"+chunkNum
fs.mkdirSync(newFolderPath)
// 如果你不希望命名后缀一直递增,也可以在新建目录之后把currentCount重新置为0
}
currentVolume+=1
const nextLevelPath = path+"/"+dirent.name
letsdance(nextLevelPath,newFolderPath)
} else if (dirent.isFile()){
currentCount += 1
const extName = dirent.name.split(".").reverse()[0]
const targetFilePath = path+"/"+dirent.name
const newFileName = newFolderPath+"/"+currentCount+"."+extName
fs.copyFileSync(targetFilePath,newFileName)
}
}
}
letsdance(conf.pathInfo.input)
}
const g = gen()
workflow(g)
运行这个脚本,如果我有两个目录,需要将他们之中的文件复制到一个新目录来实现合并的效果的话,在讲第一个目录的文件按原顺序命名为1-n之后。第二个目录的文件则会从n+1开始命名,效果如下:


使用nodejs进行了简单的文件分卷工具的更多相关文章
- java简单的文件读写工具类
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedRead ...
- 用nodejs搭建一个简单的服务器
使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...
- 拿nodejs快速搭建简单Oauth认证和restful API server攻略
拿nodejs快速搭建简单Oauth认证和restful API server攻略:http://blog.csdn.net/zhaoweitco/article/details/21708955 最 ...
- 用nodejs搭建一个简单的服务监听程序
作为一个从业三年左右的,并且从事过半年左右PHP开发工作的前端,对于后台,尤其是对以js语言进行开发的nodejs,那是比较有兴趣的,虽然本身并没有接触过相关的工作,只是自己私下做的一下小实验,但是还 ...
- 利用 nodeJS 搭建一个简单的Web服务器(转)
下面的代码演示如何利用 nodeJS 搭建一个简单的Web服务器: 1. 文件 WebServer.js: //-------------------------------------------- ...
- nodejs创建一个简单的web服务
这是一个突如其来的想法,毕竟做web服务的框架那么多,为什么要选择nodejs,因为玩前端时,偶尔想调用接口获取数据,而不想关注业务逻辑,只是想获取数据,使用java或者.net每次修改更新后还要打包 ...
- 使用jsp/servlet简单实现文件上传与下载
使用JSP/Servlet简单实现文件上传与下载 通过学习黑马jsp教学视频,我学会了使用jsp与servlet简单地实现web的文件的上传与下载,首先感谢黑马.好了,下面来简单了解如何通过使用 ...
- Mac OS环境下媒体文件分割工具mediafilesegmenter的简单使用(生成M3U8 TS文件)
mediafilesegmenter是苹果开发的一款用于分割媒体文件的工具,其功能与mediastreamsegmenter相似,但操作更简单. * 具体可以对比博客中的另一篇简介<Mac OS ...
- Spring简单的文件配置
Spring简单的文件配置 “计应134(实验班) 凌豪” 一.Spring文件配置 spring至关重要的一环就是装配,即配置文件的编写,接下来我按刚才实际过程中一步步简单讲解. 首先,要在web. ...
随机推荐
- LINUX - 最简单的CS通信实例
服务端[编译:gcc server.c -o server] #include <stdio.h> #include <sys/socket.h> #include <s ...
- 实现基于股票收盘价的时间序列的统计(用Python实现)
时间序列是按时间顺序的一组真实的数字,比如股票的交易数据.通过分析时间序列,能挖掘出这组序列背后包含的规律,从而有效地预测未来的数据.在这部分里,将讲述基于时间序列的常用统计方法. 1 用rollin ...
- universities
- C++ part8
1.volatile关键字 在C++中,对volatile修饰的对象的访问,有编译器优化上的副作用: 不允许被编译器优化,提供特殊地址的稳定访问(只从内存中读取). 有序性,编译器进行优化时,不能把对 ...
- HDU 6704 K-th occurrence(主席树 + RMQ + 后缀数组)题解
题意: 给一个串\(S\),\(length\leq 1e5\),\(Q\leq1e5\)个询问,每次询问输出和\(S_lS_{l+1}\dots S_r\)长得一模一样的第\(k\)个子串的开头位置 ...
- HDU 6155 Subsequence Count(矩阵 + DP + 线段树)题解
题意:01串,操作1:把l r区间的0变1,1变0:操作2:求出l r区间的子序列种数 思路:设DP[i][j]为到i为止以j结尾的种数,假设j为0,那么dp[i][0] = dp[i - 1][1] ...
- Java中的Lambda匿名函数后续
函数式编程(函数式接口):一个接口只包含一个方法实现 public interface Lambda{ void method(); } // 调用 Lambda lambda = new Lambd ...
- Emacs和Vim:神的编辑器和编辑器之神, 到底哪个更好?
Emacs和Vim:神的编辑器和编辑器之神, 到底哪个更好? 在这个蔚蓝色的星球上,流传着两大神器的传说:据说Emacs是神的编辑器,而Vim是编辑器之神. 一些人勇敢地拾起了Vim或Emacs,却发 ...
- React Hooks vs React Class vs React Function All In One
React Hooks vs React Class vs React Function All In One React Component Types React Hooks Component ...
- DMCA Takedown Policy
DMCA Takedown Policy https://github.com/xgqfrms/xgqfrms/issues/46 https://help.github.com/en/github/ ...