0%

操作文件系统fs

同步方法与异步方法

  • fs模块中,所有操作都可以使用同步与异步方法,带有Sync后缀的方法为同步方法

文件读写操作

文件的完整读写

  • 读文件可以使用readFile方法和readFileSync方法

    1
    fs.readFile(filename, [options], callback)

    options中包含内容:
    flag属性:
    ‘r’:读取文件,如果文件不存在则抛出异常。
    ‘r+’:读取并写入文件,如果文件不存在则抛出异常。
    ‘rs’:以同步方式读取文件并通知操作系统忽略本地文件系统缓存,如果文件不存在则抛出异常。由于该属性值的使用将使操作系统忽略本地文件系统缓存机制,因此在操作网络文件系统时建议使用该属性值,但由于其对性能产生一定的负面影响,所以在其他场合下不建议使用。
    ‘w’:写入文件。如果文件不存在则创建该文件,如果该文件已存在则清空文件内容。
    ‘wx’:作用与’w’类似,但是以排他方式写入文件。
    ‘w+’:读取并写入文件。如果文件不存在则创建该文件,如果该文件已存在则清空文件内容。
    ‘wx+’:作用与’w+’类似,但是以排他方式打开文件。
    ‘a’:追加写入文件,如果文件不存在则创建该文件。
    ‘ax’:作用与’a’类似,但是以排他方式写入文件。
    ‘a+’:读取并追加写入文件,如果文件不存在则创建该文件。
    ‘ax+’:作用与’a+’类似,但是以排他方式打开文件。
    encoding属性:
    utf8、ascii、base64

    1
    2
    3
    4
    5
    6
    7
    8
    var fs = require('fs')
    fs.readFile('./demo.txt', function(err, data) {
    if (err) {
    console.log(err)
    } else {
    console.log(data.toString())
    }
    })

    还可以用下面这种写法

    1
    2
    3
    4
    5
    6
    7
    8
    var fs = require('fs')
    fs.readFile('./demo.txt','utf8', function(err, data) {
    if (err) {
    console.log(err)
    } else {
    console.log(data)
    }
    })

    同步的写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var fs = require('fs')
    try {
    var data = fs.readFileSync('./demo.txt', 'utf8')
    // 这么写也可以
    // var data = fs.readFileSync('./demo.txt', {encoding: 'utf8'})
    console.log(data)
    } catch (err) {
    console.log(err)
    }
  • 写方法writeFilewriteFileSync

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

    options参数可以使用以下属性:
    flag属性:用于指定对该文件采取何种操作,默认值为’w’(文件不存在时创建该文件,文件已存在时重写该文件),可指定值及其含义与readFile方法中使用的options参数值中的flag属性的可指定值及其含义相同。
    mode属性:用于指定当文件被打开时对该文件的读写权限,默认值为0666(可读写)。该属性值及fs模块中的各方法中的mode参数值的指定方法均如下所示:使用4个数字组成mode属性值或?mode参数值,其中第一个数字必须是0,第二个数字用于规定文件或目录所有者的权限,第三个数字用于规定文件或目录所有者所属用户组的权限,第四个数字规定其他人的权限。可以设定的数字如下所示:
    1:执行权限
    2:写权限
    4:读权限
    如果需要读写等复合权限可以做加法,比如读写权限是6
    encoding属性:
    用于指定使用何种编码格式来写入该文件。可指定属性值为“utf8”、“ascii”与“base64”。当data参数值为一个Buffer对象时该属性值被忽略,使用默认编码格式utf8来执行文件的写入。

    1
    2
    3
    4
    5
    6
    7
    8
    var fs = require('fs')
    fs.writeFile('./demo.txt','这是第一行\r这是第二行',function (err) {
    if(err) {
    console.log(err)
    }else {
    console.log('写入成功')
    }
    })

    将缓存区写入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var fs = require('fs')
    var buf = new Buffer('啦啦啦')
    fs.writeFile('./demo.txt',buf,function (err) {
    if(err) {
    console.log(err)
    }else {
    console.log('写入成功')
    }
    })

    图片复制

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var fs = require('fs')
    fs.readFile('./demo.jpg',function (err, data) {
    fs.writeFile('./demo1.jpg',data,function (err) {
    if(err) {
    console.log(err)
    }else{
    console.log('图片复制成功')
    }
    })
    })

    另一种写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var fs = require('fs')
    fs.readFile('./demo.jpg','base64',function (err, data) {
    fs.writeFile('./demo1.jpg',data,'base64',function (err) {
    if(err) {
    console.log(err)
    }else{
    console.log('图片复制成功')
    }
    })
    })

    同步方法

    1
    fs.writeFileSync(filename,data,[options])
  • 在文件底部添加数据appendFileappendFileSync

    1
    fs.appendFile(filename,data,[options],callback)

    options参数作用与指定方法大致相同,flag属性默认值为’a’

    1
    2
    3
    4
    5
    6
    7
    8
    var fs = require('fs')
    fs.appendFile('./demo.txt','这是添加的数据',function (err) {
    if(err) {
    console.log(err)
    }else{
    console.log('success')
    }
    })

    同步方法

    1
    fs.appendFileSync(filename, data, [options])

    从指定位置开始读写文件

  • 使用openopenSync方法

    1
    fs.open(filename, flags, [mode], callback)

    flags、mode与readFile中options的flags、mode相同

    1
    2
    3
    4
    5
    6
    7
    8
    var fs = require('fs')
    fs.open('./demo.txt', 'r', function (err,fd) {
    if(err) {
    console.log(err)
    }else {
    console.log(fd)
    }
    })

    同步的方法

    1
    var fd = fs.openSync(filename,flags,[mode])
  • 在打开文件后可以使用readreadSync方法从文件的指定位置读取文件,从指定位置开始读取,一直读取到文件底部,然后将读取到的内容输出到一个缓存区中

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

    fd为open返回的藐视,buffer为指定将文件读取到哪个缓存区中,offset为指定向缓存区中写入数据时开始写入位置(字节为单位),length指定从文件中读取的字节数,position指定读取文件时的开始位置(字节为单位)
    callback如下

    1
    function (err,bytesRead,buffer){}

    bytesRead为世界读取字节数,buffer为被读取得缓存对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var fs = require('fs')
    var buf = new Buffer(255)
    fs.open('./demo.txt', 'r', function (err,fd) {
    if(err) {
    console.log(err)
    }else {
    fs.read(fd, buf, 0, 9, 6, function (err,byte,buffer) {
    console.log(buffer.slice(0,byte).toString())
    })
    }
    })
  • 打开文件后可以使用fs.write方法或writeSync方法从一个缓存区中读取数据并且从文件的指定处开始写入这些数据

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

    callback方法如下图

    1
    function (err, written, buffer){}

    written代表被写入的字节数

  • close关闭文件

    1
    fs.close(fd,[callback])
  • fsync对文件进行同步操作,将内存缓冲区中的剩余数据全部写入文件

    1
    fs.fsync(fd, [callback])

创建与读取目录

创建目录

  • 使用mkdir方法
    1
    fs.mkdir(path, [mode], callback)

    path用于指定该目录的权限,默认值为0777
    同步方法

1
2
3
4
5
fs.mkdirSync(path, [mode])
```
#### 读取目录
```js
fs.readdir(path,callback)

回调函数

1
function (err,files){}

同步方法

1
fs.readdirSync(path)

查看修改文件或目录信息

查看文件或目录的信息

  • 使用stat方法和lstat方法

    1
    2
    fs.stat(path, callback)
    fs.lstat(path, callback)//查看符号链接文件的信息时,必须使用此方法

    回调

    1
    function (err, stats) {}

    stats参数为有一个fs.Stats对象,拥有如下方法
    isFile方法:用于判断被查看的对象是否为一个文件,如果是的话则返回true,如果不是的话则返回false。
    isDirectory方法:用于判断被查看的对象是否为一个目录,如果是的话则返回true,如果不是的话则返回false。
    isBlockDevice方法:用于判断被查看的文件是否为一个块设备文件,如果是的话则返回true,如果不是的话则返回false,该方法仅在UNIX操作系统下有效。
    isCharacterDevice方法:用于判断被查看的文件是否为一个字符设备文件,如果是的话则返回true,如果不是的话则返回false,该方法仅在UNIX操作系统下有效。
    isSymbolicLink方法:用于判断被查看的文件是否为一个符号链接文件,如果是的话则返回true,如果不是的话则返回false,该方法仅在lstat方法的回调函数中有效。
    isFIFO方法:用于判断被查看的文件是否为一个FIFO文件,如果是的话则返回true,如果不是的话则返回false,该方法仅在UNIX操作系统下有效。
    isSocket:用于判断被查看的文件是否为一个socket文件,如果是的话则返回true,如果不是的话则返回false,该方法仅在UNIX操作系统下有效。
    拥有的属性:
    dev:该属性值为文件或目录所在设备ID,该属性值仅在UNIX操作系统下有效。
    ino:该属性值为文件或目录的索引编号,该属性值仅在UNIX操作系统下有效。
    mode:该属性值为使用数值形式代表的文件或目录的权限标志。
    nlink:该属性值为文件或目录的硬连接数量。
    uid:该属性值为文件或目录的所有者的用户ID,该属性值仅在UNIX操作系统下有效。
    gid:该属性值为文件或目录的所有者的组ID,该属性值仅在UNIX操作系统下有效。
    rdev:该属性值为字符设备文件或块设备文件所在设备ID,该属性值仅在UNIX操作系统下有效。
    size:该属性值为文件尺寸(即文件中的字节数)。
    atime:该属性值为文件的访问时间。
    mtime:该属性值为文件的修改时间。
    ctime:该属性值为文件的创建时间。

  • 在打开文件后可以使用fstat方法查询信息

    1
    fs.fstat(fd, callback)
  • exists检查一个文件或目录是否存在

    1
    fs.exists(path, callback)
    1
    function (exists) {}
  • 获取文件或目录的绝对路径

    1
    fs.realpath(path, [cache], callback)

    path为完整路径,cache为预先指定的路径

    1
    2
    3
    varcache = {'/etc': '/private/etc'}
    fs.realpath('/etc/passwd', cache, function(err, resolvedPath) {//回调函数代码略
    })
    1
    2
    3
    4
    jvar fs = require('fs')
    fs.realpath('./demo.txt', function(err, resolvedPath) {
    console.log(resolvedPath)
    })
  • 修改文件访问时间及修改时间

    1
    fs.utimes(path,atime,mtime,callback)

    atime用于指定修改后的访问时间
    mtime参数指定修改后的修改时间

  • 使用open打开后修改访问及修改时间

    1
    fs.futimes(fd,atime,mtime,callback)
  • 修改文件或目录的读写权限

    1
    fs.chmod(path, mode, callback)

    mode指定修改后的读写权限


可对文件或目录执行的其他操作

移动文件或目录

  • rename
    1
    fs.rename(oldPath, newPath, callback)
    1
    2
    3
    4
    5
    6
    var fs = require('fs')
    fs.rename('./demo.txt', '../lalala.txt', function (err){
    if(err) {
    console.log('移动失败')
    }
    })

    创建与删除文件的硬链接

  • 硬链接:在操作系统中,一个文件被创建之后就拥有了一个文件名,因此该文件的硬链接数量为1。但是我们可以通过某种特殊的操作为该文件再指定一个文件名,而这种特殊的操作称为对该文件创建硬链接。在对该文件创建一个硬链接之后,虽然表面上看起来拥有了两个不同的文件,但是在硬盘中这两个文件只不过是同一个文件的多个硬链接,如果修改一个文件中的内容再打开另一个文件,就会看见另一个文件中的内容也被修改。
  • link方法可以创建硬链接
    1
    fs.link(srcpath,dstpath,callback)

    srcpath用于被创建
    dstpath新创建

    1
    2
    3
    4
    5
    6
    7
    8
    var fs = require('fs')
    fs.link('./lalala.txt','../demo.txt',function (err) {
    if(err) {
    console.log(err)
    }else {
    console.log('创建成功')
    }
    })
  • unlink用于删除文件硬链接
    1
    fs.unlink(path, callback)

    如果删除的是最后一个硬链接就相当于删除文件

    创建与查看符号链接

  • 符号链接,是一种特殊的文件,这个文件中仅包含了另一个文件或目录的路径及文件名或目录名。如果打开一个文件的符号链接文件进行编辑,操作系统将自动打开符号链接中所指向的原文件进行编辑,如果打开一个目录的符号链接文件进行文件的创建、编辑或删除操作,则操作系统将自动打开符号链接中所指向的原目录并执行相应的操作。如果删除符号链接文件,不会删除原文件或目录,如果删除或移动原文件或目录,符号链接文件也不会被删除,这时产生一种称为“断链”的现象。
  • 使用symlink方法来创建文件或目录符号链接
    1
    fs.symlink(srcpath, dstpath, [type], callback)

    srcpath为被创建路径
    dstpath为创建的路径
    type指定为文件还是目录创建,file为文件,dir为目录(非win只有dir),junction为目录

  • 读取符号链接中的文件或目录的路径
    1
    fs.readlink(path,callback)
    1
    function (err,linkString){}

截断文件

  • 使用truncate方法对文件进行截断操作(先清除文件内容,然后修改文件尺寸)
    1
    fs.truncate(filename, len, callback)

    len的单位为字节

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var fs = require('fs')
    fs.truncate('./lalala.txt', 10, function (err) {
    if(err) {
    console.log(err)
    } else {
    console.log('分隔成功')
    }
    fs.stat('./lalala.txt', function(err, stat) {
    if (err) {
    console.log(err)
    } else {
    console.log(stat.size)
    }
    })
    })

删除空目录

  • rmdir方法可以删除空目录
    1
    fs.rmdir(path, callback)

监视文件或目录

  • 使用watchFile方法可以监视文件,监视到文件被修改时执行某些处理
    1
    js.watchFile(filename, [options], listener)

    option:options参数值为一个对象,可以在其中使用一个布尔类型的persistent属性值来指定当指定了被监视的文件后是否停止当前正在运行的应用程序,该属性的默认属性值为true;也可以在options参数值中使用一个整数类型的interval属性值来指定每隔多少毫秒监视一次文件是否发生改变以及发生了什么改变

    1
    function(cuur,prev){}

    curr参数为一个fs.Stats对象,代表被修改之后的当前文件,prev也是一个fs.Stats对象,代表被修改之前的文件

  • 使用watchFlie方法监视后,可以使用unwatchFile方法取消要执行的处理
    1
    fs.unwatchFile(filename, [listener])

    listener为要取消的回调函数,如果不指定则取消对该文件的监视

  • 使用watch方法对文件或目录进行监视
    1
    var watcher = fs.watch(filename, [options],[listener])

    options为一个对象,可以使用persistent属性指定当指定了被监视的文件后是否停止当前正在运行的应用程序

    1
    function(event,filename){}

    event为“rename”(当被指定的文件或被指定的目录中的任何文件被重命名、移动或删除时)或“change”(内容改变时)
    filename为发生改变的文件路径
    watch方法返回一个fs.FSWatcher对象,该对象有一个close方法,用于停止监视

    1
    warcher.close()

文件流

流的基本概念

  • 几种读写文件的区别
    • readFile:将文件完整读入缓存区(在执行期间node不能执行其他操作)
    • read:将文件部分读入缓存区(在执行期间node可以执行其他操作)
    • writeFile:将数据完整写入文件在执行期间node不能执行其他操作)
    • write:将缓存区中的部分内容写入文件(在执行期间node可以执行其他操作)
  • 当我们不关心整个文件的内容,只关注是否从文件中读取到了某些数据,以及在读取到这些数据时所需要执行的处理,这是我们可以使用node.js中的文件流来执行这一处理
  • 流的概念:在一个应用程序中,流是一组有序的、有起点和终点的字节数据的传输手段。在应用程序中各种对象之间交换与传输数据的时候,总是先将该对象中所包含的数据转换为各种形式的流数据(即字节数据),再通过流的传输,到达目的对象后再将流数据转换为该对象中可以使用的数据。
  • 可以使用flowing模式与非flowing模式来读取数据,flowing模式使用操作系统内部I/O机制读取数据,非flowing模式时,必须显示调用对象的read方法

使用ReadStream对象读取文件

  • 使用createReadStream方法创建一个将文件内容读取为流数据的ReadStream对象
    1
    fs.createReadStream(path, [options])

    options参数为一个对象,包含如下属性:
    flags:用于指定对该文件采取什么操作,默认值为’r’,可指定属性值与readFile方法中所使用的options参数对象中所使用的flags属性的可指定属性值相同。
    encoding:用于指定使用什么编码格式来读取该文件,可指定属性值为“utf8”、“ascii”与“base64”。默认值为null。
    autoClose:用于指定是否关闭在读取文件时操作系统内部使用的文件描述符。如果属性值设定为false,则文件不会自动关闭,即使在读取文件过程中产生了错误,开发者也必须通过使用close方法或closeSync方法来手动关闭文件。如果属性值设定为true,当文件读取完毕或读取文件过程中产生错误时文件将自动关闭。autoClose属性的默认属性值为true。
    start:使用整数值来指定文件的开始读取位置(单位为字节数)。
    end:使用整数值来指定文件的结束读取位置(单位为字节数)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var fs = require('fs')
    var file = fs.createReadStream('./lalala.txt',{start: 0, end:23})
    file.on('open', function (fd) {
    console.log('文件开始读取,fd为:'+fd)
    })
    file.on('data',function (data) {
    console.log('读取到数据' + data)
    })
    file.on('end',function () {
    console.log('文件读取完毕')
    })
    file.on('close', function () {
    console.log('文件已关闭')
    })
    file.on('error',function (err) {
    console.log(err)
    })

    下面添加了暂停

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    var fs = require('fs')
    var file = fs.createReadStream('./lalala.txt',{start: 0, end:23})
    file.on('open', function (fd) {
    console.log('文件开始读取,fd为:'+fd)
    })
    file.pause()
    file.on('data',function (data) {
    console.log('读取到数据' + data)
    })
    file.on('end',function () {
    console.log('文件读取完毕')
    })
    file.on('close', function () {
    console.log('文件已关闭')
    })
    file.on('error',function (err) {
    console.log(err)
    })
    setTimeout(function () {
    file.resume()
    },1000)

使用WriteStream写入文件

  • 使用createWriteStream创建将流数据写入文件中的WriteStream对象
    1
    fs.createWriteStream(path, [options])

    options参数为一个对象,包含以下内容
    flags:用于指定对该文件采取什么操作,默认值为’w’,可指定属性值与readFile方法中options参数对象的flags属性的可指定属性值相同。
    encoding:用于指定使用什么编码格式来读取该文件,可指定属性值为“utf8”、“ascii”与“base64”。默认值为null。
    start:使用整数值来指定文件的开始写入位置(单位为字节数)。如果要在文件中追加写入数据,需要将flags属性值设置为’a’。

  • WriteStream对象具有一个write方法,用于将数据写入到目标对象中
    1
    writable.write(chunk, [encoding], [callback])

    chunk:可以是一个Buffer对象或一个字符串,指定要写入的数据
    encoding:chunk为字符串时指定数据以何种编码方式写入文件
    write方法返回一个布尔类型的返回值,当系统缓存区满时值为false否则为true

  • end方法在写入文件的场合中,当没有数据再被写入流中时可以调用该方法关闭文件,这会迫使操作系统将缓存区中的剩余数据被立即写入文件中
    1
    writable.end([chunk], [encoding], [callback])

    chunk:一个Buffer对象或一个字符串,用于指定在文件关闭之前需要在文件总追加写入的数据
    encoding:当chunk为字符串时指定以什么编码方式追加写入文件

  • WriteStream对象具有bytesWritten属性,为当前已在文件中写入数据的字节数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var fs = require('fs')
    var file = fs.createReadStream('./from.txt')
    var write = fs.createWriteStream('./lalala.txt')
    write.on('open',function (fd) {
    console.log('需要写入的文件已打开,文件fd:'+fd)
    })
    file.on('data',function (data){
    write.write(data)
    console.log(data.toString())
    })
    file.on('end', function () {
    write.end(function (){
    console.log('写入完成,本次写入数据'+ write.bytesWritten)
    })
    })

    控制台同步输出写入数据,使用了write方法的回调

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var fs = require('fs')
    var file = fs.createReadStream('./from.txt')
    var write = fs.createWriteStream('./lalala.txt')
    write.on('open',function (fd) {
    console.log('需要写入的文件已打开,文件fd:'+fd)
    })
    file.on('data',function (data){
    write.write(data,function () {
    console.log(data.toString())//write方法回调
    })
    })
    file.on('end', function () {
    write.end(function (){
    console.log('写入完成,本次写入数据'+ write.bytesWritten)
    })
    })
  • WriteStream对象的write方法返回一个布尔类型的返回值,当操作系统缓存区中数据已全部写满时,该参数值为false,表示操作系统缓存区中的数据已满并将被立即输出到目标对象中,当操作系统缓存区中还可以写入数据时,该参数值为true。在Node.js中,当操作系统缓存区中数据已全部写满时,不代表不能继续写数据,而是指在将操作系统缓存区中的数据写入到文件中的同时把读取到的数据暂时缓存在内存中,待操作系统缓存区中数据已全部输出时首先将内存中缓存的数据读入操作系统缓存区中。当操作系统缓存区中的数据已被全部读出并写入到目标文件时,触发WriteStream对象的drain事件,表示操作系统缓存区中的数据已全部读出,可以继续向操作系统缓存区中写入新的数据。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var fs = require('fs')
    var out = fs.createWriteStream('./test1.txt')
    for (var i = 1; i <= 10000; i++) {
    var flag = out.write(i.toString())
    console.log(flag)
    }
    out.on('drain', function() {
    console.log('操作系统缓存区中的数据已全部输出。')
    var out = fs.createWriteStream('./test2.txt')
    for (var i = 1; i <= 10; i++) {
    var flag = out.write(i.toString())
    console.log(flag)
    }
    out.on('drain', function() {console.log('操作系统缓存区中的数据已全部输出。')})
    })
  • 观察drain事件的触发机制

    读取mp3文件时

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var fs = require('fs')
    var read = fs.createReadStream('./刚好遇见你.mp3')
    var write = fs.createWriteStream('./刚好遇见你2.mp3')
    read.on('data', function (data) {
    var flag = write.write(data)
    console.log(flag)
    })
    write.on('drain',function () {
    console.log('系统缓存区中内容已全部输出')
    })

    结果如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    false
    系统缓存区中内容已全部输出
    false
    系统缓存区中内容已全部输出
    false
    系统缓存区中内容已全部输出
    false
    系统缓存区中内容已全部输出
    false
    系统缓存区中内容已全部输出
    false
    ...
    false
    系统缓存区中内容已全部输出

    从这个结果中我们可以看出,在读取一个尺寸较大的文件时,操作系统将执行以下操作:
    1)首先读取该文件中的数据并把输入填入操作系统缓存缓存区,直到填满为止。
    2)不断执行把缓存区中数据写入目标文件,同时读取文件中剩余数据并把数据填入内存的操作,这时控制台中不断显示write方法的执行结果为false(代表操作系统缓存区已满)的情况。
    3)待操作系统缓存区中数据已全部被写入目标文件时,触发一次drain事件,在控制台中输出“操作系统缓存区中的数据已全部输出。”字符串。
    4)首先将内存内的数据写入到操作系统缓存区中,然后读取文件中的剩余数据并填入缓存区,一直到填满为止。
    5)重复执行步骤2到步骤4的操作。一直到文件中数据被读取完为止。

  • 使用WriteStream对象写入文件时,如果产生一个错误,触发WriteStream对象的error事件
    1
    writable.on('error', function (err) {})
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var fs = require('fs')
    var write = fs.createWriteStream('./from.txt')
    write.on('error',function (err) {
    console.log(err)
    console.log('出错了!')
    })
    write.write('写一些数据')
    write.end()
    write.write('lala')
  • 使用ReadStream对象的pipe方法执行文件的复制操作
    1
    readStream.pipe(destination,[options])

    destination:为一个可用于写入流数据的对象,写文件时为路径(貌似必须是对象,书上写的不清楚)
    options:为一个对象,end属性如果为true则当数据被全部读取完毕时,立即操作系统缓存区中的剩余数据全部写入文件中并关闭文件,如果为false,则不关闭文件,文件中可以写入新的数据,该属性的默认属性值为true

    1
    2
    3
    4
    var fs = require('fs')
    var read = fs.createReadStream('./from.txt')
    var write = fs.createWriteStream('./copy.txt')
    read.pipe(write)
  • 可以使用ReadStream对象的unpipe方法取消目标文件的吸入操作
    1
    readStream.unpipe([destination]);

对路径进行操作

  • 在Node.js中,提供了一个path模块在这个模块中提供许多实用的方法

    normalize方法

  • 该方法将非标准路径字符串转换为标准路径字符串,在转换过程中执行以下处理:
    1. 解析路径字符串中的’..’字符串与’.’字符串,返回解析后的标准路径。
    2. 将多个斜杠字符串转换为一个斜杠字符串,例如将’\’转换为’\’。
    3. 将Windows操作系统的反斜杠字符串转换为正斜杠字符串。
    4. 如果路径字符串以斜杠字符串结尾,则在转换后的完整路径字符串末尾保留该斜杠字符串
      1
      path.normalize(p)

join方法

  • 将多个参数值字符串结合为一个路径字符串
    1
    path.join([path1], [path2], [...])
    1
    2
    3
    var path  = require('path')
    console.log(path.join(__dirname,'a', 'b','c'))
    //Users/finup/code/node学习/#3/a/b/c

resolve方法

  • 以应用程序根目录为起点,根据所有的参数值字符串解析出一个绝对路径
    1
    path.resolve(path1, [path2], [...])
  • 解析过程如下:
    1. 以应用程序根目录为起点,解析第一个参数值字符串。
    2. 如果该参数值字符串不以“..”、“.”或“/”开头,则将参数值字符串解析为应用程序根目录下的某个子目录,将当前参考目录定为该子目录的绝对路径。例如应用程序根目录为Windows操作系统中的“d:\a\b”,第一个参数值字符串为“c”,则将当前参考目录定为“d:\a\b\c”。
    3. 如果该参数值字符串以“..”开头,则将“..”解析为应用程序根目录的上级目录,然后将“..”后的字符串解析为该目录下的某个子目录,将当前参考目录定为该子目录的绝对路径。例如应用程序根目录为Windows操作系统中的“d:\a\b”,第一个参数值字符串为“../c”,则将当前参考目录定为“d:\a\c”。
    4. 如果该参数值字符串以“.”开头,则将“.”解析为应用程序根目录的当前目录,即应用程序根目录,然后将“.”后的字符串解析为应用程序根目录下的某个子目录,将当前参考目录定为该子目录的绝对路径。例如应用程序根目录为Windows操作系统中的“d:\a\b”,第一个参数值字符串为“./c”,则将当前参考目录定为“d:\a\b\c”。
    5. 如果该参数值字符串以“_”开头,表示指定了一个绝对路径,则将当前参考目录定为该绝对路径,例如应用程序根目录为Windows操作系统中的“d:\a\b”,第一个参数值字符串为“_c”,则将当前参考目录定为“d:\c”。
    6. 如果没有下一个参数值字符串,则resolve方法返回当前参考目录的绝对路径。
    7. 如果存在下一个参数值字符串,则以当前参考目录为起点,解析下一个参数值字符串。
    8. 如果下一个参数值字符串不以“..”、“.”或“/”开头,则将参数值字符串解析为当前参考目录下的某个子目录,将当前参考目录转变为该子目录的绝对路径。例如当前参考目录为Windows操作系统中的“d:\a\b\c”,下一个参数值字符串为“d”,则将当前参考目录转变为“d:\a\b\c\d”。
    9. 如果下一个参数值字符串以“..”开头,则将“..”解析为当前参考目录的上级目录,然后将“..”后的字符串解析为该目录下的某个子目录,将当前参考目录转变为该子目录的绝对路径。例如当前参考目录为Windows操作系统中的“d:\a\c”,下一个参数值字符串为“../d”,则将当前参考目录转变为“d:\a\d”。
    10. 如果下一个参数值字符串以“.”开头,则将“.”解析为当前参考目录的当前目录,即当前参考目录,然后将“.”后的字符串解析为当前参考目录下的某个子目录,将当前参考目录转变为该子目录的绝对路径。例如当前参考目录为Windows操作系统中的“d:\a\b\c”,下一个参数值字符串为“./d”,则将当前参考目录转变为“d:\a\b\c\d”。
    11. 如果下一个参数值字符串以“_”开头,表示指定了一个绝对路径,则将当前参考目录转变为该绝对路径,例如当前参考目录为Windows操作系统中的“d:\c”,第一个参数值字符串为“_d”,则将当前参考目录转变为“d:\d”。
    12. 如果没有下一个参数值字符串,则resolve方法返回当前参考目录的绝对路径。
    13. 如果存在下一个参数值字符串,则继续执行步骤7~步骤13。
      1
      2
      var path  = require('path')
      console.log(path.resolve('a', 'b', 'c/message.txt'))

relative方法

  • 用于获取两个路径之间的相对关系
    1
    path.relative(from,to)

    返回将第一个路径视为当前路径,使用相对路径指示第二个路径的相对路径表达式

dirname方法

  • 用于获取一个路径中的目录名
    1
    path.dirname(p)

    当参数是目录路径时返回该目录的上层目录,当参数为文件路径时返回该文件所在目录

basename方法

  • 用于获取一个路径中的文件名
    1
    path.basename(p,[ext])

    p为文件路径,ext用于在方法返回的文件名中去除扩展名,因此该参数值必须等于p参数值中指定文件的扩展名

    1
    2
    3
    var path  = require('path')
    console.log(path.basename('./a/b/demo.html'))//demo.html
    console.log(path.basename('./a/b/demo.html','.html'))//demo

extname方法

  • 用于获取一个路径中的扩展名
    1
    path.extname(p)
    1
    2
    var path  = require('path')
    console.log(path.extname('./a/b/demo.html'))//.html

path.sep属性

  • 属性值为操作系统指定的文件分隔符,可能的属性值为“\”(win)或“/”(UNIX)

path.delimiter属性

  • 属性值为操作系统指定的路径分隔符,可能的属性值为”;”(win)或”:”(UNIX)
    #node