异步I/O

异步I/O  input/output
1.文件操作
2.网络操作
 
 在浏览器中也存在异步操作:
1.定时任务
2.事件处理
3.Ajax回调处理
 
 js的运行是单线程的
引入事件队列机制
 
Node.js中的事件模型与浏览器中的事件模型类似
单线程+事件队列(JS的运行是单线程的,但是Node.js的环境和浏览器的环境是多线程的)
 
Node.js中异步执行的任务:
1.文件I/O
2.网络I/O
 
Node.js是基于回调函数的编码风格

 1.文件操作

const fs = require('fs');

//异步操作
//一般回调函数的第一个参数是错误对象,如果err为null,表示没有错误,否则表示报错了
//..表示上级目录,.表示当前目录
//异步的执行结果是:先输出1 再输出3 最后输出2
//因为第二个异步的任务会进入到事件队列中,当主线程代码都执行完了,才能空闲去事件队列中把任务取出来执行
console.log(1);
fs.stat('../buffer',(err,stat) => {
    if(err) return;
    if(stat.isFile()){
        console.log('文件');
    }else if(stat.isDirectory()){
        console.log('目录');
    }
    console.log(stat);
    console.log(2);
});
console.log(3);

//异步操作是没有返回值的,只有同步操作才有返回值
//同步操作
//执行顺序肯定是:1 ret 2
console.log(1);
let ret = fs.statSync('./01.js');
console.log(ret);
console.log(2);

/**
 * 读文件操作
 */
const fs = require('fs');
const path = require('path');

//异步操作
let strpath = path.join(__dirname,'01.js');   //__dirname表示当前文件夹的绝对路径
//如果有第二个参数并且是编码,那么回调函数获取到的数据就是字符串
//如果没有第二个参数,那么得到的就是Buffer实例对象
fs.readFile(strpath,(err,data) => {
    if(err) return;
    console.log(data.toString());   //不调用toString(),则打印出来的是Buffer对象
});

//同步操作
let ret = fs.readFileSync(strpath,'utf8');
console.log(ret);

/**
 * 写文件操作
 */
//异步操作
//注意:写入的内容会覆盖掉文件里原来的内容
fs.writeFile(strpath,'hello world','utf8',(err) => {
    if(err) throw err;
    console.log('文件写入成功!');
});

let data = Buffer.from('hi');
fs.writeFile(strpath,data,'utf8',(err) => {
    if(err) throw err;
    console.log('文件写入成功!');
});

//同步操作
let ret = fs.writeFileSync(strpath,'tom and jerry','utf8');
console.log(ret);    //返回undefined
/**
 * 大文件操作(流式操作)
 * fs.createReadStream(path[, options])
 * fs.createWriteStream(path[, options])
 */
const path = require('path');
const fs = require('fs');

let spath = path.join('E://','test.zip');
let dpath = path.join('E://','file.zip');
console.log(spath);

let readStream = fs.createReadStream(spath);
let writeStream = fs.createWriteStream(dpath);
//console.log(writeStream);

//基于事件的处理方式
let num = 1;
readStream.on('data',(chunk) => {
    num++;
    writeStream.write(chunk);
});
readStream.on('end',() => {
    console.log('文件处理完成'+num);
});
//============================================================
//pipe的作用直接把输入流和输出流链接到一块
//readStream.pipe(writeStream);
fs.createReadStream(spath).pipe(fs.createWriteStream(dpath));

2.目录操作

/**
 * 目录操作:
 * 1.创建目录
 * fs.mkdir(path[, options], callback)
 * fs.mkdirSync(path[, options])
 * 2.读取目录
 * fs.readdir(path[, options], callback)
 * fs.readdirSync(path[, options])
 * 3.删除目录
 * fs.rmdir(path[, options], callback)
 * fs.rmdirSync(path[, options])
 */
const path = require('path');
const fs = require('fs');
//创建目录
//异步操作
fs.mkdir(path.join(__dirname,'abc'),(err) => {
    console.log(err);   //若没有错误,则返回null
});

//同步操作
fs.mkdirSync(path.join(__dirname,'hello'));

//读取目录
//let pathdir = path.join(__dirname,'../es6');
let pathdir = __dirname
//异步操作
fs.readdir(pathdir,(err,files) => {
    if(err) return;
    files.forEach((item,index) => {
        fs.stat(path.join(pathdir,item),(err,stat) => {
            if(stat.isFile()){
                console.log(item,'文件');
            }else if(stat.isDirectory()){
                console.log(item,'目录');
            }
        });
    });
});

//同步操作
let files = fs.readdirSync(pathdir);
files.forEach((item) => {
    fs.stat(path.join(pathdir,item),(err,stat) => {
        if(stat.isFile()){
            console.log(item,'文件');
        }else if(stat.isDirectory()){
            console.log(item,'目录');
        }
    });
});

//删除目录
//异步操作
fs.rmdir(path.join(__dirname,'abc'),(err) => {
    console.log(err);
});

//同步操作
let ret = fs.rmdirSync(path.join(__dirname,'hello'));
console.log(ret);

 3.初始化目录结构

/**
 * 文件操作案例(初始化目录结构)
 */
const path = require('path');
const fs = require('fs');

//创建的根目录的路径
let root = 'E:\\';
//用反引号
let fileContent = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div>welcome!</div>
</body>
</html>
`;
//初始化数据
let initData = {
    projectName : 'mydemo',
    data :[{
        name : 'img',
        type : 'dir'
    },
    {
        name : 'css',
        type : 'dir'
    },
    {
        name : 'js',
        type : 'dir'
    },
    {
        name : 'index.html',
        type : 'file'
    }]
};
//创建项目跟路径
fs.mkdir(path.join(root,initData.projectName),(err) => {
    if(err){
        console.log('创建失败!'); return;
    }
    //创建子目录和文件
    initData.data.forEach((item) => {
        if(item.type == 'dir'){
            //创建子目录
            fs.mkdirSync(path.join(root,initData.projectName,item.name));
        }else if(item.type == 'file'){
            //创建文件并写入内容:若没有这个文件,则自动创建然后写入内容
            fs.writeFileSync(path.join(root,initData.projectName,item.name),fileContent);
        }
    });
});

 

posted @ 2019-09-26 11:59  浮华夕颜  Views(178)  Comments(0Edit  收藏  举报