文件系统fs

一、概述

Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:

var fs = require("fs")

API文档:http://www.runoob.com/nodejs/nodejs-fs.html

require(‘readline’) 模块提供了一个接口,用于从可读流(如 process.stdin)读取数据,每次读取一行。 它可以通过以下方式使用:

const readline = require('readline');

API文档:http://nodejs.cn/api/readline#readline_rl_write_data_key

1.异步和同步

Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。

// 同步读取
var data = fs.readFileSync('input.txt');
console.log("同步读取: " + data.toString());

// 异步读取
fs.readFile('input.txt', function (err, data) {
   if (err) {
       return console.error(err);
   }
   console.log("异步读取: " + data.toString());
});

2.打开文件

以下为在异步模式下打开文件的语法格式:

fs.open(path, flags[, mode], callback)

参数使用说明如下:
path - 文件的路径。
flags - 文件打开的行为。具体值详见下文。
mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。
callback - 回调函数,带有两个参数如:callback(err, fd)。
flags 参数可以是以下值:

Flag描述
r以读取模式打开文件。如果文件不存在抛出异常。
r+以读写模式打开文件。如果文件不存在抛出异常。
rs以同步的方式读取文件。
rs+以同步的方式读取和写入文件。
w以写入模式打开文件,如果文件不存在则创建。
wx类似 ‘w’,但是如果文件路径存在,则文件写入失败。
w+以读写模式打开文件,如果文件不存在则创建。
wx+类似 ‘w+’, 但是如果文件路径存在,则文件读写失败。
a以追加模式打开文件,如果文件不存在则创建。
ax类似 ‘a’, 但是如果文件路径存在,则文件追加失败。
a+以读取追加模式打开文件,如果文件不存在则创建。
ax+类似 ‘a+’, 但是如果文件路径存在,则文件读取追加失败。
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
  console.log("文件打开成功!");     
});

3.获取文件信息

fs.stat(path, callback)

参数使用说明如下:
path - 文件路径。
callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。
fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:

fs.stat('/Users/liuht/code/itbilu/demo/fs.js', function (err, stats) {
    console.log(stats.isFile());        //true
})

4.写入文件

以下为异步模式下写入文件的语法格式:

fs.writeFile(filename, data[, options], callback)

如果文件存在,该方法写入的内容会覆盖旧的文件内容。
参数使用说明如下:
path - 文件路径。
data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(流) 对象。
options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 ‘w’
callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。

5.读取文件

以下为异步模式下读取文件的语法格式:

fs.read(fd, buffer, offset, length, position, callback)

该方法使用了文件描述符来读取文件。
参数使用说明如下:
fd - 通过 fs.open() 方法返回的文件描述符。
buffer - 数据写入的缓冲区。
offset - 缓冲区写入的写入偏移量。
length - 要从文件中读取的字节数。
position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。

6.关闭文件

以下为异步模式下关闭文件的语法格式:

fs.close(fd, callback)

该方法使用了文件描述符来读取文件。
参数使用说明如下:
fd - 通过 fs.open() 方法返回的文件描述符。
callback - 回调函数,没有参数。

其他方法描述
fs.rename(oldPath, newPath, callback)文件重命名
fs.unlink(path, callback)删除文件
fs.readdir(path, callback)读取目录
fs.createReadStream(path[, options])返回ReadStream 对象读取大文件
fs.createWriteStream(path[, options])写大文件

二、实战

公司项目平时处理BUG积攒了大量的垃圾输出标记print语句,所以就想写个工具干掉这些垃圾语句,最近也是喜欢研究nodejs这种前后端通吃的语言,索性就拿来练练手:

// 删除文件中的特殊符号信息(删除print标记)
// 1.遍历当前目录,判断是否是文件
// 2.不是文件是目录,继续递归遍历
// 3.是文件,开始做特殊处理,一行一行读取,开始做处理
// 4.判断当前行内容中是否有print
// 5.有的话,读完文件后替换源文件,没有的话则跳过到下一个文件

const fs = require('fs')
const readline = require('readline')
const os = require('os')

//要处理的特殊字符
var special_chars = ['print']

console.log('当前执行目录:'+__dirname)

//列表当前目录中的文件
function listFile(_dir_name){
    fs.readdir(_dir_name,function(_err,_files){
        if(_err)
            return console.log(_err)

        if(!_files.length)
            return console.log(_dir_name + ' have no files to show! \n')

        _files.forEach(function(_file_name){
            if(filterFile(_file_name)){
                var full_name = _dir_name + '/' + _file_name
                fs.stat(full_name,function(_err,_stat){
                    if(_stat.isDirectory())
                        listFile(full_name)
                    else
                        dealFile(full_name)
                })
            }
        })
    })
}

// 拆分全路径下的路径和文件名
function splitPathFile(_full_name){
    if(_full_name == '')
        throw('splitPathFile _full_name is null')

    var __s = _full_name.split('/')
    var __file_name = __s[__s.length-1]
    var __path_name = ''

    if(__s.length > 1){
        for (var i = 0; i <= __s.length-2; i++) {
            __path_name = __path_name + __s[i] + '/'
        }
    }

    return [__path_name,__file_name]

}

// 处理文件
function dealFile(_full_name){
    console.log('dealFile:'+_full_name)

    var __is_special = false
    var __path_name = splitPathFile(_full_name)[0]
    var __file_name = splitPathFile(_full_name)[1]
    var __tmp_name = __path_name + __file_name + 'tmp.txt'
    var __output = fs.createWriteStream(__tmp_name)

    var rl = readline.createInterface({
        input : fs.createReadStream(_full_name),
        output : __output
    })

    rl.on('line',function(_line){
        // console.log('文件单行内容:'+_line)
        var __is = filterSpecialChar(_line)

        if(__is){
            __is_special = true
            console.log('__is_special = true')
        }else{
            __output.write(_line + os.EOL)
        }

    })

    rl.on('close',function(){
        console.log(_full_name + " is closed")

        if(__is_special){
            fs.unlink(_full_name,function(_err){
                if(_err){
                    return console.log(_err)
                }

                fs.rename(__tmp_name,_full_name,function(_err){
                    if(_err){
                        return console.log(_err)
                    }

                    console.log('文件处理完毕1:' + _full_name)

                })
            })
        }else{
            fs.unlink(__tmp_name,function(_err){
                if(_err){
                    return console.log(_err)
                }

                console.log('文件处理完毕2:' + _full_name)
            })
        }
    })
}

// 过滤特殊字符
function filterSpecialChar(_str){

    var __is = false
    _str = _str.trim()
    // console.log(_str.indexOf('print'))

    for(var i =0;i < special_chars.length;i++){
        if(_str.indexOf(special_chars[i]) == 0){
            return true
        }
    }

    return false
}

//过滤器,做文件过滤工作,例如.DS_Store文件
function filterFile(_file_name){
    if(_file_name.charAt(0) == '.')
        return false

    return true
}

listFile(__dirname)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值