zoukankan      html  css  js  c++  java
  • 每天学点node系列-fs文件系统(续)

    理想如果不向现实做一点点屈服,那么理想也将归于尘土。

    创建目录

    异步创建目录

    path<string> | <Buffer> | <URL>
    options <Object> | <integer>
      - recursive <boolean> 默认值: false。
      - mode <integer> Windows 上不支持。默认值: 0o777。
    callback <Function>
      - err <Error></Error>
    
    // fs.mkdir(path[, mode], callback)
    var fs = require('fs')
    fs.mkdir('sub', function(err){
        if(err) throw err
        console.log('创建目录成功')
    })
    

    执行结果:

    $ node 1.js
    创建目录成功
    

    同步创建目录

    path<string> | <Buffer> | <URL>
      - options <Object> | <integer>
      - recursive <boolean> 默认值: false。
    mode <integer> Windows 上不支持。默认值: 0o777。
    
    // fs.mkdirSync(path[, mode])
    var fs = require('fs')
    try{
        fs.mkdirSync('rock')
        console.log('创建目录成功')
    }catch(e){
        throw e
    }
    

    执行结果:

    $ node 1.js
    创建目录成功
    

    读取目录

    异步读取目录

    path<string> | <Buffer> | <URL>
    options <string> | <Object>
      - encoding <string> 默认值: 'utf8'。
      - withFileTypes <boolean> 默认值: false。
    callback <Function>
      - err <Error>
      - files <string[]> | <Buffer[]> | <fs.Dirent[]></Error>
    

    注意: files 是目录中的文件名的数组(不包括 '.' 和 '..')

    let fs = require('fs')
    fs.readdir('./sub', 'utf8', (err, files) => {
        if (err) console.log(err)
        console.log(files)
    })
    

    执行结果:

    $ node 1.js
    [ '1.css', 'index.html' ]
    

    同步读取目录

    path <string> | <Buffer> | <URL>
    options <string> | <Object>
      - encoding <string> 默认值: 'utf8'。设置为 'buffer',则返回的文件名是 Buffer 对象。
      - withFileTypes <boolean> 默认值: false。 设置为 true,则返回的结果将包含 fs.Dirent 对象。
    返回: <string[]> | <Buffer[]> | <fs.Dirent[]></boolean>
    
    let fs = require('fs')
    try {
        let result = fs.readdirSync('./sub', 'utf8')
        console.log(result)
    } catch (error) {
        console.log(error)
    }
    

    执行结果:

    $ node 1.js
    [ '1.css', 'index.html' ]
    

    遍历目录

    var fs = require('fs')
    var path = require('path')
    var getFilesInDir = function (dir) {
        var results = [path.resolve(dir)]
        var files = fs.readdirSync(dir, 'utf8')
        files.forEach(function (file) {
            file = path.resolve(dir, file)
            var stats = fs.statSync(file)
            if (stats.isFile()) {
                results.push(file)
            } else if (stats.isDirectory()) {
                results = results.concat(getFilesInDir(file))
            }
        })
        return results
    }
    var files = getFilesInDir('./api');
    console.log(files);
    

    注意:fs.readdirSync()只会读一层,所以需要判断文件类型是否目录,如果是,则进行递归遍历。

    执行结果:

    $ node 1.js
    [ 'C:\Users\Administrator\Desktop\api',
      'C:\Users\Administrator\Desktop\api\config.1.json',
      'C:\Users\Administrator\Desktop\api\config.json',
      'C:\Users\Administrator\Desktop\api\config16.json',
      'C:\Users\Administrator\Desktop\api\integral-consumpte'
    ...
    

    修改权限

    path <string> | <Buffer> | <URL>
    mode <integer>
    callback <Function>
      - err <Error>
    
    var fs = require('fs')
    fs.chmod('1.txt', '777', function (err) {
        if (err) {
            console.log(err)
        } else {
            console.log("change done")
        }
    })
    

    同步修改所有者

    path <string> | <Buffer> | <URL>
    mode <integer>
    
    var fs = require('fs')
    fs.chmodSync('./1.txt', '777')
    

    访问/权限检测

    path<string> | <Buffer> | <URL>
        mode <integer> 默认值: fs.constants.F_OK。
        callback <Function>
      - err <Error></Error>
    
    
    const fs = require('fs')
    const file = '1.txt';
    // 检查当前目录中是否存在该文件。
    fs.access(file, fs.constants.F_OK, (err) => {
        console.log(`${file} ${err ? '不存在' : '存在'}`);
    });
    // 检查文件是否可读。
    fs.access(file, fs.constants.R_OK, (err) => {
        console.log(`${file} ${err ? '不可读' : '可读'}`);
    });
    // 检查文件是否可写。
    fs.access(file, fs.constants.W_OK, (err) => {
        console.log(`${file} ${err ? '不可写' : '可写'}`);
    });
    // 检查当前目录中是否存在该文件,以及该文件是否可写。
    fs.access(file, fs.constants.F_OK | fs.constants.W_OK, (err) => {
    if (err) {
        console.error(
            `${file} ${err.code === 'ENOENT' ? '不存在' : '只可读'}`);
        } else {
            console.log(`${file} 存在,且它是可写的`);
        }
    });
    

    执行结果:

    $ node 1.js
    1.txt 存在
    1.txt 可读
    1.txt 可写
    1.txt 存在,且它是可写的
    

    不建议在调用 fs.open()、 fs.readFile() 或 fs.writeFile() 之前使用 fs.access() 检查文件的可访问性。 这样做会引入竞态条件,因为其他进程可能会在两个调用之间更改文件的状态。 相反,应该直接打开、读取或写入文件,如果文件无法访问则处理引发的错误。

    写入(不推荐)

    
    const fs = require('fs')
    const file = '1.txt'
    fs.access(file, (err) => {
        if (!err) {
            console.error(`${file} 已存在`)
            return
        }
        fs.open(file, 'wx', (err, fd) => {
            if (err) throw err
            writeMyData(fd)
        })
    })
    

    写入(推荐)

    const fs = require('fs')
    fs.open('1.txt', 'wx', (err, fd) => {
        if (err) {
            if (err.code === 'EEXIST') {
                console.error('1.txt 已存在')
                return
            }
            throw err
        }
        writeMyData(fd)
    })
    

    同步访问/权限检测

    path<string> | <Buffer> | <URL>
    mode <integer> 默认值: fs.constants.F_OK。
    

    注意: 如果可访问性检查失败,则抛出 Error。 否则,该方法将返回 undefined。

    try {
        fs.accessSync('./1.txt', fs.constants.R_OK | fs.constants.W_OK)
        console.log('可以读写')
    } catch (err) {
        console.error('无权访问')
    }
    

    删除目录

    异步删除目录

    path<string> | <Buffer> | <URL>
    callback <Function>
      - err <Error>
    

    注意:在文件(而不是目录)上使用 fs.rmdir() 会导致在 Windows 上出现 ENOENT 错误、在 POSIX 上出现 ENOTDIR 错误。

    var fs = require('fs')
    
    fs.rmdir('./rock', function(err){
        if(err) throw err
        console.log('目录删除成功')
    })
    

    同步删除目录

    path <string> | <Buffer> | <URL>
    
    var fs = require('fs')
    fs.rmdirSync('./rock')
    

    实用场景

    文件锁

    使用独占标记创建锁文件

    fs模块为所有需要打开文件的方法提供了一个x标记。这告诉操作系统这个文件应该以独占模式打开(O_EXCL)。当使用这个方法时,若这个文件存在,文件不能被打开。

    
    

    文件数据库

    策略是不断的追加记录,在处理的时候不断的覆盖原始记录。

    var fs = require('fs')
    var EventEmitter = require('events').EventEmitter
    var Database = function (path) {
        this.path = path
        // 数据库key/value映射表
        this._records = Object.create(null)
        this._writeStream = fs.createWriteStream(this.path, {
            encoding: 'utf8',
            flags: 'a'
        })
        this._load()
    }
    // 继承自EventEmitter,让它有可以监听事件、传递事件的功能
    Database.prototype = Object.create(EventEmitter.prototype)
    Database.prototype._load = function () {
        var stream = fs.createReadStream(this.path, { encoding: 'utf8' })
        var database = this
        var data = ''
        // 当输入流准备好时触发
        stream.on('readable', function () {
            data += stream.read()
            // 每一行是一组数据
            var records = data.split('
    ')
            data = records.pop()
            for (var i = 0; i < records.length; i++) {
                try {
                    var record = JSON.parse(records[i])
                    if (record.value == null) {
                        delete database._records[record.key]
                    } else {
                        database._records[record.key] = record.value
                    }
                } catch (e) {
                    database.emit('error', 'found invalid record:', records[i])
                }
            }
        })
        // 流处理完后发送load事件给消费者
        stream.on('end', function () {
            database.emit('load')
        })
    }
    let database = new Database('./sub/a.txt')
    database._writeStream.write('beep')
    
  • 相关阅读:
    SGU 271 Book Pile (双端队列)
    POJ 3110 Jenny's First Exam (贪心)
    HDU 4310 Hero (贪心)
    ZOJ 2132 The Most Frequent Number (贪心)
    POJ 3388 Japanese Puzzle (二分)
    UVaLive 4628 Jack's socks (贪心)
    POJ 2433 Landscaping (贪心)
    CodeForces 946D Timetable (DP)
    Android Studio教程从入门到精通
    Android Tips – 填坑手册
  • 原文地址:https://www.cnblogs.com/jingh/p/11166625.html
Copyright © 2011-2022 走看看