학습 목표
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)
◎ 디렉토리 다루기
▷ 디렉토리 생성
▷ 디렉토리 내용 읽기
▷ JavaScript
◎ 버퍼 만들기
▷ 생성 후 크기 변경 불가
▷ 버퍼에서 문자열 작성
▷ 문자열의 바이트 길이
▷ 디렉토리 생성
- 같은 이름의 디렉토리가 있으면 실패
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진 데이터를 다루는 타입인 버퍼를 사용해 봤습니다.
댓글 없음:
댓글 쓰기