三日間node入門(day 1)

13444 ワード

1.はじめに
目次:
  • インストール(言わないで、ネット上で探します)
  • モジュール
  • コードの組織と導入
  • ファイルアクション
  • 本明細書のコマンド動作
    $ node node_test.js test.py test.py1
    
    process.argv[2]test.pyです.
    疑問や文章に誤りがある場合は、コメントエリアで指摘してください.私信では他の人には見られないので、がんばって一緒に進みます~~(゜▽゜*)♪
    2.モジュール
    各ファイルはモジュールであり、ファイルのパスはモジュール名です.各モジュールでは、requireexportsmoduleの3つの変数が使用できます.
    1つのモジュールのコードは、初期化時に1回のみ実行され、その後、繰り返し呼び出しのためにキャッシュされます.
    a.require
    あるモジュールで、別のモジュールをロードし、エクスポートオブジェクトを返す方法です.絶対パスではなく相対パスを入力することを推奨します.
    const foo1 = require('./foo') // .js         
    const data = require('./data.json') //     json  
    

    b.exports
    1つのオブジェクトは、現在のモジュールのエクスポートオブジェクトであり、メソッドまたはプロパティをエクスポートするために使用され、他のモジュールはrequireメソッドを使用して現在のモジュールのエクスポートオブジェクトを呼び出すことができます.
    exports.sayName=function(name){
        console.log('Hi' +name)
    }
    

    c.module
    現在のモジュールに関する情報にアクセスできるオブジェクトで、「≪関連プロパティの表示|View Related Properties|emdw≫」をクリックします.最も多くの用途は、現在のモジュールのエクスポートモジュールを置き換えることです.デフォルトのエクスポート値が空のオブジェクトである場合、関数に変更します.
    module.exports = function () {
        console.log('test');
    };
    

    d.メインモジュール
    Nodeはメインモジュールと呼ばれるエントリファイルが1つしかありません.コマンドラインを呼び出して有効にする必要があります.
    node main.js
    

    1つのファイルで同じモジュールを複数回呼び出すと、導入されたモジュールの内部変数は1回だけ初期化され、新しいメモリは開かれません.
    3.コードの組織と配置
    a.モジュールの経路解析規則
    前章からrequireが相対経路と絶対経路をサポートすることを知った.しかし、この導入方式は、後期メンテナンスでファイルの保存場所を変更した場合、参照したファイルでも関連パスを変更し、一発で全身を動かす.requireには、3つ目のパスの書き方もあります.
    内蔵モジュール
    組み込みモジュールはパス解析がなく、モジュールのエクスポートオブジェクトに直接戻ります.
    const fs=require('fs')
    

    node_modules
    ほとんどのサードパーティ製モジュールはこのディレクトリにインストールされており、node_は導入時に直接無視されます.modulesフォルダの前のパスは、直接導入すればいいです.
    たとえば、このパスは次のようになります.
    /mytac/node_modules/app
    

    導入時
    const app=require('app')
    

    NODE_PATH環境変数
    定義NODE_PATH環境変数、例えば
    NODE_PATH=/a/b/c
    
    require('file')を参照すると、nodeは次のパスを試みます.
    /a/b/c/file
    

    b.バッグ
    複数のサブモジュールからなるモジュールをパッケージと呼び、すべてのサブモジュールを同じディレクトリの下に配置し、npmパッケージを書いた人は、この大きなモジュールにエントリファイルが必要であることを知っています.エントリファイル名がindexであれば、導入時に直接前のパスを書けばいいです.
    const app=require('application')
    //    
    const app=require('application/index')
    

    c.コマンドライン
    栗を挙げると、コマンドラインプログラムがあり、関連パラメータが入力され、印刷されることを望んでいます.
    $ node myapp/src/util/node-echo.js Hello world
    Hello world
    

    この使用方法はコマンドラインプログラムに似ていません.次が望ましい方法です.
    $ node-echo Hello world
    

    Linux
    Linuxでは、jsファイルをshellスクリプトとして実行できます.上記の効果を達成するには、次の手順に従います.
  • shellスクリプトでは、#!注釈で現在のスクリプトの解釈器を指定し、まずnode-echo.jsファイルの上部にこの注釈を追加し、スクリプトがnodeで解析する必要があることを証明します.
  • #! /myapp/src/util/env node
    
  • node-echo.jsファイル実行権限
  • を付与
    $ chmod +x /myapp/src/util/node-echo.js
    
  • PATH環境変数の下でディレクトリを指定します.たとえば、/myapp/src/util/の下でソフトチェーンファイルを作成します.ファイル名は、使用する端末コマンドと同じ名前です.コマンドは次のとおりです.
  • $ sudo ln -s /myapp/src/util/node-echo.js /myapp/src/util/node-echo
    

    このように処理すると、任意のディレクトリでnode-echoコマンドを使用できますよ~
    Windows
    WindowsではLinuxとは全く異なり、.cmdファイルで問題を解決する必要があります.node-echo.jsがC:\myapp\src\utilディレクトリに格納され、PATH環境変数に追加されている場合は、次のようにディレクトリの下にnode-echo.cmdというファイルを新規作成する必要があります.
    @node "C:\myapp\src\util
    ode-echo.js" %*

    このように処理すると、任意のディレクトリでnode-echoコマンドを使用できますよ~
    プロジェクトカタログ標準サンプル
    - /home/user/workspace/node-echo/   #     
        - bin/                          #          
            node-echo
        + doc/                          #     
        - lib/                          #   API    
            echo.js
        - node_modules/                 #      
            + argv/
        + tests/                        #       
        package.json                    #      
        README.md                       #     
    

    d.NPM
    サードパーティ製パッケージのダウンロード
    #           package.json   
    $ npm install package --save
    #       
    $ npm install package1.0.1
    

    自分のパッケージを公開
    まずnpmにアカウントを登録し、npm initのヒントに従って関連情報を記入し、最後にnpm publishで公開すればいいです.
    3.ファイル操作
    a.fsモジュール
    Nodeは基本的なファイル操作apiしか提供していませんが、ファイルコピーという高度な操作はありません.ここではまず手を練習します.
    ファイルコピー
    var fs = require('fs');
    
    function copy(src, dst) {
        fs.writeFileSync(dst, fs.readFileSync(src));
    }
    
    function main(argv) {
        copy(argv[0], argv[1]);
    }
    
    main(process.argv.slice(2));
    

    ディレクトリの下に入り、ディレクトリの下のtest.pyファイルをフォルダの下のtest 2.pyにコピーする場合は、コマンドを入力します.
    $ node node-echo.js test.py test2.py
    

    以上のプログラムは、fs.readFileSyncを介してソースパスからファイル内容を読み出し、fs.writeFileSyncを用いてターゲットパスにファイルを書き込む.processは、process.argvによってコマンドラインパラメータを取得するグローバル変数です.注目すべきはargv[0]が常にnode実行プログラムの絶対パスであり、argv[1]がメインモジュールの絶対パスであるため、入力されたパラメータはargv[2]という位置から取る必要がある.
    大きなファイルコピー
    上のファイルが小さいファイルをコピーするのは大した問題はありませんが、大きいファイルを読むとメモリがパンクします.大きいファイルを読むには少しだけ読んで書くしかありません.完成するまで、上のプログラムについては以下のように改造する必要があります.
    var fs=require('fs')
    
    function copy(src,dist){
        fs.createReadStream(src).pipe(fs.createWriteStream(dist))
    }
    
    function main(argv){
        copy(argv[0],argv[1])
    }
    
    main(process.argv.slice(2))
    
    fs.createReadStreamを使用してソースファイルの読み取り専用データストリームを作成し、fs.createWriteStreamを使用して書き込み専用データストリームを作成し、pipeメソッドで2つのデータストリームを接続します.
    b.Buffer
    jsにはバイナリデータ型はなく、nodeはStringと対等な全劇構造関数Bufferを提供してバイナリデータを操作する.ファイルを読み込んでBufferのインスタンスを得ることができるほか、以下のように直接構築することもできます.
    var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
    

    BufferとStringタイプの差は多くなく、length属性でバイト長を読み取ることもできるし、[index]方式でファイル位置を読み取ることもできる.Stringと変換することもできます.たとえば、次のようにします.
    var str=bin.toString('utf-8') //     
    var bin=new Buffer('hello','utf-8') //
    

    もちろん、彼らにも違いがあります.文字列は読み取り専用で、この文字列は変更されないという意味ではなく、バイトの位置を個別に変更するという意味で、この位置は変更されませんが、Bufferは異なり、Bufferを変更することは配列を変更するようになり、ある位置の値を直接変更することができます.sliceメソッドを使用しても、新しいBufferを返すのではなく、ある位置のポインタを返し、そのポインタの値を変更すると元のbufferに作用します.例:
    var bin =new Buffer([0x68,0x65,0x6c])
    var bin2=bin.slice(1)
    bin2[0]=0x68
    console.log(bin) // 68 68 6c
    

    したがって、bufferをコピーするには、copyの方法でbufferのデータをコピーする新しいbufferを作成する必要があります.
    var bin =new Buffer([0x68,0x65,0x6c])
    var dup=new Buffer(bin.length)
    bin.copy(dup)
    bin[0]=0x65
    console.log(bin) //65 65 6c
    console.log(dup) // 68 65 6c
    

    c.Stream
    メモリに処理するデータが一度に入らない場合や、読みながら処理する必要がある場合は、データストリームを使用する必要があります.ノードでは、様々なStreamによってデータストリームの動作が提供される.たとえば、データに対して読み取り専用ストリームを作成します.
    var fs=require('fs')
    var rs=fs.createReadStream(process.argv[2])
    
    rs.on('data',function(chunk){
       // do something
        console.log(chunk) 
    })
    
    rs.on('end',function(){
        console.log('end')
    })
    

    Streamはイベントメカニズムに基づいて動作し、すべてのStreamのインスタンスはNodeJSが提供するEventEmitterに継承されます.上記のdataイベントは絶えずトリガーされますが、dataイベントの関数は毎回実行されるわけではありません.この問題は以下の方法で解決できます.
    var fs=require('fs')
    var rs=fs.createReadStream(process.argv[2])
    
    function print(data,func){
        console.log(data)
        func()
    }
    
    rs.on('data',function(chunk){
        rs.pause()
        print(chunk,function(){
            rs.resume()
        })
    })
    
    rs.on('end',function(){
        console.log('end')
    })
    

    書き込み専用データストリームの作成
    var fs=require('fs')
    var rs=fs.createReadStream(process.argv[2])
    var ws=fs.createWriteStream(process.argv[3])
    
    rs.on('data',function(chunk){
        ws.write(chunk)
    })
    
    rs.on('end',function(){
        ws.end()
        console.log('end')
    })
    

    ただし、上記のプログラムでは、書き込み速度が読み取り速度に追いつかないと内部キャッシュがパンクするという問題があります..writeメソッドの戻り値に基づいて、入力されたデータがターゲットファイルに書き込まれたのか、キャッシュに一時的に置かれたのかを判断し、drainイベントによってdrainは、いつデータストリームだけがキャッシュ中のデータをターゲットに書き込まれたのかを判断し、次の書き込み対象データを入力できるようになったことを意味する.
    var fs=require('fs')
    const argvs=process.argv
    var rs=fs.createReadStream(argvs[2])
    var ws=fs.createWriteStream(argvs[3])
    
    rs.on('data',function(chunk){
        if(ws.write(chunk)===false){
            rs.pause()
        }
    })
    
    rs.on('end',function(){
        ws.end()
    })
    
    ws.on('drain',function(){ //      
        rs.resume()
    })
    

    d.その他のファイル操作
    (a)ファイル属性の読み書き
    ファイルのプロパティの取得
    fs.stat
    var fs=require('fs')
    const argvs=process.argv
    fs.stat(argvs[2],function(err,stats){
        if(err){
            throw err
        }else{
            console.log(stats)
        }
    })
    

    読み書き権限の変更
    fs.chmod
    権限707、777の設定について
    var fs=require('fs')
    const argvs=process.argv
    function getState(path,str){
        fs.stat(path,function(err,stat){
                if(err){
                    throw err
                }else{
                    console.log(str+stat.mode)
                }
            })
    }
    
    getState(argvs[2],'   ')
    
    fs.chmod(argvs[2],0777,function(err){
        if(err){
            throw err
            console.log('    ')
        }else{
            getState(argvs[2],'   ')
        }
    })
    

    ファイル所有権の変更
    fs.chown
    var fs=require('fs')
    const path=process.argv[2]
    function getState(path){
        fs.stat(path,function(err,stat){
                if(err){
                    throw err
                }else{
                    const {gid,uid}=stat
                    console.log(`gid:${gid},uid:${uid}`)
                }
            })
    }
    
    getState(path)
    fs.chown(path,1,0,function(err){ // 1,0    uid、gid
        if(err){
            throw err
        }else{
            console.log('changed')
            getState(path)
        }
    })
    

    (b)ファイル内容の読み書き
    ファイルの内容を読み込む
    fs.readFile
    var fs=require('fs')
    const path=process.argv[2]
    fs.readFile(path,'utf-8',function(err,data){ //          , buffer    
        if(err){
            throw err
        }else{
            console.log(data)
        }
    })
    

    ファイルディレクトリの読み込み
    fs.readdir
    fs.readdir('../',function(err,files){ //    
        if(err){
            throw err
        }
            console.log(files)
    })
    

    ファイルの書き込み
    ファイルが存在する場合は上書きされます
    fs.writeFile
    fs.writeFile('test.txt','test message~~~',function(err){
        if(err){
            throw err
        }
            console.log('saved file')
    })
    

    ディレクトリの作成
    ディレクトリが存在する場合、例外が放出されます.
    fs.mkdir
    fs.mkdir('newdir',0777,err=>{
        if(err) throw err
            console.log('created!')
    })
    

    (c)下位ファイル操作
    ファイルを開く/閉じる
    fs.open fs.close
    var fs=require('fs')
    const path=process.argv[2]
    fs.open(path,'w',(err,fd)=>{
        if(err) throw err
        fs.futimes(fd,1388648322,1388648322,err=>{
            if(err) throw err
            console.log('futimes done')
        fs.close(fd,()=>{
            console.log('done')
        })
        })
    })
    

    ファイルデータの読み込み
    fs.readは、指定されたファイル記述子fdに基づいてファイルデータを読み出し、bufferが指すバッファオブジェクトに書き込む.readFileに対してより下位のインタフェースが提供する.
    一般的には、バッファとファイルポインタを手動で管理する必要があるため、ファイルのサイズが分からない場合は特に面倒なことになります.
    var fs = require('fs')
    const path = process.argv[2]
    fs.open(path, 'r', (err, fd) => {
        if (err) throw err
        let buf = new Buffer(8)
        fs.read(fd, buf, 1, 15, null, (err, bytesRead, buffer) => { // 0      100         null        ,null        
            if (err) throw err
            console.log('bytesRead', bytesRead)
            console.log(buffer)
        })
    })
    

    ファイル記述子に従ってファイルを書き込む
    fs.writeこの方法はより下位レベルの操作を提供し、実際の応用ではマルチfs.writeFile()の使用を推奨する.
    var fs = require('fs')
    const path = process.argv[2]
    fs.open(path, 'w', (err, fd) => {
        if (err) throw err
        const data='# hello python!'
        const buf=new Buffer(data,'utf-8')
        fs.write(fd,buf,0,data.length,0,(err,bytesWritten,buffer)=>{
            if(err) throw err
            console.log(bytesWritten)
            console.log(buffer)
    
            fs.close(fd,err=>{
                if(err) throw err
                    console.log('file closed')
            })
        })
    }
    

    以上説明した方法はすべて非同期で呼び出され、それぞれ対応する同期方法もあり、readFileSyncを例に挙げます.
    var fs = require('fs')
    const path = process.argv[2]
    try{
        const data=fs.readFileSync(path)
        console.log(data)
    }catch(err){
        console.log(err)
    }
    

    e.Path
    Nodeには、パス関連の操作を簡素化し、コードの可読性を向上させるためのいくつかの組み込みモジュールが用意されています.
    パスの標準化
    path.normalize(path)は、入力されたパスを標準のパスに変換し、余分なスラッシュを取り除くことができます.しかし、異なるオペレーティングシステムでは、解析後のスラッシュが異なります.
    var path=require('path')
    const url = process.argv[0]
    console.log(path.normalize(url))
    

    接続パス区切り
    pathクリップを接続し、パスを正規化します.path.join
    var path=require('path')
    console.log(path.join('/foo','//bar','abc','../abc')) // \foo\bar\abc
    

    pathの拡張子の取得
    ファイルの拡張子を返し、最後の.から切り取り、.がなければ空の文字列を返します.path.extname
    const url = process.argv[2]
    var path=require('path')
    console.log(path.extname(url)) // .py