대용량 파일 읽기: 인구이동통계 데이터
1. 파일 입력
A. 한 글자씩 읽어오기
public void readByChar(String filename) throws IOException {
FileReader fileReader = new FileReader(filename);
String fileContents = "";
while(fileContents.length()<1000000){
char content = (char) fileReader.read();
fileContents += content;
System.out.print(content);
}
}
2. csv parsing
A. csv로 도시 코드 추출하기
- 전입하기 전과 후의 거주지를 변수로 가지는 클래스
: private한 변수를 가지므로 생성자를 통해 업데이트, getter를 통해 접근
public class PopulationMove {
private int fromAddress, toAddress;
public PopulationMove(int fromAddress, int toAddress){
this.fromAddress = fromAddress;
this.toAddress = toAddress;
}
public int getFromAddress(){
return fromAddress;
}
public int getToAddress(){
return toAddress;
}
}
- csv의 1,7번째 열이 각각 전입한 후, 전입하기 전의 시도
- split(",")를 통해서 csv에 있는 값을 추출함
- 추출한 값을 PopulationMove에 넣어주어 주소를 업데이트하므로 return 값이 PopulationMove
public PopulationMove parse(String data){
String[] addresses = data.split(",");
return new PopulationMove (Integer.valueOf(addresses[6]),Integer.valueOf(addresses[0]));
}
B. 추출한 값을 csv 형태로 출력하여 다시 불러오기: 필요한 데이터만 불러오기
3. 주소코드를 시도명에 mapping
- 시도코드를 통해서 도시명을 얻을 수 있게 하기 위해서 Map 사용
public String addressMaping(int addressInteger){
Map<Integer, String> addressMap = new HashMap<>();
addressMap.put(11,"서울특별시");
addressMap.put(26, "부산광역시");
addressMap.put(27, "대구광역시");
addressMap.put(28, "인천광역시");
addressMap.put(29, "광주광역시");
addressMap.put(30, "대전광역시");
addressMap.put(31, "울산광역시");
addressMap.put(36, "세종특별자치시");
addressMap.put(41, "경기도");
addressMap.put(42, "강원도");
addressMap.put(43, "충청북도");
addressMap.put(44, "충청남도");
addressMap.put(45, "전라북도");
addressMap.put(46, "전라남도");
addressMap.put(47, "경상북도");
addressMap.put(48, "경상남도");
addressMap.put(50, "제주특별자치도");
return addressMap.get(addressInteger);
}
4. 전입-전출 시도별 이동량 구하기
- 전입 전 후의 도시의 코드를 key, 이동량을 value로 가지는 map을 생성하여 특정 도시에서 다른 도시로 이동한 사람들의 수를 구할 수 있음
- Map의 get은 object 형태로 return하므로 특정 key가 존재하지 않으면 null을 반환
- parsing한 값을 넣어주어 업데이트를 한 PopulationMove를 List의 형태로 반환 -> 각각의 입력값을 불러낼 수 있는 for-each문을 돌림
public Map<String, Integer> getMoveCntMap(List<PopulationMove> pml){
Map<String, Integer> moveCntMap = new HashMap<>();
for(PopulationMove pm: pml){
String key = pm.getFromAddress() + "," + pm.getToAddress();
if (moveCntMap.get(key) == null){
moveCntMap.put(key, 1);
} else{
moveCntMap.put(key, moveCntMap.get(key)+1);
}
}
return moveCntMap;
}
5. 파일에 결과값 출력
A.
B. 출력하는 결과값의 형식 맞춰 작성하기
C. 출력한 파일 읽어들여서 heatmap을 작성하기 위한 형식으로 파일 작성하기
6. 전체 코드
- PopulationMove
: 이동한 인구의 이전 주소(fromAddress)와 이후 주소(toAddress)를 받아오는 클래스
package moveproject;
public class PopulationMove {
private int fromAddress, toAddress;
public PopulationMove(int fromAddress, int toAddress){
this.fromAddress = fromAddress;
this.toAddress = toAddress;
}
public int getFromAddress(){
return fromAddress;
}
public int getToAddress(){
return toAddress;
}
}
- PopulationStatistics
1) File 읽는 메소드: readFileByLine, readFileByLine2, readByChar
2) 불러온 csv 파일을 comma(,)를 기준으로 parsing하는 메소드: parse
3) 주소 코드를 시도에 mapping하는 메소드: addressMaping
4) 파일 생성 후 출력하는 메소드: CreateAFile, write
5) 전입-전출 시도별 이동량을 구하는 메소드: getMoveCntMap
6) heatmap을 만들기 위해 출력하는 txt 파일의 형식을 맞추는 메소드: fromToString, heatmapIdxMap
package moveproject;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class PopulationStatistics {
public List<PopulationMove> readFileByLine(String filename) throws IOException {
List<PopulationMove> pml = new ArrayList<>();
BufferedReader bufferedReader = new BufferedReader(
new FileReader(filename)
);
String str;
while ((str = bufferedReader.readLine()) != null) {
PopulationMove pm = parse(str);
pml.add(pm);
}
bufferedReader.close();
return pml;
}
public void readFileByLine2(String filename) {
try(BufferedReader br = Files.newBufferedReader(
Paths.get(filename), StandardCharsets.UTF_8)){
String line;
while((line = br.readLine())!=null){
System.out.println(line);
}
} catch(IOException e){
throw new RuntimeException(e);
}
}
public void readByChar(String filename) throws IOException {
FileReader fileReader = new FileReader(filename);
String fileContents = "";
while(fileContents.length()<1000000){
char content = (char) fileReader.read();
fileContents += content;
System.out.print(content);
}
}
public PopulationMove parse(String data){
String[] addresses = data.split(",");
return new PopulationMove (Integer.valueOf(addresses[0]),Integer.valueOf(addresses[1]));
}
public String addressMaping(int addressInteger){
Map<Integer, String> addressMap = new HashMap<>();
addressMap.put(11,"서울특별시");
addressMap.put(26, "부산광역시");
addressMap.put(27, "대구광역시");
addressMap.put(28, "인천광역시");
addressMap.put(29, "광주광역시");
addressMap.put(30, "대전광역시");
addressMap.put(31, "울산광역시");
addressMap.put(36, "세종특별자치시");
addressMap.put(41, "경기도");
addressMap.put(42, "강원도");
addressMap.put(43, "충청북도");
addressMap.put(44, "충청남도");
addressMap.put(45, "전라북도");
addressMap.put(46, "전라남도");
addressMap.put(47, "경상북도");
addressMap.put(48, "경상남도");
addressMap.put(50, "제주특별자치도");
return addressMap.get(addressInteger);
}
public void CreateAFile(String filename){
File file = new File(filename);
try{
file.createNewFile();
} catch(IOException e){
throw new RuntimeException(e);
}
}
public void write(List<String> strs, String filename){
File file = new File(filename);
try{
BufferedWriter writer = new BufferedWriter(new FileWriter((file)));
for (String str: strs){
writer.write(str);
}
writer.close();
} catch(IOException e){
e.printStackTrace();
}
}
public String fromToString(PopulationMove populationMove){
return populationMove.getFromAddress() + "," + populationMove.getToAddress()+"\n";
}
public Map<String, Integer> getMoveCntMap(List<PopulationMove> pml){
Map<String, Integer> moveCntMap = new HashMap<>();
for(PopulationMove pm: pml){
String key = pm.getFromAddress() + "," + pm.getToAddress();
if (moveCntMap.get(key) == null){
moveCntMap.put(key, 1);
} else{
moveCntMap.put(key, moveCntMap.get(key)+1);
}
}
return moveCntMap;
}
public Map<String, Integer> heatmapIdxMap (){
Map<String, Integer> map = new HashMap<>();
map.put("11",0);
map.put("26",1);
map.put("27",2);
map.put("28",3);
map.put("29",4);
map.put("30",5);
map.put("31",6);
map.put("36",7);
map.put("41",8);
map.put("42",9);
map.put("43",10);
map.put("44",11);
map.put("45",12);
map.put("46",13);
map.put("47",14);
map.put("48",15);
map.put("50",16);
return map;
}
public static void main(String[] args) throws IOException {
String address = "./from_to.txt";
PopulationStatistics populationStatistics= new PopulationStatistics();
List<PopulationMove> pml = populationStatistics.readFileByLine(address);
Map<String, Integer> map = populationStatistics.getMoveCntMap(pml);
Map<String, Integer> heatMapIdxMap = populationStatistics.heatmapIdxMap();
String targetFileName = "for_heatmap.txt";
populationStatistics.CreateAFile(targetFileName);
List<String> cntResult = new ArrayList<>();
for(String key: map.keySet()){
String[] fromto = key.split(",");
String s = String.format("[%s, %s, %d],", heatMapIdxMap.get(fromto[0]), heatMapIdxMap.get(fromto[1]), map.get(key));
cntResult.add(s);
}
populationStatistics.write(cntResult, targetFileName);
}
}