본문 바로가기

Java 웹 개발

21.09.14 - 웹 개발 입문 25일차

24일차 과제 클래스로 구현해보기

package api.collection3;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class RentApp {
	private Map<String, Car> map = new HashMap<>();
	private Scanner sc = new Scanner(System.in);

	public RentApp() {
		// 데이터 추가
		map.put("스타렉스", new Car("스타렉스", 11, 150000));
		map.put("카니발", new Car("카니발", 7, 170000));
		map.put("그랜저", new Car("그랜저", 4, 200000));
	}

	public String menu() {// 메뉴
		System.out.println("<렌트카>");
		System.out.println("저희 렌트카는 항상 친절과 정성으로 고객을 모시겠습니다~");
		System.out.println("원하시는 명령을 입력해주세요");
		System.out.println("- 대여");
		System.out.println("- 반납");
		System.out.println("- 종료");
		System.out.print("명령 입력 : ");
		String command = sc.nextLine();
		return command;
	}

	public void exit() {// 종료
		System.out.println("프로그램을 종료합니다");
		sc.close();
		System.exit(0);
	}

	public void rental() {// 대여
		System.out.print("차량명 입력 : ");
		String name = sc.nextLine();

		if (map.containsKey(name)) {
			Car find = map.get(name);
			if (find.isRent()) {
				System.out.println("대여 가능한 차량입니다");
				find.rental();// find.setRent(false);//대여 처리
				System.out.println("대여 처리가 완료되었습니다");
			} else {
				System.out.println("대여중인 차량입니다");
			}
		} else {
			System.out.println("차량이 존재하지 않습니다");
		}
	}

	public void rentalReturn() {// 반납
		System.out.print("차량명 입력 : ");
		String name = sc.nextLine();

		if (map.containsKey(name)) {
			Car find = map.get(name);
			if (!find.isRent()) {
				System.out.println("반납 가능한 차량입니다");
				find.setRent(true);// 반납 처리
				System.out.println("반납 처리가 완료되었습니다");
			} else {
				System.out.println("대여중인 차량이 아닙니다");
			}
		} else {
			System.out.println("차량이 존재하지 않습니다");
		}
	}

	public void information() {
		System.out.println("잘못 입력하셨습니다");
	}

	public void action(String command) {
//		if(command.equals("종료")) {
//			this.exit();
//		}
//		else if(command.equals("대여")) {
//			this.rental();
//		}
//		else if(command.equals("반납")) {
//			this.rentalReturn();
//		}
//		else {
//			this.information();
//		}
		switch (command) {
		case "종료":
			this.exit();
			break;
		case "대여":
			this.rental();
			break;
		case "반납":
			this.rentalReturn();
			break;
		default:
			this.information();
			break;
		}
	}

	public void run() {
		while (true) {
			try {
				String command = this.menu();
				this.action(command);
			} catch (Exception e) {
				e.printStackTrace();
				System.out.println("오류 발생. 관리자에게 문의하세요");
			}
		}
	}
}

 

package api.collection3;

public class Test05_9 {
	public static void main(String[] args) {
		RentApp app = new RentApp();
		app.run();
	}
}

 

 

Collection - Map iteration

Q : Map이 개별 저장소인건 알겠는데... 전체 목록 출력은 아예 안되는건가?
A : 되긴 되는데... map에서 key 목록을 추출하는 명령이 필요하다.

 

Map에서 Key 만 뽑아서 생각해보면 Set 형태를 띈다고 볼 수 있다.
keySet() 명령을 사용하면 반환형이 Set이다.
key를 모두 열거한 다음 연결된 value를 불러오면 모든 데이터를 조회할 수 있다.

package api.collection3;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

public class Test06_1 {
	public static void main(String[] args) {

		// Map<String, Integer> map = new HashMap<>();
		Map<String, Integer> map = new TreeMap<>();

		map.put("피카츄", 75);
		map.put("라이츄", 65);
		map.put("파이리", 90);

		Set<String> set = map.keySet();
		for (String name : set) {
			System.out.println("name = " + name);
			System.out.println("score = " + map.get(name));
		}
	}
}

 

 

 

Collection - Stack, Queue

Stack과 Queue
Queue : 대기열. 줄을 서서 기다리는 형태. FIFO(선입선출) 구조
Stack :  출입구가 하나뿐인 저장소 형태. LIFO(후입선출) 구조
이러한 저장소들은 사용법이 정해져 있으므로 그 이외의 사용이 불가

 

package api.collection4;

import java.util.Stack;

public class Test01 {
	public static void main(String[] args) {

		Stack<String> st = new Stack<>();

		st.push("아이유");
		st.push("공유");
		st.push("이동욱");
		st.push("한지민");
		st.push("전지현");

		while(!st.empty()) {
			System.out.println(st.pop());
		}

	}
}

전지현
한지민
이동욱
공유
아이유

 

 

 

Stack 형식의 저장소를 사용하면 "이력 관리"를 할 수 있다.
되돌리기 명령 실행 시 pop() 을 통하여 나온 데이터를 이용하여 어떤 처리를 수행할 수 있다

package api.collection4;

import java.util.Stack;

public class Test02 {
	public static void main(String[] args) {

		Stack<String> history = new Stack<>();

		history.push("https://www.google.com");
		history.push("https://www.naver.com");
		history.push("https://www.daum.net");

		System.out.println(history.pop());
		System.out.println(history.pop());
		System.out.println(history.pop());
	}
}

https://www.daum.net
https://www.naver.com
https://www.google.com

 

 

 

Queue : FIFO(선입선출) 저장소
등록한 순서대로 추출이 가능하므로 작업 순서등을 설정할 때 유리

package api.collection4;

import java.util.Collection;
import java.util.Iterator;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class Test03 {
	public static void main(String[] args) {

		Queue<String> q = new ArrayBlockingQueue<>(10);

		q.add("아이유");
		q.add("공유");
		q.add("이동욱");
		q.add("한지민");
		q.add("전지현");

		System.out.println(q.peek());// 조회(누가 나올 차례인가요?)
		System.out.println(q);// 데이터 변화 없음
		System.out.println(q.poll());// 추출(나오세요!)
		System.out.println(q);// 데이터 사라짐
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q.poll());
		System.out.println(q);
	}
}

 

 

 

파일 - File 제어

파일(File)이란?
글자를 보관하기 위한 저장공간
파일의 크기 == 파일 안에 들어있는 글자의 크기

1. 일반적인 글자를 보관하기 위한 파일(텍스트 파일)
2. 특정 프로그램에서만 이해할 수 있는 파일(바이너리 파일)

File 클래스에서는 물리 저장소에 존재하는 파일을 제어할 수 있다.
해당하는 파일의 객체를 생성해야 제어가 가능하며, 생성을 위해서는 반드시 정보가 필요하다.
필요한 정보 : 파일이 위치한 경로와 파일의 이름
자바에서는 전체경로를 적지 않으면 프로젝트부터 계산한다

 

package api.io.file;

import java.io.File;

public class Test01 {
	public static void main(String[] args) {

		File a = new File("sample", "test.txt");//sample 폴더의 test.txt 관리 객체 생성!
		File b = new File("sample/test.txt");//sample/test.txt 관리 객체 생성!
		File c = new File("sample\\test.txt");//sample\test.txt 관리 객체 생성!

		//올바른 파일을 대상으로 생성하였는지 검사
		System.out.println(a.exists());//a의 대상 파일이 존재하는가?
		System.out.println(b.exists());//b의 대상 파일이 존재하는가?
		System.out.println(c.exists());//c의 대상 파일이 존재하는가?
	}
}

 

 

파일 정보 분석

package api.io.file;

import java.io.File;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test02 {
	public static void main(String[] args) {
		File f = new File("sample", "test.txt");
		System.out.println(f.exists());

		// 1. 파일명
		System.out.println(f.getName());
		// 2. 파일 위치(경로)
		// = 상대 경로란 특정 지점을 기준으로 계산한 경로를 의미한다(우리 옆집)
		// = 절대 경로란 어떠한 경우에도 변하지 않는 경로를 의미한다(집주소)
		System.out.println(f.getPath());// 상대경로(relative path)
		System.out.println(f.getAbsolutePath());// 절대경로(absolute path)
		// 3. 파일 크기 : 반환형이 long임을 주의해야 한다
		System.out.println(f.length());
		// 4. 최종 수정 시각 : 최신 파일 여부를 판단할 때 사용
		System.out.println(f.lastModified());

		Date d = new Date(f.lastModified());
		Format form = new SimpleDateFormat("yyyy-MM-dd E a h:mm:ss");
		System.out.println(form.format(d));

		// 5. 숨김 파일인지 확인
		System.out.println(f.isHidden());

		// 6. 읽기 전용인지 확인
		System.out.println(f.canRead());
		System.out.println(f.canWrite());
	}
}

 

 

 

자바에서는 파일 뿐만 아니라 폴더(디렉터리, Directroy)도 File 클래스로 제어가능
디렉터리란? 파일을 보관하기 위한 틀(껍데기, 통)
디렉터리는 크기가 없다

package api.io.file;

import java.io.File;

public class Test03 {
	public static void main(String[] args) {

		File dir = new File("sample");
		System.out.println(dir.exists());

		// 정보 분석
		// 1. 디렉터리는 크기가 없다.
		System.out.println(dir.length());

		// 2. 이름
		System.out.println(dir.getName());

		// 3. 경로
		System.out.println(dir.getPath());
		System.out.println(dir.getAbsolutePath());

		// 4. 내부의 파일 목록
		// = list() : 이름만 반환
		// = listFiles() : 파일 객체를 반환
		String[] names = dir.list();
		for (String name : names) {
			System.out.println(name);
		}

		File[] files = dir.listFiles();
		for (File f : files) {
			System.out.println(f);
			System.out.println("file? " + f.isFile());
			System.out.println("directory? " + f.isDirectory());
		}

	}
}

 

 

 

Q. 사용자에게 파일 또는 디렉터리의 경로를 입력받아 다음과 같이 처리하는 프로그램을 구현
1. 사용자가 입력한 경로가 `파일`인 경우 파일 정보 중 다음 내용을 출력
- 절대경로
- 파일 크기
- 최종 수정시각을 다음과 같이 출력(2021년 9월 14일 화 14시 53분 2초)
2. 사용자가 입력한 경로가 `디렉터리`인 경우 디렉터리 내부의 목록을 출력
- 내부 목록 중 파일은 이름 좌측에 [파일] 을 붙여서 출력
- 파일은 이름 우측에 크기를 붙여서 출력
- 내부 목록 중 디렉터리는 이름 좌측에 [폴더] 를 붙여서 출력
3. 사용자가 입력한 경로가 존재하지 않는 경로일 경우 다음 메세지를 출력
- 해당 경로는 존재하지 않습니다.

 

package api.io.file;

import java.io.File;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Test04_1 {
	public static void main(String[] args) {

//		경로 입력
		Scanner sc = new Scanner(System.in);
		System.out.print("경로 입력 : ");
		String path = sc.nextLine();
		sc.close();

//		파일 객체 생성
		File file = new File(path);

		if (file.exists()) {// 존재하는 경우(파일 또는 디렉터리)
			if (file.isFile()) {
				System.out.println("[파일 정보]");
				System.out.println("이름 : " + file.getName());
				System.out.println("절대경로 : " + file.getAbsolutePath());
				System.out.println("크기 : " + file.length() + " byte");
				Format f = new SimpleDateFormat("y년 M월 d일 E h시 m분 s초");
				Date d = new Date(file.lastModified());
				System.out.println("최종 수정 시각 : " + f.format(d));
			}
//			else if(file.isDirectory()) {
			else {
				System.out.println("[디렉터리 정보]");
				System.out.println("이름 : " + file.getName());

				File[] files = file.listFiles();
				for (File f : files) {
					if (f.isFile()) {
						System.out.println("--> [파일] " + f.getName() + " (" + f.length() + " bytes)");
					} else if (f.isDirectory()) {
						System.out.println("--> [폴더] " + f.getName());
					}
				}
			}
		} else {// 존재하지 않는 경우
			System.out.println("해당 경로는 존재하지 않습니다.");
		}
	}
}

 

경로 입력 : C:\Program Files\Java\jdk1.8.0_301
[디렉터리 정보]
이름 : jdk1.8.0_301
--> [폴더] bin
--> [파일] COPYRIGHT (3244 bytes)
--> [폴더] include
--> [파일] javafx-src.zip (5235470 bytes)
--> [파일] jmc.txt (195 bytes)
--> [폴더] jre
--> [폴더] legal
--> [폴더] lib
--> [파일] LICENSE (44 bytes)
--> [파일] README.html (159 bytes)
--> [파일] release (488 bytes)
--> [파일] src.zip (21176403 bytes)
--> [파일] THIRDPARTYLICENSEREADME-JAVAFX.txt (190 bytes)
--> [파일] THIRDPARTYLICENSEREADME.txt (190 bytes)

 

 

 

 

파일 - 경로이동 예제

경로 이동
상위 경로로 이동 또는 하위 경로로 이동

package api.io.file;

import java.io.File;

public class Test05 {
	public static void main(String[] args) {

		File f = new File("sample", "test.txt");
		f = f.getAbsoluteFile();// 절대 경로를 기준으로 파일 객체를 재생성
		System.out.println(f.getAbsolutePath());

		// 상위 경로로 이동(탐색기의 ↑ 화살표)
		// File dir = f의 상위 파일 객체;
		File dir = f.getParentFile();
		System.out.println(dir.getAbsolutePath());

		dir = dir.getParentFile();
		System.out.println(dir.getAbsolutePath());

		// 하위 경로로 이동(대상 디렉터리의 이름이 필요)
		dir = new File(dir, "sample");
		System.out.println(dir.getAbsolutePath());

	}
}

 

 

 

파일 - 생성 및 삭제

 파일 또는 디렉터리의 생성 및 삭제
 파일과 디렉터리는 생성 명령이 다르다
이름만으로는 파일인지 디렉터리인지 구분할 수 없기 때문에 명령 자체가 다르다

package api.io.file;

import java.io.File;

public class Test06 {
	public static void main(String[] args) {

		// 1. 디렉터리 생성
		File a = new File("sample/a/b/c/d");
		// boolean result = a.mkdir();//중간 경로가 없는 경우에는 생성하지 않는 명령
		boolean result = a.mkdirs();// 중간 경로까지 생성하는 명령
		System.out.println("result = " + result);

		// a.delete();

		// 응용 - 사용자 폴더에 academy 폴더 만들기
		String home = System.getProperty("user.home");
		System.out.println("home = " + home);
		File aca = new File(home, "academy");
		aca.mkdirs();
		System.out.println("폴더 생성 완료!");

		// aca.delete();

	}
}

result = false
home = C:\Users\user
폴더 생성 완료!

 

 

 

파일입출력 - 개요 및 싱글바이트 출력

 

 

Single Byte 출력
준비물 : FileOutputStream, File

package api.io.single;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Test01 {
	public static void main(String[] args) throws IOException {

		// 파일 생성
		File target = new File("sample", "single.txt");
		target.createNewFile();

		// 파일 출력 스트림 생성
		OutputStream out = new FileOutputStream(target);

		// 구조 : [프로그램] → out → target → [single.txt]

		// 파일 출력 :
		out.write(104);// h
		out.write(101);// e
		out.write(108);// l
		out.write(108);// l
		out.write(111);// o
		out.write(9);// tab(\t)
		out.write('J');
		out.write('a');
		out.write('v');
		out.write('a');
		out.write('\n');// enter(10)

		// byte를 초과한 데이터(50000 ---> 80로 강제변환)
		// =byte를 초과한 데이터 넣어도 의미없다
		// =단순하게 편의성을 위해 데이터 넣어도 의미없다
		// =50000 ---> (byte)50000 --->0
		out.write(50000);

		// 통로는 반드시 마지막에 닫아야한다(cf : Scanner)
		out.close();

	}
}

 

 

Single Byte 입력
준비물 : FileInputStream, File 객체

 

방법[1] File에 들어있는 byte 수만큼 읽어오도록 구현

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Test02_1 {
	public static void main(String[] args) throws IOException {

		File target = new File("sample", "single.txt");
		FileInputStream in = new FileInputStream(target);

		// 구조 : [프로그램] ← in ← target ← [single.txt]

		// [1] File에 들어있는 byte 수만큼 읽어오도록 구현

		for (long i = 0; i < target.length(); i++) {
			int data = in.read();
			System.out.println("data = " + data);
		}

		// 통로 정리
		in.close();
	}
}

 

방법[2] EOF(-1) 지점까지 읽도록 구현

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Test02_2 {
	public static void main(String[] args) throws IOException {

		File target = new File("sample", "single.txt");
		FileInputStream in = new FileInputStream(target);

		// 구조 : [프로그램] ← in ← target ← [single.txt]

		// [2] EOF(-1) 지점까지 읽도록 구현
		while (true) {
			int data = in.read();
			if (data == -1)
				break;
			System.out.println("data = " + data);
		}

		// 통로 정리
		in.close();
	}
}

 

 

 

- 과제

다음 요구사항에 맞게 파일을 만들고 입출력을 수행하세요.
- 요구사항
- 프로젝트 내의 sample 폴더에 origin.txt 파일을 만들고 "hello java!"를 5줄 작성한 뒤 저장
- 프로젝트 내의 sample 폴더에 copy.txt 파일을 만든다
- origin.txt 파일의 내용을 copy.txt에 복사한다.
- origin.txt의 내용을 불러와서 copy.txt 파일에 그대로 내보낸다
- 더이상 내보낼 데이터가 없을 때까지 동일한 작업을 반복한다.

 

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Test03 {
	public static void main(String[] args) throws Exception {

		// 1. origin.txt 생성
		File origin = new File("sample", "origin.txt");
//		origin.createNewFile();

		FileOutputStream originOut = new FileOutputStream(origin);

		for (int i = 0; i < 5; i++) {
			originOut.write('h');
			originOut.write('e');
			originOut.write('l');
			originOut.write('l');
			originOut.write('o');
			originOut.write('\t');
			originOut.write('J');
			originOut.write('a');
			originOut.write('v');
			originOut.write('a');
			originOut.write('!');
			originOut.write('\n');
		}

		originOut.close();

		// 2. copy.txt 생성
		File copy = new File("sample", "copy.txt");
//		copy.createNewFile();

		// 3. origin.txt → copy.txt 복사
		FileOutputStream copyOut = new FileOutputStream(copy);
		FileInputStream originIn = new FileInputStream(origin);

		while (true) {
			int data = originIn.read();
			if (data == -1)
				break;
			copyOut.write(data);
		}

		copyOut.close();
		originIn.close();

		// copy.delete();
	}
}