文件编码问题
1、node
在读取文件的时候是不支持读取GBK
编码的文件,一般都是utf8
,所以有的时候我们需要读取GBK
文件时,可以借助第三方插件iconv-lite
来转换成我们所需要的编码形式。
- 1、https://www.npmjs.com/package/iconv-lite 首先去官网下载
iconv-lite
这个模块,然后用require
引入该模块。只要是文件操作,都要引用fs
和path
两个模块
/**
* Created by 黄森 on 2017/6/7.
*/
const fs = require('fs');
const path = require('path');
const iconv = require('iconv-lite');
fs.readFile(path.join(__dirname,'./血染的风采.lrc'),(error,data)=>{
//decode中两个参数,第一个为你要转化的buffer,第二个为你要转化的编码方式
console.log(iconv.decode(data,'GBK'));
// console.log(data.toString('GBK'));
});
这样就可以将我们所读取的buffer转化成GBK
格式的文件,如果直接使用data.toString('GBK')
的话会提示这样的错误:
buffer.js:480
throw new TypeError('Unknown encoding: ' + encoding);
^
TypeError: Unknown encoding: gbk
at Buffer.slowToString (buffer.js:480:17)
at Buffer.toString (buffer.js:493:27)
at fs.readFile (F:\WebstormProjects\untitled\06.js:10:22)
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:446:3)
小小案例(动态显示歌词)
将lrc
的歌词按照时间顺序将对应的歌词在控制台显示
/**
* Created by 黄森 on 2017/6/7.
*/
// 动态显示歌词
//引入模块
const fs = require('fs');
const path = require('path');
const iconv = require('iconv-lite');
fs.readFile(path.join(__dirname,'./血染的风采.lrc'),(error,data)=>{
//按照换行分割歌词
var lines = iconv.decode(data, 'gbk').split('\n');
// console.log(lines.length);
//正则匹配歌词
var regex = /\[(\d{2})\:(\d{2})\.(\d{2})\]\s(.+)/;
//计时间差
var begin = new Date().getTime();
// 遍历
lines.forEach((line) => {
// [00:32.67] 也许我告别 将不再回来
var matches = regex.exec(line);
if (matches) {
var m = parseFloat(matches[1]);
var s = parseFloat(matches[2]);
var f = parseFloat(matches[3]);
var lyric = matches[4]; // 当前行歌词不是立即执行
// 由于下达输出任务的时刻不同
// 由于代码执行需要消耗时间,所以要减去执行时间
var offset = new Date().getTime() - begin;
setTimeout(() => {
console.log(lyric);
}, m * 60 * 1000 + s * 1000 + f - offset);
} else {
// 不是一行歌词
console.log(line);
}
});
});
但是这种方式是一下把所有的内容全部读取到内存中,文件比较大的话就会出现卡顿,node
就提供了一个读取单行文本的api
2、readline模块逐行读取文本
下面用readline
模块改版读取歌词
/**
* Created by 黄森 on 2017/6/7.
*/
// readline动态显示歌词
const fs = require('fs');
const path = require('path');
const iconv = require('iconv-lite');
const readline = require('readline');
var filename = path.join(__dirname, './../lyrics/血染的风采.lrc');
var streamReader = fs.createReadStream(filename)
.pipe(iconv.decodeStream('gbk'));
// 利用readline读取
var rl = readline.createInterface({ input: streamReader });
var begin = new Date().getTime();
rl.on('line', (line) => {
task(line, begin);
});
var regex = /\[(\d{2})\:(\d{2})\.(\d{2})\]\s(.+)/;
//输出歌词,抽出单独方法
function task(line, begin) {
// [00:32.67] 也许我告别 将不再回来
var matches = regex.exec(line);
if (matches) {
var m = parseFloat(matches[1]);
var s = parseFloat(matches[2]);
var f = parseFloat(matches[3]);
var lyric = matches[4]; // 当前行歌词不是立即执行
// 由于下达输出任务的时刻不同
var offset = new Date().getTime() - begin;
setTimeout(() => {
console.log(lyric);
}, m * 60 * 1000 + s * 1000 + f - offset);
} else {
// 不是一行歌词
console.log(line);
}
}
3、文件写入
异步文件写入
fs.writeFile(file,data[,option],callback(err))
同步文件写入
fs.writeFileSync(file,data,[,option])
流式文件写
fs.createWriteStream(path[,option])
默认写入操作是覆盖源文件
异步追加
fs.appendFile(file,data[,options],callback(err))
同步追加
fs.appendFileSync(file,data[,options])
- 1)文件异步写入
/**
* Created by 黄森 on 2017/6/7.
*/
const fs = require('fs');
const path = require('path');
//JSON.stringify({id:10})序列化
//JSON.parse 反序列化
fs.writeFile(path.join(__dirname,'./test.txt'),JSON.stringify({id:10}),(err)=>{
if(err){
//读文件是不存在报错
//意外错误
//文件权限问题
//文件夹找不到(不会自动创建文件夹)
console.log('error')
}else {
console.log('success');
}
});
fs.writeFile()
方法中系一个参数为路径,第二个参数是要写入的内容,第三个参数是回掉函数。JSON.stringify({id:10})
序列化,将一个对象转化为JSON
,JSON.parse
反序列化,将JSON转化为object
.
同步写入fs.writeFileSync();
和异步是一样的。
因为文件的写入是覆盖源文件,所以就又文件追加的这样一个需求,node
提供了fs.appendFile()
这样一个函数,可以在原有的基础上追加文件内容。里面的参数和fs.writeFile()
是一样的。
- 2)文件同步写入
fs.appendFileSync(file,data[,options])
,同步写入和异步是一样的,参数都相同
4、其他文件操作
重命名文件或目录/移动文件
fs.rename(oldPath,newPath,callback)
fs.renameSync(oldPath,newPath)
删除文件
fs.unlink(path,callback(err))
fs.unlinkSync(path)
验证路径是否存在(过时的API,用stat代替)
fs.exists(path,callback(exists))
fs.existsSync(path) // => 返回布尔类型 exists
获取文件信息
fs.stat(path,callback(err,stats))
fs.statSync(path) // => 返回一个fs.Stats实例
移动文件
fs.rename(oldPath,newPath)
对目录的操作
创建一个目录
fs.mkdir(path[,model],callback)
fs.mkdirSync(path[,model])
删除一个空目录
fs.rmdir(path,callback)
fs.rmdirSync(path)
读取一个目录
fs.readdir(path,callback(err,files))
fs.readdirSync(path) // => 返回files
案例:打印目录列表
/**
* Created by 黄森 on 2017/6/7.
*/
//打印当前目录所有文件
const fs = require('fs');
const path = require('path');
require('./proto.js'); //格式化时间的js
//获取当前有没有传入目标路径
var target = path.join(__dirname,process.argv[2] || './');
fs.readdir(target,(error,files)=>{
files.forEach(files=>{
// console.log(path.join(target,files));
fs.stat(path.join(target,files),(err,stats)=>{
console.log(`${stats.mtime.format('yyyy/MM/dd HH:mm')}\t${stats.size}\t${files}`)
})
})
});
5、创建文件夹
/**
* Created by 黄森 on 2017/6/8.
*/
//创建文件夹
const fs = require('fs');
const path =require('path');
fs.mkdir(path.join(__dirname,'demo'));
文件夹路径过长,无法拷贝问题
监视文件变化:
fs.watchFile(filename[, options], listener(curr,prev))
options:{persistent,interval}
fs.watch(filename[,options][,listener])
利用文件监视实现自动 markdown 文件转换
https://github.com/chjj/marked
https://github.com/Browsersync/browser-sync
大文件拷贝
https://github.com/tj/node-progress
6、文件的拷贝
// 文件的复制
const fs = require('fs');
const path = require('path');
console.time('read');//计算时间
fs.readFile('C:\\Users\\iceStone\\Desktop\\1.iso', (err, data) => {
if (err) {
throw err
}
console.timeEnd('read');
console.time('write');
// 读取完文件拿到
fs.writeFile('C:\\Users\\iceStone\\Desktop\\2.iso', data, err=> {
if (err) {
throw err
}
console.timeEnd('write');
console.log('拷贝完成');
});
});
这种方式的话,文件太大,我们电脑的内存就会受不了,所以就会使用文件流的方式拷贝文件
// 文件流的方式的复制
const fs = require('fs');
const path = require('path');
// 创建文件的读取流,并没有读出正式的数据,开始了读取文件的任务()
var reader = fs.createReadStream('C:\\Users\\iceStone\\Desktop\\1.itcast');
// 磁盘: 7200转 6100转 转速越快 读写越快 资源消耗更大
fs.stat('C:\\Users\\iceStone\\Desktop\\1.itcast', (err, stats) => {
if (stats) {
var readTotal = 0;
reader.on('data', (chunk) => {
// chunk是一个buffer(字节数组)
console.log('读了一点 进度:' + ((readTotal += chunk.length) / stats.size * 100) + '%');
});
}
});
网友评论