Nodejs file and stream

先来个题外话,听闻express的作者TJ大神已投入到Go的怀抱啦!真是遗憾啊,感谢大神对NodeJS社区的贡献.

File

文件操作对于一般的后端语言来说,是非常基础的功能,今天来说说NodeJS里的文件API,详情API地址可以看这里,官方文件API,本篇只说一些常用的方法



首先文件api在NodeJS里是唯一的一个具有同步和异步的方法调用,所有的文件相关的方法都在file模块内,这个是系统内置模块,请求方法如下

var fs = require('file');

接下来就可以测试文件API啦,先来一个常用的readFile方法

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

说到读文件,这里就要先讲讲NodeJS的路径问题

  • __dirname 程序目录
  • process.cwd() 代表程序当前工作目录
  • . 相对于程序路径的上级
  • .. 相对于程序路径的上上级

比如这里获取当前运行文件同级目录里的feenan.js,代码如下

fs.readFile(__dirname + '/feenan.js', 'utf8', function(err, data){
    // do stuff here
    if(!err){
        console.log(data);
    }
})

方法的第二个参数可以传递数据编码格式,这里设置utf8,最后一个参数是一个回调,当文件读取完毕的时候会调用,出错的话,err参数有值,否则为null,这时就可以对数据进行处理了.

这个方法对应的同步方法是readFileSync,一般同步方法就是在后面加上Sync

目前这个读取文件的方案,对于小文件还可以接受,但是大文件的话,则性能不是很好,因为这是一次性的分配文件内容大小的内存的,后面会讲到以流的方式来处理.

说完了读取文件,再来说说读取文件夹

fs.readdir(path, callback)

读取文件夹信息比较简单,传递目录路径,以及回调函数.

fs.readdir(__dirname, function(err, files){
    if(!err){
        files.forEach(function(v){
            console.log(v);
        })
    }
});

上面的主要说是读取当前程序所在目录下面的信息,回调函数的files是一个数组,里面存放目录列表的名字

这里当获取到目录列表的时候,想读取某个文件怎么办?怎么来区分哪个是目录哪个是文件呢?这里得讲下另外一个常用的api

fs.stat(path, callback)

上面的API是读取文件属性,这里的文件包括目录以及单个文件,直接来看个例子吧,对上面返回的文件数组进行过滤然后分别显示哪些是目录,哪些是文件

function file(i){
    var filename = files[i];
    fs.stat(__dirname + '/' + filename, function(err, stat){
        // 保存文件属性对象
        stats[i] = stat;
        if(err){
            console.log('file read error!');
        }else{
            if(stat.isDirectory()){
                console.log('目录名: ' + filename);
            }else{
                console.log('文件名: ' + filename);
            }
            i++;
            if(i === files.length){
                done();
            }else{
                file(i);
            }
        }
    });
}
file(0);

上面主要是用到了fs.stat返回的stat.isDirectory方法来检查是否是文件夹

最后贴一个完整的获取目录下的文件信息,并支持命令行输入索引来查看文件信息

var fs = require('fs');
var stdin = process.stdin,
    stdout = process.stdout;

// 异步调用获取当前工作目录下的列表
fs.readdir(__dirname, function(err, files){
    // 列出文件列表之后,提示输入想查看的内容
    var done = function(){
        console.log('');
        stdout.write('输入你的选择: ');
        stdin.resume();
        stdin.setEncoding('utf8');
        stdin.on('data', function(data){
            if(!files[+data]){
                stdout.write('输入你的选择: ');
            }else{
                stdin.pause();
                // 开始读取选择的文件夹或者文件
                var filename = files[+data];
                if(stats[+data].isDirectory()){
                    // 开始读取文件夹里的内容
                    fs.readdir(__dirname + '/' + filename, function(err, files){
                        if(!err){
                            console.log('');
                            console.log('(' + files.length  + '个文件' + ')');
                            files.forEach(function(v){
                                console.log('      -' + v);
                            })
                            console.log('');
                        }
                    });
                }else{
                    // 开始读取文件
                    fs.readFile(__dirname + '/' + filename, 'utf8',  function(err, data){
                        console.log('');
                        console.log(data.replace(/(.*)g/, '    $1'));
                    });
                }
            }
        });
    }
    var stats = [];
    if(!files.length){
        console.log('不存在任何文件列表!');
        return;
    }
    console.log('列出你想看的列表内容: ');
    function file(i){
        var filename = files[i];
        fs.stat(__dirname + '/' + filename, function(err, stat){
            // 保存文件属性对象
            stats[i] = stat;
            if(err){
                console.log('file read error!');
            }else{
                if(stat.isDirectory()){
                    console.log('目录名: ' + filename);
                }else{
                    console.log('文件名: ' + filename);
                }
                i++;
                if(i === files.length){
                    done();
                }else{
                    file(i);
                }
            }
        });
    }
    file(0);
});

Stream

刚才上面讲到了读取文件时的一个影响性能的地方,这里可以用流来处理,看看代码

var readstream = fs.createReadStream(__dirname + '/demo.js', { Encoding: 'utf8'});
var content = [];

readstream.on('data', function(data){
    content.push(data);
})

readstream.on('end', function(data){
    content.push(data);
    console.log(content.join(''));
})

上面用到了文件流里的createReadStream方法,参数如下

fs.createReadStream(path, [options])

选项里可以传入文件编码信息,更多参数可以参考官网API

然后这里的只读流对象提供了读取数据以及数据完成事件,这种方式跟上面的一次性读取内容的区别在于,内存是一块一块分配的,而不是一次性分配很大的内存,这种情况用在网络请求文件的时候,性能尤其明显

下面再来一个可写流,方法参数如下

fs.createWriteStream(path, [options])

var writestream = fs.createWriteStream(__dirname + '/demo.js', { Encoding: 'utf8'});
writestream.write('hello feenan!');

而且有一个方便的方法可以从只读流写入到可写流中,效率也是最好的

var readstream = fs.createReadStream(__dirname + '/demo.js', { Encoding: 'utf8'});
var writestream = fs.createWriteStream(__dirname + '/demo.js', { Encoding: 'utf8'});
readstream.pipe(writestream);

其实就是调用了流的pipe管道方法,确实人如其名:)

总结

文件与流都是file模块下面的API,用好这些方法,对构建前端自动化,编写网络服务程序都有很好的帮助!

时间: 2024-10-01 17:41:36

Nodejs file and stream的相关文章

Nodejs基础:stream模块入门介绍与使用

本文摘录自<Nodejs学习笔记>,更多章节及更新,请访问 github主页地址.欢迎加群交流,群号 197339705. 模块概览 nodejs的核心模块,基本上都是stream的的实例,比如process.stdout.http.clientRequest. 对于大部分的nodejs开发者来说,平常并不会直接用到stream模块,只需要了解stream的运行机制即可(非常重要). 而对于想要实现自定义stream实例的开发者来说,就得好好研究stream的扩展API了,比如gulp的内部实

Drupal中处理文件流File System和Stream Wrapper原理

在Drupal7以及PHP(也不知那个版本)后,多了一个概念:Stream,主要用来表示文件流.BTW,追溯起Stream的概念,这个应该很早在Java和C#等OOP的语言中已存在,PHP只是简单的封装了file/file_get_content等函数,使用起来方便,所以PHPer 们更少的在意stream以及整个底层的操作. 当我们使用一个完整的框架(如:drupal框架),drupal又更加完善了PHP中stream的概念和使用方式,使其更加OO,更加易用. 注意:PHP本身是支持Strea

Nodejs学习item【入门手上】_node.js

一. 安装 首先,去http://nodejs.org 下载安装.我下的版本是0.8.14.安装很简单,下一步下一步就哦了.然后在path中配置一下安装目录即可,msi会把npm(Node Package Manager)一并装上. 我的安装目录是C:\Program Files (x86)\nodejs.这时使用cmd命令窗口 node -v ,npm -v命令查看下安装的版本 1.1.helloworld 在Node.js工程目录中新建一个文件hello.js,里面敲一行代码 console

七天学会NodeJS (原生NodeJS 学习资料 来自淘宝技术团队)

NodeJS基础 什么是NodeJS JS是脚本语言,脚本语言都需要一个解析器才能运行.对于写在HTML页面里的JS,浏览器充当了解析器的角色.而对于需要独立运行的JS,NodeJS就是一个解析器. 每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情.例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了document之类的内置对象.而运行在NodeJS中的JS的用途是操作磁盘文件或搭建HTTP服务器,NodeJS

Get the Mime Type from a File

原文:http://www.rgagnon.com/javadetails/java-0487.html Using javax.activation.MimetypesFileTypeMap activation.jar is required, it can be downloaded from http://java.sun.com/products/javabeans/glasgow/jaf.html. The MimetypesFileMap class is used to map

Interprocess communication - 1 data stream

当进程间可以共享数据, 并且可以等待其他进程是否执行完毕时, 程序将变得更加强大. 显然共享数据和等待都是内部进程通信的范畴, 这里主要讲一下 data stream. 每个进程都有一个descriptor table, 这个表包含了file descriptor(a number) 和 data stream的映射关系. 如图 :  A file descriptor is a number that represents a data stream. 默认会有3条映射关系, 0, 1 , 2

gulp.src()内部实现探究

写在前面 本来是想写个如何编写gulp插件的科普文的,突然探究欲又发作了,于是就有了这篇东西...翻了下源码看了下gulp.src()的实现,不禁由衷感慨:肿么这么复杂... 进入正题 首先我们看下gulpfile里面的内容是长什么样子的,很有express中间件的味道是不是- 我们知道.pipe()是典型的流式操作的API.很自然的,我们会想到gulp.src()这个API返回的应该是个Stream对象(也许经过层层封装).本着一探究竟的目的,花了点时间把gulp的源码大致扫了下,终于找到了答

(虽然是转的,很希望给大家看)分析中文编码问题

简介  编码问题一直困扰着开发人员,尤其在 Java 中更加明显,因为 Java 是跨平台语言,不同平台之间编码之间的切换较多.本文将向你详细介绍 Java 中编码问题出现的根本原因,你将了解到:Java 中经常遇到的几种编码格式的区别:Java 中经常需要编码的场景:出现中文问题的原因分析:在开发 Java web 程序时可能会存在编码的几个地方,一个 HTTP 请求怎么控制编码格式?如何避免出现中文问题?   为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?

FFMPEG:H264解码-SDL显示(RGB32、RGB24、YUV420P、YUV422)

FFMpeg对视频文件进行解码的大致流程 1. 注册所有容器格式: av_register_all()2. 打开文件: av_open_input_file()3. 从文件中提取流信息: av_find_stream_info()4. 穷举所有的流,查找其中种类为CODEC_TYPE_VIDEO5. 查找对应的解码器: avcodec_find_decoder()6. 打开编解码器: avcodec_open()7. 为解码帧分配内存: avcodec_alloc_frame()8. 不停地从码