| open() - 打开文件
| close() - 关闭文件
| stat() - 文件信息
| read()、write() - 读文件数据并写入Buffer
| readFile()、readFileSync() - 读、写取文件,可以读图片并写出图片,但不能写流文件
| createReadStream()、createWriteStream() - 读/写文件流
| rename()、renameSync() - 修改文件或目录
| ftruncate() - 截断文件
| appendFile() - 将数据追加到文件中
| mkdir() - 创建/删除目录
| rmdir() - 删除空目录
| readDir()、readdirSync() - 读取目录下所有文件
|
| stat() - 文件信息
| utimes() - 修改文件时间
| watchFile() - 监视文件
| access() - 判断文件或目录权限
| link() - 硬链接
| unlink() - 删除文件链接
| symlink() - 符号链接
| readlink() - 读取链接源地址
| watchFile()、watch() - 侦听文件/文件夹内文件的变化

fs 模块引用

var fs = reuqire('fs');        // 加载文件模块

文件系统方法有异步和同步两种

1、readFile()与createReadStream()区别

    readFile是整个文件都读取完后在载入内存中,createReadStream()分片来读取内容块,直接读取完成,缓存与文件流的区别

open() 异步打开文件

open(文件路径, 打开方式(读/写),设置模式(读4/写2/执行1), callback(err, fd文件句柄)): 异步打开文件

    打开方式: r 读、 w 写

opensync(): 同步打开文件

Example:
    const fileName = path.resolve(__dirname, 'test.txt');
    fs.open(fileName, 'r', (err, fd) => {
        console.log(err);
        fs.close();
    })

close() 关闭一个文件

fs.close(fd, callback)

readFile()、readFileSync()

同步和异步读取文件

readFile('filename', [编码方式], callback)

缺点: readFile()是先将数据全部读入内存,文件大时候,读取效率低下,而createReadStream会把文件分割成小块,然后通过事件和来最后得到数据

注意: 编码方式不设置返回的是Buffer, 如果设置了utf-8返回的是字符串

Example:
    fs.readFile('./nodeJS学习笔记.txt', 'utf-8', function(err, data){
        if(err){
            console.log('文件读取错误')
        }
        else{
            var buf = new Buffer(data);        // 将读取到的数据转成Buffer
            console.log(buf.toString());    // 二进制转成字符串
        }                
    })

writeFile() 向文件写内容

可以使用readFile读图片并写出图片,但不能写流文件

writeFile(filename, data, [flag], callback(err)err不为真写入成功) 向文件写内容,文件不存在自动创建文件

writeFileSync同步

    filename: 路径加文件名, 如果文件不存在会创建一个文件**

    data: 写入的内容可以是字符串或二进制

    flag: 对文件怎么来操作,  'w' 清空后在写入  'a' 将新内容加到之后  {flag: 'w'}

    writeFileSync('文件名', '内容'): 同步写文件

Example: 
    var writeBuf = new Buffer(writeStr);

    fs.writeFile('./buffer/file/user.txt', writeStr, {flag: 'a'}, function(err){
        err ? console.log('文件写入失败') : console.log('文件写入成功');
    })

createReadStream(path, [options]): 读取文件流

fs模块允许你通过Stream来对数据进行读取操作,与readFile、writeFile不同是它对内存分配不是一次完成的.

options:
    { 
        flags: 'r',            // r只读 w写
        encoding: null,        // 字符编码 utf-8
        fd: null,
        mode: 0666,
        autoClose: true,    // 读完数据是否关闭文件描述符
        start: 0,            // 读取流的开始
        end: 300            // 读取流的结束
    }

Example: 
    var fs = require('fs');
    var rs = fs.createReadStream(path.resolve(basePath, 'test.txt'), {statr:100});
    var str = '';        // 存储读取的数据

    // 读取数据
    rs.on('data', (data)=>{
        str += data;
    })

    // 数据读取完成
    rs.on('end', ()=>{
        console.log('读取完成')
        console.log(str);            // 打印出读取数据
    })

    // 读取出错
    rs.on('error', (err) => {
        console.log(err);
    })

createWriteStream(文件路径, {options}): 可写数据流

write(): 写入内容, 把文件内容清空后在写入

end(): 关闭写入

    var fs = require('fs');
    var ws = fs.createWriteStream('./files/stream.txt');

    // 写入内容
    ws.write('内容加入到文件中', 'utf-8', function(){
        console.log(arguments);
    })
    ws.end(function(){

    })

rename() 修改文件或目录名

rename(oldPath, newPath, callback) 修改文件或目录名, renameSync同步

Example: 
    let oldName = path.resolve(basePath, 'newTest.txt');
    let newName = path.resolve(basePath, 'test.txt');
    fs.rename(oldName, newName, (err) => {
        if(err){
            console.log(err);
        }
        console.log('文件名修改成功')
    })

copyFile(f1, f2) 复制文件内容

copyFile('a.txt', 'b.txt');

ftruncate() 截断文件

ftruncate(文件路径, 第几个字符截断, callback) 截断文件, ftruncateSync同步

一个中文四个字节,英文两个字节

Example: 
    const basePath = __dirname;
    fs.open(path.resolve(basePath, 'test.txt'), 'r+', (err, fd)=>{
        if(err){
            console.log(err);
        }
        else{
            fs.truncate(fd, 400, (err)=>{        // 截取四百个字节
                var readNewFile = fs.readFile(fd, 'utf8', (err, data)=>{    // 读取文件
                    var buf = new Buffer(data);
                    console.log(buf.toString('utf-8'));        //
                    fs.close();
                });
            })
        }
    })

appendFile(): 将数据追加到文件中

appendFile(文件名, 加入内容): 异步地追加数据到一个文件,如果文件不存在则创建文件,与writeFile()中设置flag: 'a' 一样

Example: 
    fs.appendFile(path.resolve(basePath, 'append.txt'), '这是要加入的字符串', (err) => {
        console.log('complate');
    })

read() 指定的文件中读取数据,并写入缓存区buffer

read(fd, buffer, offset, length, position, callback): 读文件

// read(路径, 指定存到的缓存区, buf的开始, buf的结束, 文件读取的起启位置, callback)

Example: 
    var buf = new Buffer(6);
    fs.open(path.resolve(basePath, 'append.txt'), 'r', (err, fd) => {
        if(err){
            console.log(err);
            return false;
        }

        fs.read(fd, buf, 0, buf.length, 3, (err, bytesRead, buffer) => {
            var str = new Buffer(buffer);
            console.log(str.toString())
            console.log('bytesRead : ' + bytesRead);
        })
    })

write() 指定的文件中写数据

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

二、操作目录

mkdir(目录名, callback(err))、rmdir(): 创建/删除目录

fs.mkdir('js/lib', function(err){        // 可以连续创建子目录, 先创建js,并在js目录下在创建lib目录
    console.log(err)
})

rmdir(path, callback): 删除空目录

readdir(path, callback(err, files)): 获取目录下所有文件

eaddirSync()同步

files: 将目录下所有文件返回一个数组

fs.readdir(basePath, 'utf-8', (err, files) => {
    if(err){
        console.log('文件目录获取失败', err);
    }
    else{
        files.forEach(function(data){
            var buf = new Buffer(data);
            console.log(buf);       // 输出文件名的二进制
        })
    }
})

三、文件权限

chown() 文件所有者变更

fs.chown(文件名,uid,gid,回调函数);
fs.fchown(文件句柄fd,uid,gid,回调函数);
fs.lchown(链接路径,uid,gid,回调函数);    

chmod()文件权限变更

fs.chmod(文件名,mode,回调函数);
fs.fchmod(文件句柄,mode,回调函数);
fs.lchmod(链接路径,mode,回调函数);

stat() 文件信息

也可以判断文件是否存在

fs.stat(文件路径, 回调函数(err.fs.Stats对象)); 获取文件或目录下的文件详情
fs.fstat(文件句柄fd, 回调函数(err.fs.Stats对象)); 显示文件或文件系统状态
fs.lstat(链接路径, 回调函数(err.fs.Stats对象)); 显示文件或文件系统状态(符号链接)

stat(path, callback(err, stats)): 获取文件详情, statSync同步

    fs.stat(`${dir}/img/readText.txt`, function (err, stats) {
        console.log(stats);                    // stats类
        console.log(stats.isFile());        // true
    })

    stats.isFile() - 是否是文件
    stats.isDirectory() - 是否是目录
    stats.isBlockDevice() - 是否是块设备
    stats.isCharacterDevice() - 是否是是字符
    stats.isSymbolicLink() (仅对 fs.lstat() 有效) - 是否是软链接
    stats.isFIFO() - 是不是FIFO
    stats.isSocket() - 是不是Socket


Example: fileSystem目录下有两个文件, a.txt、main.js

    fs.readdir('./fileSystem', function(err, files){
        files.forEach(function(file){
            console.log(file)
            fs.stat('./fileSystem/'+file, function(erro, stats){
                console.log('是否是目录:' + stats.isDirectory());
                console.log('是否是文件:' + stats.isFile());
                console.log(stats);      // 输出所有文件的详情
            })
        })
    })

utimes() 修改文件时间

fs.utimes(文件路径,访问时间,新建时间,回调函数);
fs.futimes(文件句柄,访问时间,新建时间,回调函数);      

watchFile()监视文件

fs.watchFile(文件名,[options],listener_callback(当前文件的stats,改变前的stats));      
fs.unwatchFile(文件名);

access(path, [mode], callback): 也是判断文件或目录的权限

fs.constants.F_OK - path 文件对调用进程可见。 这在确定文件是否存在时很有用,但不涉及 rwx 权限。 如果没指定 mode,则默认为该值。
fs.constants.R_OK - path 文件可被调用进程读取。
fs.constants.W_OK - path 文件可被调用进程写入。
fs.constants.X_OK - path 文件可被调用进程执行。 对 Windows 系统没作用(相当于 fs.constants.F_OK)

四、链接文件操作

创建一个硬链接

fs.link(srcpath, dstpath, [callback]): 硬链接 

fs.symlink(destination, path, [type], [callback]): 符号链接

读取链接指向的路径

fs.readlink(path, [callback(err,linkstr)]): 读取链接源地址 

fs.unlink(path,[callback]); 删除文件链接

watchFile()、watch(): 侦听文件/文件夹内的文件的变化

unwatchFile(): 停止侦听

// 侦听文件
fs.watch('./buffer/file/password.txt', {encoding: 'buffer'}, (eventType, filename) => {
    console.log(eventType, filename);
    if (filename){
        console.log(filename);
    }
});

// 向password.txt写内容
fs.writeFile('./buffer/file/password.txt', '添加新内容', {flag: 'a'}, function(err, data){
    if(!err){
        console.log('写入成功');
    }
})