본문 바로가기

STUDY/국비과정

[JAVA 웹 개발 공부] 국비지원 38일차 - 전화번호부 프로그램, try-with-resources, 메모장 만들기, csv 파일 읽기

전화번호부 프로그램

 

public class Start {
	public static void main(String[] args) {
		UserInfos u = new UserInfos();
		u.start();
	}
}
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

public class UserInfos implements UserInputEventListener {
	private Map<String, String> users;
	private UserFrame frame;
	private UserFileRepository repo;
	
	public UserInfos() {
		users = new LinkedHashMap<>();
		frame = new UserFrame(this);
		repo = new UserFileRepository();
	}
	
	public void start() {
		Map<String, String> map = repo.readUser();
		for (Entry<String, String> e : map.entrySet()) {
			frame.addUser(e.getKey(), e.getValue());
		}
		frame.setVisible(true);
	}
	
	public void userInputCompleted(String name, String phone) {
		users.put(name, phone);
		repo.writeUser(users);
		frame.addUser(name, phone);
	}

	@Override
	public void userInputCompleted(UserInputEvent e) {
		userInputCompleted(e.getUserName(), e.getUserPhone());
	}
}
import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class UserFrame extends JFrame {
	private JPanel contentPane;
	private JPanel panel;
	private JPanel panel_1;
	private JButton btnNew;

	public UserFrame(UserInfos userInfos) {
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 450, 300);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout(0, 0));
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		contentPane.add(scrollPane, BorderLayout.CENTER);
		
		panel = new JPanel();
		scrollPane.setViewportView(panel);
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		
		panel_1 = new JPanel();
		contentPane.add(panel_1, BorderLayout.SOUTH);
		
		btnNew = new JButton("추가하기");
		btnNew.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				UserDialog dialog = new UserDialog();
				dialog.addUserInputEventListener(userInfos);
				dialog.setVisible(true);
			}
		});
		panel_1.add(btnNew);
	}
	
	public void addUser(String name, String phone) {
		panel.add(new UserInfoPnl(name, phone));
		panel.revalidate();
		panel.repaint();
	}
}
public interface UserInputEventListener {
	void userInputCompleted(UserInputEvent e);
}
public class UserInputEvent {
	private String userName;
	private String userPhone;
	public UserInputEvent(String userName, String userPhone) {
		super();
		this.userName = userName;
		this.userPhone = userPhone;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getUserPhone() {
		return userPhone;
	}
	public void setUserPhone(String userPhone) {
		this.userPhone = userPhone;
	}
}
import java.awt.BorderLayout;
import java.awt.FlowLayout;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class UserDialog extends JDialog {

	private final JPanel contentPanel = new JPanel();
	private UserInfoPnl userInfoPnl;
	private String userName;
	private String userPhone;
	private boolean completed;
	private UserInputEventListener listener;
	
	public UserDialog() {
		setModal(true);
		
		setBounds(100, 100, 450, 300);
		getContentPane().setLayout(new BorderLayout());
		contentPanel.setLayout(new FlowLayout());
		contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
		getContentPane().add(contentPanel, BorderLayout.CENTER);
		userInfoPnl = new UserInfoPnl((String) null, (String) null);
		contentPanel.add(userInfoPnl);
		
		JPanel buttonPane = new JPanel();
		buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
		getContentPane().add(buttonPane, BorderLayout.SOUTH);
		
		JButton okButton = new JButton("OK");
		okButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				userName = userInfoPnl.getUserName();
				userPhone = userInfoPnl.getUserPhone();
				listener.userInputCompleted(new UserInputEvent(userName, userPhone));
				dispose();
			}
		});
		buttonPane.add(okButton);
		
		JButton cancelButton = new JButton("Cancel");
		cancelButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				dispose();
			}
		});
		buttonPane.add(cancelButton);
	}

	public boolean showInput() {
		setVisible(true);
		return completed;
	}

	public String getUserName() {
		return userName;
	}
	
	public String getUserPhone() {
		return userPhone;
	}

	public void addUserInputEventListener(UserInputEventListener listener) {
		this.listener = listener;
	}
}
import java.awt.Dimension;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;

public class UserInfoPnl extends JPanel {
	private JLabel lblName;
	private JLabel lblPhone;
	private JTextField tfName;
	private JTextField tfPhone;

	public UserInfoPnl(String name, String phone) {
		setPreferredSize(new Dimension(400, 100));
		SpringLayout springLayout = new SpringLayout();
		setLayout(springLayout);
		
		lblName = new JLabel("이름");
		springLayout.putConstraint(SpringLayout.NORTH, lblName, 20, SpringLayout.NORTH, this);
		springLayout.putConstraint(SpringLayout.WEST, lblName, 10, SpringLayout.WEST, this);
		add(lblName);
		
		lblPhone = new JLabel("전화번호");
		springLayout.putConstraint(SpringLayout.NORTH, lblPhone, 25, SpringLayout.SOUTH, lblName);
		springLayout.putConstraint(SpringLayout.WEST, lblPhone, 10, SpringLayout.WEST, this);
		add(lblPhone);
		
		tfName = new JTextField();
		springLayout.putConstraint(SpringLayout.NORTH, tfName, 0, SpringLayout.NORTH, lblName);
		springLayout.putConstraint(SpringLayout.WEST, tfName, 6, SpringLayout.EAST, lblName);
		springLayout.putConstraint(SpringLayout.EAST, tfName, -10, SpringLayout.EAST, this);
		add(tfName);
		tfName.setColumns(10);
		
		tfPhone = new JTextField();
		springLayout.putConstraint(SpringLayout.WEST, tfPhone, 6, SpringLayout.EAST, lblPhone);
		springLayout.putConstraint(SpringLayout.EAST, tfPhone, -10, SpringLayout.EAST, this);
		springLayout.putConstraint(SpringLayout.NORTH, tfPhone, 0, SpringLayout.NORTH, lblPhone);
		add(tfPhone);
		tfPhone.setColumns(10);
		
		setUserName(name);
		setUserPhone(phone);
	}
	
	public void setUserName(String name) {
		tfName.setText(name);
	}
	
	public void setUserPhone(String phone) {
		tfPhone.setText(phone);
	}
	
	public String getUserName() {
		return tfName.getText();
	}
	
	public String getUserPhone() {
		return tfPhone.getText();
	}
}
import java.util.LinkedHashMap;
import java.util.Map;

public class TestUserFile {
	public static void main(String[] args) {
		UserFileRepository repo = new UserFileRepository();
		
		Map<String, String> testMap = new LinkedHashMap<>();	
		testMap.put("테스트용이름", "테스트용전화번호");
		testMap.put("다음사람이름", "다음사람전화번호");
		
//		repo.writeUser(testMap);
//		System.out.println("기록된 텍스트파일을 확인해보세요.");
		
		Map<String, String> readMap = repo.readUser();
		System.out.println(testMap.equals(readMap));
		
	}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;

public class UserFileRepository {
	private final File file = new File("d:\\myfolder\\user.txt");
	
	public void writeUser(Map<String, String> map) {
		BufferedWriter bw = null;
		
		try {
			bw = new BufferedWriter(new FileWriter(file));
			
			for (Entry<String, String> e : map.entrySet()) {
				bw.write(e.getKey() + " " + e.getValue() + "\n");
			}
			bw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public Map<String, String> readUser() {
		BufferedReader br = null;
		Map<String, String> map = new LinkedHashMap<>();
		try {
			br = new BufferedReader(new FileReader(file));
			
			String line;
			while ((line = br.readLine()) != null) {
				StringTokenizer st = new StringTokenizer(line, " ");
				String name = st.nextToken();
				String phone = st.nextToken();
				map.put(name, phone);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return map;
	}
}

 

 

try-with-resources

 

try에 자원 객체를 전달하면, try 코드 블록이 끝나면 자동으로 자원을 종료해주는 기능이다.

즉, 따로 finally 블록이나 모든 catch 블록에 종료 처리를 하지 않아도 된다.

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Main {
	public static void main(String[] args) {
		try (FileWriter fw = new FileWriter(new File("d:\\myfolder\\test1.txt"), true);) {
			fw.write("문자열");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

DataInputStream, DataOutputStream

 

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main4 {
	public static void main(String[] args) {
		File file = new File("d:\\myfolder\\dooli.bin");
		
		try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
			dos.writeUTF("둘리"); // writeUTF 문자를 기록
			dos.writeInt(22);
			dos.writeDouble(180.3);
			dos.writeUTF("호잇");
			dos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try (DataInputStream dis = new DataInputStream(new FileInputStream(file))) {
			String name = dis.readUTF();
			int age = dis.readInt();
			double height = dis.readDouble();
			String hobby = dis.readUTF();
			
			System.out.println(name);
			System.out.println(age);
			System.out.println(height);
			System.out.println(hobby);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

ObjectOutputStream, ObjectInputStream

 

정보를 가장 쉽게 읽고 쓰고 할 수 있음

*장점 : 쉽다.

*단점 : 이진정보라서 사람이 읽을 수 없다. 자바 시스템 외에선 활용 불가, 직렬화 가능한 객체여야 가능(implements Serializable)

 

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Main5 {
	public static void main(String[] args) {
		Person p = new Person("둘리", 22, 180.3, "호잇");
		
		File file = new File("d:\\myfolder\\person.ser");
		
		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
			oos.writeObject(p);
			oos.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
			Person read = (Person) ois.readObject();
			System.out.println(read);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

 

 

메모장 만들기

 

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Main extends JFrame {
	public Main() {
		JTextArea ta = new JTextArea();
		JScrollPane scroll = new JScrollPane(ta);
		add(scroll);
		
		
		JPanel pnlSouth = new JPanel();
		JButton btnReset = new JButton("새 파일");
		btnReset.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				ta.setText("");
			}
		});
		JButton btnOutput = new JButton("저장하기");
		btnOutput.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				int option = chooser.showSaveDialog(Main.this);
				if (option == JFileChooser.APPROVE_OPTION) {
					File select = chooser.getSelectedFile();
					writeTextToFile(select, ta.getText());
				}
			}
		});
		JButton btnInput = new JButton("불러오기");
		btnInput.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				int option = chooser.showOpenDialog(Main.this);
				if (option == JFileChooser.APPROVE_OPTION) {
					File select = chooser.getSelectedFile();
					String text = readTextFromFile(select);
					ta.setText(text);
				}
			}
		});
		
		pnlSouth.add(btnReset);
		pnlSouth.add(btnInput);
		pnlSouth.add(btnOutput);
		add(pnlSouth, "South");
		
		setSize(500, 500);
		
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	private void writeTextToFile(File dest, String text) {
		try (PrintWriter pw = new PrintWriter(dest);) {
			pw.print(text);
			pw.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private String readTextFromFile(File select) {
		StringBuilder sb = new StringBuilder();
		try (BufferedReader br = new BufferedReader(new FileReader(select))) {
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line).append("\n");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}
	
	public static void main(String[] args) {
		new Main();
	}
}

 

 

CSV 파일 읽기

 

CSV 파일은 딥러닝의 훈련 데이터 형식으로 많이 사용된다. CSV 파일은 텍스트 파일로서 콤마(,)로 데이터를 분리하여 제공한다.

자바에는 많은 CSV 파서 라이브러리가 있다. 하지만 간단한 CSV 파일은 핵심 자바만을 이용하여도 가능하다. 

FileReader, BufferedReader, String.split()만 사용하면 간단한 CSV 파일을 파싱할 수 있다. 

 

ex)

1. 자료 읽기 확인해보기

국가정보 한줄씩 읽어오기(첫번째 줄은 생략)
2. 데이터로 활용가능한 형 변환
3. 국가들의 인구 합

code,country,area,capital,population
KR,Korea,98480,Seoul,48422644
US,USA,9629091,Washington,310232863
JP,Japan,377835,Tokyo,127288000
CN,China,9596960,Beijing,1330044000
RU,Russia,17100000,Moscow,140702000

 

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Main2 {
	// 자료 읽기
	private static String readFile(File file) {
		StringBuilder sb = new StringBuilder();
		try (BufferedReader br = new BufferedReader(new FileReader(file));) {
			String line;
			line = br.readLine();
			while ((line = br.readLine()) != null) {
				sb.append(line).append("\n");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return sb.toString();
	}

	// 데이터로 활용가능한 형 변환
	private static Map<String, String[]> changeData(File file) {
		Map<String, String[]> countryData = new HashMap<>();
		try (BufferedReader br = new BufferedReader(new FileReader(file));) {
			String line;
			line = br.readLine();
			while ((line = br.readLine()) != null) {
				String[] data = line.split(",");
				countryData.put(data[0], data);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return countryData;
	}

	// 국가들의 인구 합
	private static int plusPeopleSum(Map<String, String[]> countryData) {
		int sum = 0;
		Set<Entry<String, String[]>> entrySet = countryData.entrySet();
		for (Entry<String, String[]> e : entrySet) {
			sum += Integer.valueOf(e.getValue()[4]);
		}
		return sum;
	}

	public static void main(String[] args) {
		File file = new File("d:\\myfolder\\country.csv");

		// 자료 읽기 확인해보기
		System.out.println(readFile(file));

		// 데이터로 활용가능한 형 변환
		Map<String, String[]> countryData = changeData(file);

		// 국가들의 인구 합
		plusPeopleSum(countryData);
		System.out.println(plusPeopleSum(countryData));

	}
}