2017년 10월 23일 월요일

Chapter3. NodeJS의 기본 모듈2



학습 목표

1. 자주 사용하는 기본 모듈에 대해서  알 수 있습니다.
2. 파일을 다루기 위해 path, fs 모듈을 사용할 수 있습니다.
3. 이진 데이터를 다루는 버퍼 모듈을 사용할 수 있습니다.

01. 경로 다루기

◎ path 모듈 : 파일 경로 다루기

  • 경로 정규화
  • 경로 생성
  • 디렉토리/파일 이름 추출
  • 파일 확장자 추출
◎ 경로 정보
▷ 현재 실행 파일 경로, 폴더 경로
▷ 전역 객체(global)
  • __filename
  • __dirname
▷ 같은 폴더 내 이미지 경로
  • var path = __dirname + '/image.png';
◎ 경로 다듬기
▷ 경로 다듬기
  • path.normalize()
▷ 경로 구성
  • '..' : 부모 폴더
  • '.' : 같은 폴더
▷ 예제
pathUtil.normalize('/user/tmp/../local///bin/');
// returns
/user/local/bin/

◎ 경로 구성 요소
▷ 경로 구성 요소 얻기

  • path.basename() : 파일 이름, 경로 중 마지막 요소
  • path.dirname() : 파일이 포함된 폴더 경로
  • path.extname() : 확장자
▷ 예제
var path = '/foo/bar/baz/asdf/quux.html';

// /foo/bar/baz/asdf
pathUtil.dirname(path);
//quux.html
pathUtil.basename(path);
// .html
pathUtil.extname(path);

▷ 경로 구성 객체
var info = path.parse('/home/user/dir/file.txt')
{
    root : "/",
    dir : "/home/user/dir",
    base : "file.txt",
    ext : ".txt",
    name : "file"
}
// 구성요소얻기
info.base
info.name

◎ 경로 만들기

  • pathUtil.sep // '/,\'
  • pathUtil.join()
  • pathUtil.format()
▷ 경로 연산
  • __dirname + pathUtil.sep + 'image.png';
  • 현재 폴더 내 image.png
▷ 경로 붙이기
  • path.join
    pathUtil.join('/foo', 'bar', 'baz/asdf', 'quux', '..')
    // returns
    '/foo/bar/baz/asdf'
▷ path.format
var path = pathUtil.format({
    root : "/",
    dir : "/home/user/dir",
    base : "file.txt",
    ext : ".txt",
    name : "file"
});

▷ '/home/user/dir/file.txt'

02. 파일 시스템 다루기

◎ 파일 시스템 다루기
▷ 파일 시스템 모듈 : fs
var fs = require('fs');
▷ 주요 기능

  • 파일 생성/읽기/쓰기/삭제
  • 파일 접근성/속성
  • 디렉토리 생성/읽기/삭제
  • 파일 스트림
주의 : 모든 플랫폼에 100% 호환되지 않음
◎ fs 모듈의 특징
▷ 특징
  • 비동기와 동기 방식 함수 모두 제공
▷ 비동기식
  • callback 사용
  • 논-블럭 방식
▷ 동기식
  • 이름 규칙 + Sync(readFileSync)
  • 블록(block)방식 - 성능상 주의
  • 반환값 이용
◎ 비동기식/동기식 API
▷ 동기식과 비동기식 API 사용 방법
▷  비동기식
var data = fs.readFileSync('textfile.txt', 'utf8);
▷  동기식
fs.readFile('textfile.txt', 'utf8', function(error, data) {
});
▷ 동기식과 비동기식 API 에러 처리 방법

  • 동기식 : try~catch사용
try {
    var data = fs.readFileSync('none_exist.txt', 'utf-8');
}
catch( exception ) {
    console.error('Readfile Error : ', exception);
}


  • 비동기식 : 콜백 함수의 에러 파라미터 사용
fs.readFile('none_exist.txt', 'utf-8', function(err, data) {
    if(err) {
        console.error('Readfile error', err);
    }
    else {
        // 정상 처리
    }
});

◎ 파일 다루기
▷  파일 다루기

  • 파일 디스크립터
  • 파일 경로
▷ FileDescription로 파일 다루기
  • fs.read(fd, buffer, offset, length, position, callback)
  • fs.readSync(fd, buffer, offset, length, position)
▷ 파일 경로로 파일 다루기
  • fs.readFile(filename[, options], callback)
  • fs.readFileSync(filename[, options])
◎ 파일 디스크립터
▷ FileDescription 얻기 : open 함수
var fd = fs.openSync(path, flag[, mode])
fs.open(path, flags[, mode], function(err, fd) {
});
▷ flag

  • r(읽기), w(쓰기), a(추가), ...
▷ 파일 닫기
  • fs.close(fd, callback);
  • fs.closeSync(fd);
◎ 파일 읽기
▷ 파일 내용 읽기
  • fs.read(fd, buffer, offset, length, position, callback)
  • fs.readFile(filename[, options], callback)
  • fs.readFileSync(filename[, options])
▷ 파일 종류
  • 문자열 읽기 : 인코딩
  • 바이너리 읽기 : buffer
▷ 인코딩 설정 안하면 - buffer

◎ 파일 읽기 예제
▷ 파일 읽기 예제 - 파일 디스크립터, 동기식
var fd = fs.openSync(file, 'r');
var buffer = new Buffer(10);

var byte = fs.readSync(fd, buffer, 0, buffer.length, 0);
console.log('File Contents : ', buffer.toString('utf-8'));

// 파일 디스크립터 닫기
fs.closeSync(fd);

▷ 파일 읽기 예제 - 파일 디스크립터, 비동기
fs.open(file, 'r' function(err, fd2) {
    var buffer2 = new Buffer(20);
    fs.read(fd2, buffer2, 0, buffer2.length, 10, functon(err, byteRead, buffer) {
        console.log('File Read', byteRead, 'bytes');
        console.log('File Content : ',  buffer.toString('utf-8'));

        fs.close(fd, function(err)[]);
    });
});

▷ 파일 읽기 - 동기식
경로를 이용하면 fd를 이용하는 것보다 편한점이 있다.
// 파일 읽기, 인코딩
console.log('File Reading, with Encoding');
var data = fs.readFileSync(file, 'utf-8);
console.log(data);

// 바이너리 파일 읽기
var imageData = fs.readFileSync('./image.jpg');
console.log('Read Image File');
console.log(imageData);

▷ 에러 처리 : try~catch

▷ 파일 읽기 : 비동기 , 인코딩
fs.readFile(file, 'UTF-8', function(err, data) {
    if(err) {
        console.error('File Read Error : ', err);
        return;
    }
    console.log('Read Text File, UTF-8 Encoding');
    console.log(data);
});

◎ 파일 상태 확인

  • 파일 다루기 : 파일 상태에 따라서 에러 발생
  • 파일 다루기 전 : 파일 상태 확인
◎ 파일 상태 - 존재 확인
▷ 파일 존재 확인하기


  • deprecated
    fs.exists(path, callback)a
    fs.existsSync(path)
▷ 대신
  • fs.access(Sync) 사용
  • fs.stat(Sync)
◎ 파일 접근 상태 확인
▷ 파일 접근 가능 확인하기
  • fs.access(path[, mode], callback)
  • fs.accessSync(path, [, mode])
▷ 접근 모드
  • fs.F_OK : 존재 확인
  • fs.R_OK, W_OK, X_OK : 읽기/쓰기/실행 여부 확인
▷ 결론
  • 접근 불가능하면 에러 발생 : try~catch 사용
◎ 파일 접근 여부 확인 후 읽기
▷ 파일 접근 여부 확인 후 읽기 - 동기식
try {
    fs.accessSync(file, fs.F_OK);
    console.log('파일 접근 가능');
    var data = fs.readFileSync(file, 'utf8');
    console.log('파일 내용 : ', data);
}
catch( exception ) {
    // 파일 없음
    console.log('파일없음 : ', excpetion);
}

◎ 파일 접근 여부 확인 후 읽기
▷ 파일 접근 여부 확인 후 읽기 - 비동기식
fs.access(file, fs.F_OK | fs.R_OK, fuction(err) {
    if(err) {
        // 에러 처리
    }
    fs.readFile(file, 'utf8', function(err, data) {
        if(err) {
            // 에러 처리
        }
        
        console.log(data);
    });
});

◎ 파일 상태
▷ 파일 상태 얻기

  • fs.stat(path, callback)
  • fs.statSync(path)
▷ 파일 상태 : fs.stats
  • 파일, 디렉토리 여부 : stats.isFile(), stats.isDirectory()
  • 파일 크기 : stats.size
  • 생성일/접근/수정일 : stats.birthtime, stats.atime, stats.mtime
▷ 파일 상태 확인 : 동기
try {
    var stats = fs.statSync(file)
    console.log('Create : ', stats.birthtime);
    console.log('size : ', stats.size);
    console.log('isFile : ', stats.isFile());
    console.log('isDirectory : ', stats.isDirectory());
}
catch(err) {
    console.error('파일 접근 에러', err);
}

▷ 파일 상태 확인 : 비동기
fs.stat(file, function(err, stats) {
    if(err) {
        console.error('File Stats Error', err);
        return;
    }

    console.log('Create : ', stats.birthtime);
    console.log('size : ', stats.size);
    console.log('isFile : ', stats.isFile());
    console.log('isDirectory : ', stats.isDirectory());
}

▷ 파일 상태 확인 후 읽기
fs.stat(path, function(err, stats) {
    if(stats.isFile()) {
        fs.readFile(path, 'utf-8', function(err, data) {
            console.log('파일 읽기 : ', data);
        });
    }
}

◎ 파일에 저장
▷ 파일에 데이터 저장

  • fs.write(fd, data[, position[, encoding]], callback)
  • fs.writeFile(filename, data[, option], callback)
  • fs.writeFileSync(filename, data[, options])
▷ 파일에 데이터 저장
  • fd, filename : 파일 디스크립터, 파일 경로
  • data : 문자열 혹은 Buffer
  • encoding : 문자열 저장 시 인코딩
▷ 같은 파일 이름 - 덮어쓰기

◎ 파일에 저장
▷ 문자열 데이터 저장
fs.writeFile('./textData.txt', 'Hello World', function(err) {
    if(err) {
        console.error('파일 저장 실패 : ', err);
        return;
    }
    console.log('파일 저장 성공');
});

◎ 파일에 추가
▷ 기존 파일에 내용 추가

  • fs.appendFile(file, data[, options], callback)
  • fs.appendFileSync(file, data[, options])
▷ 파일이 없으면? : 새 파일 생성

▷ 파일에 내용 추가
fs.appendFile(path, 'Additional data', function(err) {
    if(err) {
        console.error('파일 내용 추가 실패 : ', err);
    }
    console.log('파일 내용 추가 성공');
});

◎ 파일 삭제
▷ 파일 삭제

  • fs.unlink(path, callback)
  • fs.unlinkSync(path)
▷ 파일이 없으면 에러
▷ 예제 코드
fs.unlink('./binaryData.da, function(err) {
    if(err) {
        console.error('Delete Error : ', err);
    }
});

◎ 파일 이름 변경/이동
▷ 파일 이름 변경/이동

  • fs.rename(oldPath, newPath, callback)
  • fs.renameSync(oldPath, newPath)
◎ 디렉토리 다루기
▷ 디렉토리 생성

  • 같은 이름의 디렉토리가 있으면 실패
    fs.mkdir(path[, mode], callback), fs.mkdirSync
▷ 디렉토리 삭제
  • 디렉토리가 비어있지 않으면 실패
    fs.rmdir(path, callback), fs.rmdirSync
▷ 예제코드1
fs.mkdir('testdir', function(err) {
    if(err) {
        console.error('mkdir error:', err);
        return;
    }
}
▷ 예제코드2
try {
    fs.rmdirSync('test');
}
catch(error) {
    console.log('디렉토리 삭제 에러');
}

▷ 디렉토리 내 파일 목록

  • fs.readdir(path, callback), fs.readdirSync
▷ 디렉토리가 없으면 에러

▷ 디렉토리 내용 읽기
fs.readdir(path, function(err, files) {
    if(err) {
        console.error('디렉토리 읽기 에러');
        return;
    }
    console.log('디렉토리 내 파일 목록(Async)\n', files);
});

◎ 파일 스트림
▷ 스트림 만들기

  • fs.createReadStream(path[, options])
  • fs.createWriteStream(path[, options])
상세한 내용은 스트림 모듈에서

03.버퍼

◎ 버퍼
▷ JavaScript

  • 문자열 다루는 기능 제고
  • 바이너리 데이터를 다루는 기능이 없음
▷ Buffer : 바이너리 데이터 다루는 모듈
▷ 글로벌이므로 별도의 로딩(require) 불필요

◎ 버퍼 얻기
▷ 파일에서 읽기
var fileBuffer = fs.readFileSync('image.jpg');
▷ 네트워크에서 얻기
socket.on('data', function(data) {
    // data - buffer
});

◎ 버퍼 만들기
▷ 생성 후 크기 변경 불가

  • new Buffer(size)
  • new Buffer(array)
  • new Buffer(str[, encoding])
◎ 버퍼 다루기
▷ 모듈 함수
  • 바이트 길이 - Buffer.byteLength(string[, encoding])
  • 비교 - Buffer.compare(buf1, buf2)
  • 붙이기 - Buffer.concat(list[, totalLength])
  • 버퍼 확인 - Buffer.isBuffer(obj)
  • 인코딩 - Buffer.isEncoding(encoding)
▷ 객체 메소드
  • 길이 - buffer.length
  • 채우기 - buf.fill(value[, offset][, end])
  • 자르기 - buf.slice([start[, end]])
  • 비교하기 - buf.compare(otherBuffer)
  • 복사하기 - buf.copy(targetBuffer[, targetStart][, sourceStart][, sourceEnd])
◎ 문자열과 버퍼
▷ 문자열 - 바이너리 데이터로 다루기
▷ 문자열에서 버퍼 생성
  • new Buffer(str[, encoding])
▷ 문자열 인코딩 필요
  • ascii, utf8, ...
▷ 잘못된 인코딩 -> 에러
▷ 버퍼에 문자열 쓰기
  • buf.write(string[, offset][, length][, encoding])
▷ 변환
  • buf.toString([encoding][, start][, end])
▷ 문자열에서 버퍼 생성
var strBuffer = new Buffer('Hello World');
strBuffer.toString('utf-8');
strBuffer.toString('base64'); // SGVsbG8gV29ybGQ=

▷ 버퍼에서 문자열 작성
var buffer = new Buffer(10);
// 버퍼에 문자열 쓰기
buffer.write('Hello World');
buffer.toString(); // Hello Worl , 크기를 벗어남

▷ 문자열의 바이트 길이

  • Buffer.byteLength(string[, encoding])
▷ 예제
var str1 = 'Hello World';
str1.length // 11
Buffer.byteLength(str1); // 11
// 이모지라는 이모티콘은 문자열 길이와 바이트 사이즈가 틀림

◎ 버퍼 - 데이터 읽기/쓰기
▷ 데이터 읽기/쓰기

  • buf.readInt8(offset[, noAssert])
  • buf.writeInt8(value, offset[, noAssert])
▷ 16비트 크기의 정수형 데이터 읽고 쓰기
  • buf.readUInt16LE(offset[, noAssert])
  • buf.writeUInt16LE(value, offset[, noAssert])

▷ 실수형 데이터 읽고 쓰기
cpu의 인코딩 방식에 따라 LE, BE

  • buf.writeFloatLE(value, offset[, noAssert])
  • buf.writeFloatBE(value, offset[, noAssert])
  • buf.readFloatLE(offset[, noAssert])
  • buf.readFloatBE(offset[, noAssert])
▷ Endian
  • require('os').endianness()
▷ 버퍼 쓰기(value, offset)

  • buffer.writeInt8(0, 0); // 01
  • buffer.writeUInt8(0xFF, 1); // FF
  • buffer.writeUInt16LE(0xFF, 2); // FF 00
  • buffer.writeUInt16BE(0xFF, 4); // 00 FF
  • // 01 FF FF 00 00 FF
▷ 버퍼 읽기

  • buffer.readInt8(0) // 1
  • buffer.readUInt8(1) // 255
  • buffer.readUInt16LE(2) // 255
  • buffer.readUInt16BE(4) // 255

학습정리




◎ 지금까지 'Node.JS의 기본모듈2'에 대해 살펴보았습니다.
▷ 경로 다루기
파일이나 디렉토리를 다루려면 경로를 먼저 알아야 했습니다.
경로 모듈을 이용해서 경로 정보를 상세하게 얻어낼 수 있었습니다.

▷ 파일 시스템
파일 시스템 모듈을 이용해서 파일과 디렉토리를 다룰 수 있었습니다.

▷ 버퍼
2진 데이터를 다루는 타입인 버퍼를 사용해 봤습니다.



댓글 없음: