node.js에서 fs 모듈로 입력을 받아 문제를 풀다보면 런타임 에러 (EACCES)가 발생할 수 있습니다.
이러한 문제들은 readline 모듈을 사용하여 풀어야 합니다.
저도 몇 번을 시도해도 자꾸 런타임 에러가 뜨길래 구글링 해보고 알게 되었습니다 ㅎㅎ ㅠㅠ
fs모듈과 readline모듈의 사용법, 간단히 두 가지를 비교한 것에 대해 공부했습니다😊
fs는 FileSystem의 약자로, 파일 처리와 관련된 모듈입니다.
fs 모듈은 Node.js에 내장되어 있기 때문에 불러와서 사용하면 됩니다.
fs 모듈을 불러오는 방법은 CommonJS
, ES6
2가지 방식이 있습니다.
const fs = require("fs");
먼저 CommonJS 방식
입니다. 저는 이 방식을 사용하여 진행하겠습니다.
자바스크립트의 모듈화 명세를 만든 그룹 중 하나인 CommonJS에서는 모듈을 이용할 때 require()
를 사용했고, 이것은 큰 의미를 가져 하나의 방식이 되었습니다.
import fs from "fs";
다음은 ES6 방식
입니다.
ES6(ES2015) 부터는 ES6 Module이라는 개념으로 자바스크립트에서 자체 모듈화를 지원합니다. import
/ export 로 모듈을 사용할 수 있고, 이 방법을 사용하려면 ES 모듈 시스템을 사용하는 프로젝트여야 합니다.
let input = fs.readFileSync("/dev/stdin").toString().trim();
readFileSync()
: 입력 값을 가져온 후 그 값을 이용해 문제를 푸는 것이므로, 파일을 읽어온 후 코드가 동작해야함. 따라서 동기식을 사용함
"/dev/stdin"
: 백준 사이트에서 문제를 풀 때 사용되는 문장. 필요에 맞게 경로를 바꾸어 사용함
toString()
: 입력 값을 받을 때 toString()을 포함시키는 이유는 fs.readFileSync("/dev/stdin")의 반환값은 버퍼 객체이기 때문에 fs.readFileSync("/dev/stdin", "utf8")처럼 인수로 인코딩 지정을 하지 않으면 사람이 읽을 수 없는 형식이기 때문. 따라서 문자열로 바꿔주는 메서드를 사용해줌
trim()
: 입력 값을 받을 때 trim()을 사용하는 이유는 입력 값의 마지막에 개행문자("\n")이 포함되는 경우가 있는데, 이를 제거하지 않고 사용하면 의도하지 않은 값이 나올 수 있기 때문. 따라서 미리 제거해주는 것
ex) let input = "1\n2\n3\n";
console.log(input.split("\n")); // ['1', '2', '3', '']
console.log(input.trim().split("\n")); // ['1', '2', '3']
vscode에서 문제를 풀어보고, 정답일 때 백준에서 채점 돌리는 사람이 많을 것이라고 생각합니다.
이때마다 파일 경로를 변경해주기 귀찮다면 다음과 같은 방법 사용을 추천합니다.const filePath = process.platform === "linux" ? "/dev/stdin" : "./입력값.txt"; let input = fs.readFileSync(filePath).toString().trim();
백준 채점 서버는 리눅스이므로 리눅스 환경이라면
"/dev/stdin"
를, 아니라면 본인 컴퓨터 속 입력값을 담아두는 파일("./입력값.txt"
)에서 값을 가져오도록 지정했습니다. 이 방법을 사용하면 매번 경로를 바꾸지 않아도 되어 간편합니다😄
const input=fs.readFileSync(“/dev/stdin”).toString().trim();
const input=fs.readFileSync(“/dev/stdin”).toString().trim().split(“ ”);
const input=fs.readFileSync(“/dev/stdin”).toString().trim().split(“\n”);
이 외에도 다양한 경우가 있을 수 있는데, 상황에 맞게 응용하여 사용하시면 됩니다.
const fs = require("fs");
let input = fs.readFileSync("/dev/stdin").toString().trim();
Readable Stream에서 한 번에 한 줄씩 데이터를 읽을 수 있는 인터페이스를 제공하는 것으로, input과 output을 이용해 입출력을 한 줄씩 처리하는 모듈입니다.
const readline = require('readline')
readline 모듈을 불러오는 방법에도 CommonJS
, ES6
2가지 방식이 있습니다.
저는 주로 사용되는 CommonJS 방식으로 진행하겠습니다.
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
stdin
는 standard input의 약자, stdout
는 standard output의 약자입니다.
vscode에서 문제를 풀고 싶을 때는, input의 경로를 본인 컴퓨터 속 입력값를 담아두는 파일("./입력값.txt")로 변경하면 됩니다.
input: require("fs").createReadStream("./입력값.txt"),
rl.on("line", (line) => {
/*입력 값을 처리하는 코드(내가 작성하는 부분)*/
rl.close();
});
rl.on("close", () => {
/*입력이 끝나고 실행할 코드, 출력 값 부분(내가 작성하는 부분)*/
process.exit();
});
on()
: 해당 메서드로 이벤트("line", "close")와 콜백함수(내가 작성하는 부분) 전달“line”
: 입력 값을 한 줄씩 읽어와 문자열 타입으로 전달하는 역할의 이벤트rl.close()
: 인터페이스를 종료하는 함수로, 무한히 입력 받는 것을 방지함"close"
: 더 이상 입력 값이 없을 때 실행되는 이벤트. rl.close()로 인터페이스가 끝나면 시작됨process.exit()
: 프로세스를 종료하는 함수
rl.close()
를 쓰지 않고 인터페이스를 종료시키고 싶다면,ctrl+c
를 사용하면 됩니다.
rl.on("line", (line) => { /*입력 값을 처리하는 코드(내가 작성하는 부분)*/ rl.close(); }).on("close", () => { /*입력이 끝나고 실행할 코드, 출력 값 부분(내가 작성하는 부분)*/ process.exit(); });
위 코드처럼 on()메소드를 연결하여 하나의 입출력 코드로 작성할 수 있습니다.
입력 값을 원하는 형태로 사용하기 위해서는 /*입력 값을 처리하는 코드(내가 작성하는 부분)*/
에 직접 코드를 작성해야합니다.
rl.on("line", (line) => {
/*입력 값(하나 혹은 한 줄)은 line에 저장됨*/
rl.close();
});
rl.on("close", () => {
/*입력이 끝나고 실행할 코드, 출력 값 부분(내가 작성하는 부분)*/
process.exit();
});
rl.on("line", (line) {
input = line.split(" ");
rl.close();
});
rl.on("close", () {
/*입력이 끝나고 실행할 코드, 출력 값 부분(내가 작성하는 부분)*/
process.exit();
});
rl.on("line", (line) {
input.push(line);
rl.close();
});
rl.on("close", () {
/*입력이 끝나고 실행할 코드, 출력 값 부분(내가 작성하는 부분)*/
process.exit();
});
fs 모듈과 마찬가지로 기본 형태에서 상황에 맞게 응용하여 사용하시면 됩니다.
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", (line) => {
/*입력 값을 처리하는 코드(내가 작성하는 부분)*/
rl.close();
});
rl.on("close", () => {
/*입력이 끝나고 실행할 코드, 출력 값 부분(내가 작성하는 부분)*/
process.exit();
});
fs 모듈 | readline 모듈 | |
---|---|---|
속도 | 예제 입력 파일을 읽어오기에 빠름 | 한 줄씩 처리해서 상대적으로 느림 |
발생 가능 오류 | 런타임 에러 (EACCES) - 접근 권한 오류 | 시간 초과 |
코드 길이 | 짧음 | 상대적으로 긺 |
참고한 자료: [백준] Node.js fs모듈로 입력값 받기
Node.js의 fs 모듈로 파일 입출력 처리하기
readline 모듈 사용하기
JavaScript readline 사용하기
[백준]node.js readline모듈로 입력받기