👇 공부한 자료들의 실제 소스파일들을 기록해논 공간입니다 👇
수업 시작 전
오늘은 예외 처리와 I/O입출력 공부를 한다고 하셨다
매일 조금씩 이런 내용들을 설명해주시는데 꼭 필요한 내용인 것 같다
이 내용을 이해하려면 부분부분 암기하려 하지 말고 어떻게 흘러가는 프로세스인지 이해하면서 암기해야 한다고 하셨다.
오늘 수업을 하실 예외와 에러의 차이도 잠깐 설명해주셨다
에러와 예외의 차이
에러는 컴파일도 안된다, 예외는 컴파일은 하되 실행 중에 발생된다
비유 : 소개팅하러 나갔더니 상대가 별로여서 인사하고 나갔다 ( 컴파일 ) , 결혼 후 상대배우자가 별로인데 참고 산다 ( 예외 )라고 비유를 해주셨다
예외는 많이 보는 게 좋지만 NullPointException은 자주 안 보는 게 좋다.
자바에서 File 시스템을 연결할 때 예외가 자주 나기 때문에 예외를 꼭 처리해야 한다
그래서 예외처리를 잘 알고 있어야 된다
예외처리
컴파일 실행 시 JVM에 main Thread가 생성된다
main 메서드를 호출한다
소스는 명령어의 집합이다. 실행 중이진 않는다
소스를 실행하게 하는 것이 Thread이다.
Thread 라인별로 읽어온다. 세미콜론으로 끝나는 걸 인식한다
Thread 개념
자바 소스를 실행하는 것이 Thread이다.
Thread가 있어야 실행 가능하다
Thread 마다 이름을 갖고 있는데 currentThread(). getName()을 쓰게 되면 이름을 가져온다
Thread.sleep은 잠시 Thread를 잠재운다는 의미다
현재는 main Thread 가 모든 처리를 해준다 : Single Thread
예시
Test 객체를 만들고 kkk() 메서드에 접근
main스레드는 객체를 만들고 t 참조 변수의 주소값을 참조하여 kkk() 메서드의
모든 명령어가 다 실행되면 리턴한다
> 예외처리 문법
try {
// 예외 발생 시 더 이상 소스를 처리하지 않고 catch 구문으로 넘어간다
} catch ( exception e ){
} finally {
}
예외처리 개념
직접 개발자가 예외를 처리하는 코드문법이다.
특징
예외 처리도 계층이 있다 : Exception이 가장 최상위 객체
예외가 발생 시 더 이상 코드를 실행하지 않고 catch구문으로 넘어간다
그리고 finally구간으로 넘어가고 예외 처리 로직을 마친다
예외가 발생될 경우 프로그램은 오동작 가능성이 높다, 그러하기 때문에 예외처리를 해주는 게 좋다
구문중 catch와 finally는 생략가능하다.
예외처리 구문에 finally는 예외 여부를 떠나서 무조건 실행되고 가장 마지막에 실행된다
자바에 예외처리를 꼭 해야 하는 경우가 있는데
예외처리가 필요한 경우는 운영체제 자원을 끌어다 쓰는 경우 꼭 예외처리를 해야 한다.
JVM혼자 처리 가능한 경우는 예외처리를 안 해도 된다
throws는 예외가 발생되었을 때 호출한 메서드에게 책임을 떠넘긴다
throws InterruptedException
책임 전가를 main까지 올라가게 되어 main도 책임 전가를 할 경우 JVM에게 책임이 넘어간다
지금처럼 kkk2() 호출한 구문으로 에러가 발생
해당 구문에도 throws시 또 책임을 떠넘긴다.
하지만 결국엔 처리를 해야 하기 때문에 언젠간 꼭 try ~ catch를 사용하여
처리할 수 있도록 해야 한다
예외 처리 메서드
e.printStackTrace() : 예외 문구 출력함
JAVA의 I/O 입출력
import 해야 하는 라이브러리
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
write : 쓰기
append : 추가하기
기본적인 로직은 이러하였다.
File file = new File("a.txt");
FileWriter a = null;
try{
a = new FileWriter(file);
a.write("abc\ncde\nfeg");
a.append("ggg");
} catch (Exception e){
} finally {
try {
// FileWriter 라는 녀석은 파일을 쓰기 위한 도구인데 운영체제에서 빌려서 쓴다
// 쓰고 난 뒤 운영체제에 반납하기 위해 close를 써야한다
a.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Scanner in = new Scanner(System.in);
System.out.print("생성 할 파일명 입력 >> ");
String fileName = in.nextLine();
File file = new File(fileName + ".txt");
FileWriter a = null;
try{
a = new FileWriter(file);
while (true){
System.out.println("글을 입력하세요, exit는 종료입니다 ");
String wLine = in.nextLine();
if (wLine.equals("exit".toLowerCase())) break;
a.write(wLine);
a.write("\n");
}
} catch (Exception e){
} finally {
try {
// FileWriter 라는 녀석은 파일을 쓰기 위한 도구인데 운영체제에서 빌려서 쓴다
// 쓰고 난 뒤 운영체제에 반납하기 위해 close를 써야한다
a.close();
} catch (IOException e) {
e.printStackTrace();
}
}
오늘의 문제 : 샘플 코드의 재 해석
샘플 코드를 이용하여 단어를 저장/전체 보기/수정/삭제 순으로 개발하기
기본적인 CRUD 콘셉트로 hashmap이나 list로 코드작성하는 게 목표
샘플 코드
Scanner in = new Scanner(System.in);
System.out.println("생성할 파일명을 입력하세요");
String fname=in.nextLine();
File file = new File(fname);
FileWriter a = null;
try {
a = new FileWriter(file);
while(true) {
System.out.println("글을 입력하세요. exit는 종료입니다");
String wLine=in.nextLine();
if(wLine.equals("exit")) break;
a.append(wLine);
a.append("\n");
}
} catch (Exception e) {
} finally {
try {
a.close();
} catch (IOException e) {
e.printStackTrace();
}
}
FileReader fr = null;
try {
char[] readL= new char[100];
fr = new FileReader("b.txt");
if(fr.read(readL) != -1) {
String k = new String(readL);
System.out.println(k);
String[] karry = k.split("\n");
for(String kk : karry) {
System.out.println(kk);
}
System.out.println(karry.length);
}
} catch (Exception e) {
e.printStackTrace();
}
문제 풀이 고민
- 시작 전 고민
hashmap을 쓸 것인지
인덱스번호가 생성되는 list를 쓸 것인지 고민한다.
리스트 번호와 번호를 같이 뿌려줄 경우?
hashmap이 과연 나은 선택인가?
list 컬렉션으로 관리하는 게 더 나은 선택인가?
1. 메모 생성 시나리오
사용자가 메모를 새로 생성한다
List를 사용하여 정상 메모 생성 시 memoList에 추가해 준다
예외가 발생된 경우 List에 추가되지 않도록 한다
2. 메모 전체 보기 시나리오
처음엔 List에 등록된 메모장 제목만 보여준다
전체 보기하고 싶은 List번호를 사용자는 키보드로 입력한다
번호 입력이 정상적인 경우 해당 제목의 파일에 내용을 전체다 읽어온다
3. 메모 수정 시나리오
메뉴 진입 시 리스트 번호와 제목을 보여준다
수정할 리스트 번호를 선택 후 진행한다
수정 로직은 새로운 파일을 하나 더 만든다 (기존파일명에. temp)를 추가한 파일
수정이 정상적으로 완료되면 새로운 파일을 생성해서 기존 파일명으로 바꿔준다.
수정 시 리스트 번호도 갱신된다
4. 메모 삭제 시나리오
메모 삭제 시 리스트 번호와 제목을 전체 보여준다
사용자는 삭제할 번호를 키보드에 입력한다
삭제가 완료되면 어떤 파일이 삭제되었는지 삭제된 메모장 이름을 적어주고 종료된다
Class Diagram
소스코드
package TeatCode;
/*
문제 : 샘플 코드를 이용하여 단어를 저장/전체보기/수정/삭제 순으로 개발
*/
public class a_FileO {
public static void main(String[] args) {
// todo : 단어장 프로그램 만들기 __ 프로그램 시작
new Controller();
}
}
package TeatCode;
import TeatCode.menu.*;
import java.util.ArrayList;
public class Controller {
private static ArrayList<String> memoList = new ArrayList<>();
// todo 단어장 만들기
// 필요 기능
// 1. 생성과 저장
// 2. 전체보기
// 3. 메모장 수정
// 4. 메모 삭제
// 전체적인 메뉴로 진입하고 memoList를 생성하는곳
public Controller(){
boolean flag = true;
while (flag){
Functions fn = new Functions();
info();
int userNum = Integer.parseInt(fn.inputKey("메뉴 번호"));
switch ( userNum ){
case 1 : // 메모 저장
new MemoWrite();
break;
case 2 : // 메모 전체보기
new MemoTOTview();
break;
case 3 : // 메모 수정
new MemoUpdate();
break;
case 4 : // 메모 삭제
new MemoDelete();
break;
case 5 :
System.out.println("프로그램을 종료합니다.");
flag = false;
break;
default :
System.out.println("잘못된 번호 입력입니다. 다시 입력하세요");
}
}
}
public static ArrayList<String> getMemoList() {
return memoList;
}
public static void setMemoList(String fileName, int num) {
// 1번은 파일제목 list컬렉션에 추가 , 2번은 삭제
if ( num == 1) memoList.add(fileName);
if ( num == 2 ) memoList.remove(fileName);
}
private void info(){
System.out.println("나만의 메모장 관리 입니다");
System.out.println("1. 새로운 메모");
System.out.println("2. 메모장 전체보기");
System.out.println("3. 메모 수정");
System.out.println("4. 메모 삭제");
System.out.println("5. 종료");
}
}
package TeatCode;
import java.util.ArrayList;
import java.util.Scanner;
import static TeatCode.Controller.getMemoList;
public class Functions {
// 간편한 기능들의 메서드를 모아논 클래스
ArrayList<String> memoList = null;
Scanner in = new Scanner(System.in);
// 기능 메서드
// 1. 키보드 입력 반환 메서드
public String inputKey (String text){
System.out.print("\t" + text + " 입력 >> ");
String userKeyInput = in.nextLine();
return userKeyInput;
}
// 기능 메서드
// 2. 등록된 모든 메모의 제목들을 출력해줌
public void prtMemoList(){
this.memoList = getMemoList();
int i = 1;
System.out.println("등록된 모든 메모의 제목입니다");
for ( String memo : memoList ){
System.out.println("List no."+ i + "\t Title : " + memo);
i++;
}
}
// 기능 메서드
// 3. 등록된 메모 목록에서 사용자가 수정,삭제 할 메모의 번호를 눌러주면 인덱스 번호를 반환해주는 메서드
public int selectMemoIdx(){
this.memoList = getMemoList();
int selNum = (Integer.parseInt(inputKey("메모 번호"))-1);
for (int i = 0; i < memoList.size(); i++) {
if ( selNum == i ) return i;
}
return -1;
}
}
package TeatCode.menu;
import TeatCode.Controller;
import TeatCode.Functions;
import java.io.File;
/*
메모 삭제 시나리오
메모 삭제 시 리스트 번호와 제목을 전체 보여준다
사용자는 삭제 할 번호를 키보드에 입력한다
삭제가 완료되면 어떤 파일이 삭제 되었는지 삭제된 메모장 이름을 적어주고 종료된다
*/
public class MemoDelete {
public MemoDelete() {
System.out.println("메모 삭제 메뉴입니다.");
Functions fn = new Functions();
fn.prtMemoList();
int selNum = fn.selectMemoIdx();
try {
String tmp = Controller.getMemoList().get(selNum);
File file = new File(tmp);
file.delete();
System.out.println(tmp + " 파일 삭제 완료");
Controller.setMemoList(tmp, 2);
} catch (Exception e) {
System.out.println("File not found");
}
}
}
package TeatCode.menu;
import TeatCode.Functions;
import java.io.FileReader;
import java.util.ArrayList;
import static TeatCode.Controller.getMemoList;
/*
메모 전체 보기 시나리오
처음엔 List에 등록된 메모장 제목만 보여준다
전체 보기 하고 싶은 List번호를 사용자는 키보드로 입력한다
번호 입력이 정상적인 경우 해당 제목의 파일에 내용을 전체다 읽어온다
*/
public class MemoTOTview {
ArrayList<String> memoList = null;
public MemoTOTview() {
// 메모 전체보기
// 시나리오 : 해당 메뉴 진입시 등록된 모든 메모의 제목을 보여준다
Functions fn = new Functions();
FileReader fileReader = null;
fn.prtMemoList();
this.memoList = getMemoList();
try {
int userNum = fn.selectMemoIdx();
char[] readText = new char[100];
fileReader = new FileReader(memoList.get(userNum));
if (fileReader.read(readText) != -1) {
String k = new String(readText);
String[] karry = k.split("\n");
for (String tmp : karry) System.out.println(tmp);
}
} catch (Exception e) {
} finally {
try {
fileReader.close();
} catch (Exception e) {
System.out.println("File not found");
}
}
}
}
package TeatCode.menu;
import TeatCode.*;
import java.io.*;
public class MemoUpdate {
/*
메모 수정 시나리오
메뉴 진입시 리스트 번호와 제목을 보여준다
수정할 리스트 번호를 선택 후 진행한다
수정 로직은 새로운 파일을 하나 더 만든다 (기존파일명에 .temp)를 추가한 파일
수정이 정상적으로 완료 되면 새로운 파일을 생성해서 기존 파일명으로 바꿔준다.
수정시 리스트 번호도 갱신된다
*/
public MemoUpdate() {
System.out.println("메모 수정 메뉴 입니다");
Functions fn = new Functions();
fn.prtMemoList();
int selNum = fn.selectMemoIdx();
String fileTitle = Controller.getMemoList().get(selNum);
File beforFile = new File(fileTitle); // inputFile
File afterFile = new File(fileTitle+".temp"); // outputFile
FileInputStream fileInputStream = null;
BufferedReader bufferedReader = null;
FileOutputStream fileOutputStream = null;
BufferedWriter bufferedWriter = null;
boolean result = false;
try {
fileInputStream = new FileInputStream(beforFile);
fileOutputStream = new FileOutputStream(afterFile);
bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream));
while (true) {
String writerLine = fn.inputKey("[exit - 종료] 글");
if (writerLine.toLowerCase().equals("exit")) break;
bufferedWriter.write(writerLine,0,writerLine.length());
bufferedWriter.newLine();
}
result = true;
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("File not found");
} finally {
// close할때는 하나씩 해조는게 좋다함
try {
bufferedReader.close();
} catch (IOException ex1) {
ex1.printStackTrace();
}
try {
bufferedWriter.close();
} catch (IOException ex2){
ex2.printStackTrace();
}
if (result){
beforFile.delete();
afterFile.renameTo(new File(fileTitle));
Controller.setMemoList(fileTitle, 2);
Controller.setMemoList(fileTitle, 1);
}
}
}
}
package TeatCode.menu;
import TeatCode.Controller;
import TeatCode.Functions;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MemoWrite {
/*
메모 생성 시나리오
사용자가 메모를 새로 생성한다
List를 사용하여 정상 메모 생성 시 memoList에 추가해준다
예외가 발생 된 경우 List에 추가되지 않도록 한다
*/
public MemoWrite() {
Functions fn = new Functions();
String fileName = fn.inputKey("새로 만들 폴더명");
File file = new File(fileName + ".txt");
FileWriter fileWriter = null;
String filename = file.getName();
try {
fileWriter = new FileWriter(file);
while (true) {
String writerLine = fn.inputKey("[exit - 종료] 글");
if (writerLine.toLowerCase().equals("exit")) break;
fileWriter.append(writerLine);
fileWriter.append("\n");
}
Controller.setMemoList(filename,1);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
'👩🏻💻 𝐋𝐚𝐧𝐠𝐮𝐚𝐠𝐞 > ⠀⠀⠀⠀ Jᴀᴠᴀ' 카테고리의 다른 글
2023/11/06 ✨ CRUD를 위한 첫걸음 (0) | 2023.11.07 |
---|---|
2023/11/03 🐰 개인 프로젝트/자유주제 (1) | 2023.11.04 |
2023/11/01 💛 HashMap (1) | 2023.11.01 |
2023/10/31 🤔 Collections Framework & ArrayList (1) | 2023.11.01 |
2023/10/30 📝 Getter & Setter (0) | 2023.11.01 |