1. 程式人生 > >node學習七:檔案操作

node學習七:檔案操作

檔案操作涉及到了nodejs設計思想中的非同步I/O(檔案操作、網路操作)

非同步程式設計:

非同步I/O input/output:

1、檔案操作
2、網路操作

在瀏覽器中也存在非同步操作:

1、定時任務
2、事件處理
3、Ajax回撥處理

js的執行時單執行緒的
單執行緒存在缺點:一旦遇到一個耗時的任務,比如迴圈操作一萬次,比較消耗cpu,可能會導致ui操作的阻塞
所以引入事件佇列機制
Node.js中的事件模型與瀏覽器中的事件模型類似
單執行緒+事件佇列
基於回撥函式的編碼風格

匯入fs檔案系統模組:

const fs = require('fs');

檔案操作:

檔案資訊獲取:

非同步操作方式的檔案資訊獲取:

fs.stat(path[, options], callback):

fs.stat('./data.txt',(err,stat) => {
    // 一般回撥函式的第一個引數是錯誤物件,如果err為null,表示沒有錯誤,否則表示報錯了
    if(err) return ;
    console.log(err);
})

fs.stat('./data1.txt',(err,stat) => {
    // 一般回撥函式的第一個引數是錯誤物件,如果err為null,表示沒有錯誤,否則表示報錯了
    console.log(err);
    if(err) return ;
})

stats.isFile():

fs.stat('./data.txt',(err,stat) => {
    // 一般回撥函式的第一個引數是錯誤物件,如果err為null,表示沒有錯誤,否則表示報錯了
    if(err) return ;
    // console.log(err);
    if(stat.isFile()){
        console.log("檔案");
    }else if(stat.isDirectory()){
        console.log("目錄");
    }
})

stats.isDirectory():

fs.stat('./hello',(err,stat) => {
    // 一般回撥函式的第一個引數是錯誤物件,如果err為null,表示沒有錯誤,否則表示報錯了
    if(err) return ;
    // console.log(err);
    if(stat.isFile()){
        console.log("檔案");
    }else if(stat.isDirectory()){
        console.log("目錄");
    }
})

stats.atime 檔案訪問時間
stats.ctime 檔案的狀態資訊發生變化的時間(比如檔案的許可權)
stats.mtime 檔案資料發生變化的時間
stats.birthtime 檔案建立的時間

同步操作方式的檔案資訊獲取:

// 同步操作
let ret = fs.statSync('./data.txt');
console.log(ret);

同步操作(要執行完此時的操作才能繼續後面的操作)裡ret的值和非同步操作裡回撥函式裡的引數stat的值是一樣的

讀檔案操作:

匯入path、fs模組:

const fs = require('fs');
const path = require('path');

非同步操作方式的讀檔案:

fs.readFile(path[, options], callback):

let strpath = path.join(__dirname,'data.txt');
fs.readFile(strpath,(err,data)=>{
    if(err) return;
    console.log(data);
    console.log(data.toString());
});

// 如果有第二個引數並且是編碼,那麼回撥函式獲取到的資料就是字串
// 如果沒有第二個引數,那麼得到的就是Buffer例項物件
let strpath = path.join(__dirname,'data.txt');
fs.readFile(strpath,'utf8',(err,data)=>{
    if(err) return;
    // console.log(data.toString());
    console.log(data);
});

同步操作方式的讀檔案:

let strpath = path.join(__dirname,'data.txt');
let ret1 = fs.readFileSync(strpath);
console.log(ret1);
let ret2 = fs.readFileSync(strpath,'utf8');
console.log(ret2);

寫檔案操作:

匯入path、fs模組:

const fs = require('fs');
const path = require('path');

非同步操作方式的寫檔案:

fs.writeFile(file, data[, options], callback):

let strpath = path.join(__dirname,'data.txt');
fs.writeFile(strpath,'hello nihao','utf8',(err)=>{
    if(!err){
        console.log('檔案寫入成功');
    }
});

data.txt檔案的變化:

let strpath = path.join(__dirname,'data.txt');
let buf = Buffer.from('hi');
fs.writeFile(strpath,buf,'utf8',(err)=>{
    if(!err){
        console.log('檔案寫入成功');
    }
});

data.txt檔案的變化:

同步操作方式的寫檔案:

// 同步操作
let strpath = path.join(__dirname,'data.txt');
fs.writeFileSync(strpath,'tom and jerry');

大檔案操作(流式操作--一部分一部分的處理):

匯入path、fs模組:

const fs = require('fs');
const path = require('path');

fs.createReadStream(path[, options]):

let spath = path.join(__dirname,'../03-source','file.zip');
let dpath = path.join('C:\\Users\\www\\Desktop','file.zip');

let readStream = fs.createReadStream(spath);
let writeStream = fs.createWriteStream(dpath);
let num = 1;
readStream.on('data',(chunk)=>{
    num++;
    writeStream.write(chunk);
});

readStream.on('end',()=>{
    console.log('檔案處理完成'+num);
});
let spath = path.join(__dirname,'../03-source','file.zip');
let dpath = path.join('C:\\Users\\www\\Desktop','file.zip');

let readStream = fs.createReadStream(spath);
let writeStream = fs.createWriteStream(dpath);
// pipe的作用直接把輸入流和輸出流
readStream.pipe(writeStream);
let spath = path.join(__dirname,'../03-source','file.zip');
let dpath = path.join('C:\\Users\\www\\Desktop','file.zip');
fs.createReadStream(spath).pipe(fs.createWriteStream(dpath));

目錄操作:

匯入path和fs模組:

const path = require('path');
const fs = require('fs');

建立目錄:
fs.mkdir(path[, mode], callback)

// 建立目錄
fs.mkdir(path.join(__dirname,'abc'),(err)=>{
    console.log(err);
});


fs.mkdirSync(path[, mode])

fs.mkdirSync(path.join(__dirname,'abc'));

讀取目錄:
fs.readdir(path[, options], callback)

// 讀取目錄
fs.readdir(__dirname,(err,files)=>{
    files.forEach((item,index)=>{
        fs.stat(path.join(__dirname,item),(err,stat)=>{
            if(stat.isFile()){
                console.log(item,'檔案');
            }else if(stat.isDirectory()){
                console.log(item,'目錄');
            }
        });
    });
});

fs.readdirSync(path[, options])

let files = fs.readdirSync(__dirname);
files.forEach((item,index)=>{
    fs.stat(path.join(__dirname,item),(err,stat)=>{
        if(stat.isFile()){
            console.log(item,'檔案');
        }else if(stat.isDirectory()){
            console.log(item,'目錄');
        }
    });
});

刪除目錄:
fs.rmdir(path, callback)

// 刪除目錄
fs.rmdir(path.join(__dirname,'abc'),(err)=>{
    console.log(err);
});

fs.rmdirSync(path)

fs.rmdirSync(path.join(__dirname,'abc'));

檔案操作案例(初始化目錄結構):

/*
    檔案操作案例(初始化目錄結構)
*/
const path = require('path');
const fs = require('fs');

let root = 'C:\\Users\\www\\Desktop';
let fileContent = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div>welcome to this</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) 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);
        }
    });
});