1. 파일 읽기
박수진_1007
FileReader
•
FileReader은 Character 파일을 읽을 수 있는 기능 제공
•
인코딩을 지정할 수 있으며, 이 기능은 Java 11이후에서만 제공
BufferedReader
•
buffer를 사용하기 때문에 FileReader보다 좀 더 효율적으로 파일을 읽어올 수 있음
•
BufferedReader의 기본 buffer 사이즈는 8KB
한글자씩 읽기
코드
설명
한 라인씩 읽기(효율적인 방법)
코드
설명
2. parser()
Parser
•
파싱을 하는 프로세서를 파서라고 함 (파서가 파싱 작업을 하는 것)
•
컴파일러의 일부로서 원시 프로그램(기계어로 번역되기 전의 프로그램)으로 컴파일러나 인터프리터에서 원시 프로그램을 읽어 들여, 그 문장의 구조를 알아내느 구문 분석을 행하는 프로그램을 말함
•
parser는 수작업으로 프로그래밍되며 도구에 의해 (반)자동적으로 만들어질 수 있다
•
parse는 일련의 입력 문자로부터 token을 만들기 위해 별도의 낱말 분석기를 이용하기도 한다
Parsing
•
인터넷에 주어진 정보를 내가 원하는대로 가공하여 서버에서 원하는 때에 불러올 수 있도록 하는 것
•
<>와 같은 태그를 사용자가 입력하면 컴퓨터가 알아볼 수 있도록 바꿔주는 과정
•
어떤 문장을 분석하거나 문법적 관계를 해석하는 행위
•
Parsing 기법으로 XML 파싱 기법인 DOM과 SAX / JSON 파싱 기법이 있다
parse메소드 구현
3.getMoveCntMap
PopulationMove.java
전출과 전입의 정보를 담을 수 있는 PopulationMove 클래스 생성.
public class PopulationMove {
private int fromSido; // 전출
private int toSido; // 전입
// constructor 추가 fromSido, toSido를 받아서 멤버 변수에 넣는 기능
public PopulationMove(int fromSido, int toSido) {
this.fromSido = fromSido;
this.toSido = toSido;
}
public int getFromSido() {
return fromSido;
}
public int getToSido() {
return toSido;
}
}
Java
복사
PopulationStatistics.java
1.
PopulationStatistics 객체 생성
코드
2.
List<PopulationMove>pml 객체 생성
코드
a.
readByLine 메소드를 사용하여 fileAddress의 내용을 읽어온다.
코드
fileAddress 내용
b.
List<PopulationMove>pml을 ArrayList형태로 선언한다.
c.
반복문을 진행하면서 filename의 한 문장씩 str변수에 대입한다.
d.
변수 str을 parse메소드를 통해 split후 PopulationMove 필드에 넣는다.
e.
생성된 PopulationMove pm을 pml에 추가한다.
f.
모든 pm이 추가된 pml을 리턴한다.
3.
getMoveCntMap메소드를 진행하여 데이터를 넣으면서 Map<String, Integer> map객체를 생성한다.
코드
a.
Map<String, Integer> moveCntMap을 해시맵으로 생성한다.
b.
List pml을 반복하면서 꺼내 온 값으로 fromSido와 getToSido를 분리하여 String key에 대입한다.
c.
맵 moveCntMap의 키를 대입했을 때 key와 value가 존재하지 않은 null 상태라면, moveCntMap에 key값과 value를 추가해준다. key가 존재한다면 기존에 갖고 있던 value값에 +1을 진행한다.
d.
생성된 HashMap moveCntMap을 리턴한다. ( ex ) key : “11,13”, value : 25231 )
종합 코드
코드
PopulationMove.java
전출과 전입의 정보를 담을 수 있는 PopulationMove 클래스 생성.
public class PopulationMove {
private int fromSido; // 전출
private int toSido; // 전입
// constructor 추가 fromSido, toSido를 받아서 멤버 변수에 넣는 기능
public PopulationMove(int fromSido, int toSido) {
this.fromSido = fromSido;
this.toSido = toSido;
}
public int getFromSido() {
return fromSido;
}
public int getToSido() {
return toSido;
}
}
Java
복사
PopulationStatistics.java
1.
PopulationStatistics 객체 생성
코드
2.
List<PopulationMove>pml 객체 생성
코드
a.
readByLine 메소드를 사용하여 fileAddress의 내용을 읽어온다.
코드
fileAddress 내용
b.
List<PopulationMove>pml을 ArrayList형태로 선언한다.
c.
반복문을 진행하면서 filename의 한 문장씩 str변수에 대입한다.
d.
변수 str을 parse메소드를 통해 split후 PopulationMove 필드에 넣는다.
e.
생성된 PopulationMove pm을 pml에 추가한다.
f.
모든 pm이 추가된 pml을 리턴한다.
3.
getMoveCntMap메소드를 진행하여 데이터를 넣으면서 Map<String, Integer> map객체를 생성한다.
코드
a.
Map<String, Integer> moveCntMap을 해시맵으로 생성한다.
b.
List pml을 반복하면서 꺼내 온 값으로 fromSido와 getToSido를 분리하여 String key에 대입한다.
c.
맵 moveCntMap의 키를 대입했을 때 key와 value가 존재하지 않은 null 상태라면, moveCntMap에 key값과 value를 추가해준다. key가 존재한다면 기존에 갖고 있던 value값에 +1을 진행한다.
d.
생성된 HashMap moveCntMap을 리턴한다. ( ex ) key : “11,13”, value : 25231 )
종합 코드
public class PopulationStatistics {
public static void main(String[] args) throws Exception {
String fileAddress = "./from_to.txt";
PopulationStatistics ps = new PopulationStatistics();
List<PopulationMove> pml = ps.readByLine(fileAddress);
Map<String, Integer> map = ps.getMoveCntMap(pml);
}
public List<PopulationMove> readByLine(String filename) throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(filename));
String str;
List<PopulationMove> pml = new ArrayList<>();
while ((str = reader.readLine()) != null) {
PopulationMove pm = parse(str);
pml.add(pm);
}
return pml;
}
public PopulationMove parse(String data) {
String[] intData = data.split(",");
int fromSido = Integer.parseInt(intData[0]);
int toSido = Integer.parseInt(intData[1]);
return new PopulationMove(fromSido, toSido);
}
public Map<String, Integer> getMoveCntMap(List<PopulationMove> pml) {
Map<String, Integer> moveCntMap = new HashMap<>();
for (PopulationMove pm : pml) {
String key = pm.getFromSido() + "," + pm.getToSido();
if (moveCntMap.get(key) == null) {
moveCntMap.put(key, 1);
}
moveCntMap.put(key, moveCntMap.get(key) + 1);
}
return moveCntMap;
}
}
Java
복사
4. 파일 저장
김하늘_1007
저장할 빈 파일 생성 메소드
생성된 파일에 내용 작성 메소드
전체 인구 파일에서 전입 전출 내용만 추출하여 저장하기
HeatMap Chart그리기를 위하여 인덱스 변경하여 저장하기
5. Chart 표현
6. OOP 설계
이 프로젝트에 OOP (Object Oriented Programming) 방식을 적용하여 리팩토링 함으로서 재사용성, 확장성, 개방-폐쇄 원칙(SOLID 원칙의 O)에 준하는 프로그램을 만들어보자.
코드 리팩토링하기
중복되는 메서드 readByLine()과 parse()를 외부 클래스에서 구현
코드 보기
코드 설명
코드 보기
코드 설명
코드 보기
코드 설명
재사용성, 확장성
만약 전입과 전출 정보가 아니라 전입일이나 세대주의 성별과 같은 정보 (같은 파일에 저장되어 있다) 를 추출하고 싶다면, 단순히 ParseDateAndGender과 같은 ParseAccordingly를 구현하는 구현체 클래스를 만들어서 CSV 파일의 다른 부분(12번째, 40번째 와 같은)의 데이터를 추출하면 된다. 또 만약 CSV 파일이 아니라서 데이터가 아닌 쉼표가 아니라 탭이나 빈칸으로 분리되어 있다고 한다면 ParseBlankSeparated와 같은 클래스를 만들어 split 의 매개변수만 바꾸어주면 되기 때문에 계속해서 하나의 인터페이스를 다르게 구현하는 노력만 하면 된다. ReadLineContext는 변하지 않고 그대로일 것이고, ParseAccordingly도 마찬가지이다.
개방-폐쇄 원칙, 정보 은닉
만약 이 모든 메서드들을 하나의 클래스에 담으면 모든 객체들이 하는 일에 대해 알 필요가 없는 클래스에 구현들을 노출하게 된다. 하지만 이렇게 다양한 인터페이스와 클래스로 나누면 객체의 수정에 대해서 숨길 수 있게 된다. 서로 관련이 없는 객체끼리는 최대한 관여하지 않게 되고, 그 만큼 다른 객체의 코드가 변하는 것에 받는 영향이 줄어든다.