본문 바로가기

Java 웹 개발

21.09.15 - 웹 개발 입문 26일차

-25일차 과제 정리

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.text.Format;

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

		//입력
		String originFileName = "sample/origin.txt";
		String copyFileName = "sample/copy.txt";

		//복사
		File originFile = new File(originFileName);
		File copyFile = new File(copyFileName);
		//copyFile.createNewFile();//출력 시 자동 생성되므로 생략 가능

		FileInputStream originFileStream = new FileInputStream(originFile);	
		FileOutputStream copyFileStream = new FileOutputStream(copyFile);

		//진행상황 표시
		//= 원본 파일의 byte 크기
		//= 복사 완료한 byte 크기
		Format f = new DecimalFormat("#,##0.00");
		long total = originFile.length();
		long count = 0L;
		while(true) {
			int data = originFileStream.read();
			if(data == -1) break;

			copyFileStream.write(data);
			count++;

			float percent = count * 100f / total;
			System.out.println("총 "+total+"byte 중 "+count+"byte 복사 완료("+f.format(percent)+" %)");
		}

		//stream 종료
		originFileStream.close();
		copyFileStream.close();

	}
}

 

총 60byte 중 1byte 복사 완료(1.67 %)
총 60byte 중 2byte 복사 완료(3.33 %)
총 60byte 중 3byte 복사 완료(5.00 %)
총 60byte 중 4byte 복사 완료(6.67 %)
총 60byte 중 5byte 복사 완료(8.33 %)
총 60byte 중 6byte 복사 완료(10.00 %)
총 60byte 중 7byte 복사 완료(11.67 %)
총 60byte 중 8byte 복사 완료(13.33 %)
총 60byte 중 9byte 복사 완료(15.00 %)
총 60byte 중 10byte 복사 완료(16.67 %)
총 60byte 중 11byte 복사 완료(18.33 %)
총 60byte 중 12byte 복사 완료(20.00 %)
총 60byte 중 13byte 복사 완료(21.67 %)
총 60byte 중 14byte 복사 완료(23.33 %)
총 60byte 중 15byte 복사 완료(25.00 %)
총 60byte 중 16byte 복사 완료(26.67 %)
총 60byte 중 17byte 복사 완료(28.33 %)
총 60byte 중 18byte 복사 완료(30.00 %)
총 60byte 중 19byte 복사 완료(31.67 %)
총 60byte 중 20byte 복사 완료(33.33 %)
총 60byte 중 21byte 복사 완료(35.00 %)
총 60byte 중 22byte 복사 완료(36.67 %)
총 60byte 중 23byte 복사 완료(38.33 %)
총 60byte 중 24byte 복사 완료(40.00 %)
총 60byte 중 25byte 복사 완료(41.67 %)
총 60byte 중 26byte 복사 완료(43.33 %)
총 60byte 중 27byte 복사 완료(45.00 %)
총 60byte 중 28byte 복사 완료(46.67 %)
총 60byte 중 29byte 복사 완료(48.33 %)
총 60byte 중 30byte 복사 완료(50.00 %)
총 60byte 중 31byte 복사 완료(51.67 %)
총 60byte 중 32byte 복사 완료(53.33 %)
총 60byte 중 33byte 복사 완료(55.00 %)
총 60byte 중 34byte 복사 완료(56.67 %)
총 60byte 중 35byte 복사 완료(58.33 %)
총 60byte 중 36byte 복사 완료(60.00 %)
총 60byte 중 37byte 복사 완료(61.67 %)
총 60byte 중 38byte 복사 완료(63.33 %)
총 60byte 중 39byte 복사 완료(65.00 %)
총 60byte 중 40byte 복사 완료(66.67 %)
총 60byte 중 41byte 복사 완료(68.33 %)
총 60byte 중 42byte 복사 완료(70.00 %)
총 60byte 중 43byte 복사 완료(71.67 %)
총 60byte 중 44byte 복사 완료(73.33 %)
총 60byte 중 45byte 복사 완료(75.00 %)
총 60byte 중 46byte 복사 완료(76.67 %)
총 60byte 중 47byte 복사 완료(78.33 %)
총 60byte 중 48byte 복사 완료(80.00 %)
총 60byte 중 49byte 복사 완료(81.67 %)
총 60byte 중 50byte 복사 완료(83.33 %)
총 60byte 중 51byte 복사 완료(85.00 %)
총 60byte 중 52byte 복사 완료(86.67 %)
총 60byte 중 53byte 복사 완료(88.33 %)
총 60byte 중 54byte 복사 완료(90.00 %)
총 60byte 중 55byte 복사 완료(91.67 %)
총 60byte 중 56byte 복사 완료(93.33 %)
총 60byte 중 57byte 복사 완료(95.00 %)
총 60byte 중 58byte 복사 완료(96.67 %)
총 60byte 중 59byte 복사 완료(98.33 %)
총 60byte 중 60byte 복사 완료(100.00 %)

 

 

 

- 용량이 많은 파일 복사하기

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.DecimalFormat;
import java.text.Format;

public class Test03_6 {
	public static void main(String[] args) throws Exception {
		// 입력
		String originFileName = "D:/jdk-8u301-windows-x64.exe";// 약 200MB
		String copyFileName = "D:/copy.exe";

		// 복사
		File originFile = new File(originFileName);
		File copyFile = new File(copyFileName);
		// copyFile.createNewFile();//출력 시 자동 생성되므로 생략 가능

		FileManager.copyFile(originFile, copyFile, true);// debug on(진행상황 표시)
	}
}

--> 1byte씩 변환해서 복사하므로 엄청 오래걸린다...

 Q : Single-Byte 입출력에서 성능 저하가 발생하는 원인
A : 자바의 특징
운영체제에 독립적이고 이식성이 뛰어나다
운영체제와 별로 안친하다
운영체제의 허락(System call)이 필요한 작업이 오래 걸린다
해결책 :
운영체제와 친해진다(Java의 장점이 다 사라짐)
운영체제의 허락을 최대한 적게 받는다(ex : 1개씩 옮기는게 아니라 100개씩 옮긴다면?)
1개씩 옮기면 100개를 옮기는데 100번의 허락이 필요
100개씩 옮기면 100개를 옮기는데 1번의 허락이 필요
묶음으로 옮기기 위해 생성하는 임시 저장소를 버퍼(Buffer)라고 부른다

 

 

파일입출력 - 버퍼를 활용한 싱글바이트 입출력

버퍼(Buffer)를 사용하여 한 번에 여러 개의 바이트 읽기
파일마다 크기(byte수)가 다르다
buffer를 만들 때 일정 크기를 지정해서 만들어야 한다.
"적당한" 크기가 얼마인지에 대해서 이해할 필요가 있다.

 

ex : 버퍼 크기를 5로 설정하여 읽어들이는 예제(현재 파일크기는 14byte)

--> 예상 시나리오
--> 첫 번째 읽으면 : 5byte
--> 두 번째 읽으면 : 5byte
--> 세 번째 읽으면 : 4byte

 

- 출력

package api.io.single;

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

public class Test04 {

		File target = new File("sample", "single.txt");
		OutputStream out = new FileOutputStream(target);

		byte[] buffer = new byte[] { 104, 101, 108, 108, 111 };

		out.write(buffer);// buffer에 들어있는 값을 전부 출력하세요

		out.write('\n');

		out.write(buffer, 0, 4);// buffer에 들어있는 값을 0번위치부터 4개 출력

		out.write('\n');

		out.write(buffer, 1, 3);// buffer에 들어있는 값을 1번위치부터 3개 출력

		out.close();
	}
}

 

- 입력

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

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

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

		byte[] buffer = new byte[5];

		int n = in.read(buffer);
		System.out.println("n = " + n);
		System.out.println("buffer = " + Arrays.toString(buffer));

		//통로 종료
		in.close();
	}
}

 

- 입력 정리

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

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

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

		byte[] buffer = new byte[5];

		while (true) {
			int size = in.read(buffer);
			if (size == -1)
				break;
			System.out.println("size = " + size);
			System.out.println("buffer = " + Arrays.toString(buffer));
		}

		// 통로 종료
		in.close();
	}
}

size = 5
buffer = [104, 101, 108, 108, 111]
size = 5
buffer = [10, 104, 101, 108, 108]
size = 4
buffer = [10, 101, 108, 108, 108]

 

 

-> (1) 복사 프로그램을 byte[] 입출력으로 변경 

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

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

		String originFileName = "sample/origin.txt";
		String copyFileName = "sample/copy.txt";

		File originFile = new File(originFileName);
		File copyFile = new File(copyFileName);

		InputStream originFileStream = new FileInputStream(originFile);
		OutputStream copyFileStream = new FileOutputStream(copyFile);

		// 구조 : [origin.txt] → originFile → originFileStream
		// → [프로그램] → copyFileStream → copyFile → [copy.txt]
		byte[] buffer = new byte[5];

		int size = originFileStream.read(buffer);
		copyFileStream.write(buffer);

		// 통로 종료
		originFileStream.close();
		copyFileStream.close();

	}
}

-> (2) 복사 프로그램을 byte[] 입출력으로 변경 

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.Format;

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

		String originFileName = "sample/origin.txt";
		String copyFileName = "sample/copy.txt";

		File originFile = new File(originFileName);
		File copyFile = new File(copyFileName);

		InputStream originFileStream = new FileInputStream(originFile);
		OutputStream copyFileStream = new FileOutputStream(copyFile);

		//구조 : [origin.txt] → originFile → originFileStream 
		//					→ [프로그램] → copyFileStream → copyFile → [copy.txt]
		byte[] buffer = new byte[5];

		//진행상황 확인 코드 추가
		Format f = new DecimalFormat("#,##0.00");
		long total = originFile.length();
		long count = 0L;

		while(true) {
			int size = originFileStream.read(buffer);
			if(size == -1) break;
			copyFileStream.write(buffer, 0, size);//+0부터 size개만큼 출력

			count += size;
			float percent = count * 100f / total;
			System.out.println("총 "+total+"바이트 중 "+count+"바이트 복사 완료 ("+f.format(percent)+" % )");
		}

		//통로 종료
		originFileStream.close();
		copyFileStream.close();

	}
}

총 60바이트 중 5바이트 복사 완료 (8.33 % )
총 60바이트 중 10바이트 복사 완료 (16.67 % )
총 60바이트 중 15바이트 복사 완료 (25.00 % )
총 60바이트 중 20바이트 복사 완료 (33.33 % )
총 60바이트 중 25바이트 복사 완료 (41.67 % )
총 60바이트 중 30바이트 복사 완료 (50.00 % )
총 60바이트 중 35바이트 복사 완료 (58.33 % )
총 60바이트 중 40바이트 복사 완료 (66.67 % )
총 60바이트 중 45바이트 복사 완료 (75.00 % )
총 60바이트 중 50바이트 복사 완료 (83.33 % )
총 60바이트 중 55바이트 복사 완료 (91.67 % )
총 60바이트 중 60바이트 복사 완료 (100.00 % )

 

 

- 버퍼로 용량이 많은 파일 복사하기

package api.io.single;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.Format;

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

		String originFileName = "D:/jdk-8u301-windows-x64.exe";// 약 200MB
		String copyFileName = "D:/copy.exe";

		File originFile = new File(originFileName);
		File copyFile = new File(copyFileName);

		InputStream originFileStream = new FileInputStream(originFile);
		OutputStream copyFileStream = new FileOutputStream(copyFile);

		// 구조 : [origin.txt] → originFile → originFileStream
		// → [프로그램] → copyFileStream → copyFile → [copy.txt]
		byte[] buffer = new byte[8192];

		// 진행상황 확인 코드 추가
		Format f = new DecimalFormat("#,##0.00");
		long total = originFile.length();
		long count = 0L;

		long start = System.currentTimeMillis();

		while (true) {
			int size = originFileStream.read(buffer);
			if (size == -1)
				break;
			copyFileStream.write(buffer, 0, size);// +0부터 size개만큼 출력

			count += size;
			float percent = count * 100f / total;
			System.out.println("총 " + total + "바이트 중 " + count + "바이트 복사 완료 (" + f.format(percent) + " % )");
		}

		long finish = System.currentTimeMillis();
		long time = finish - start;
		System.out.println("소요시간 : " + time + "ms");

		// 통로 종료
		originFileStream.close();
		copyFileStream.close();

	}
}

 

 

디렉터리 복사
디렉터리는 크기가 없으며 단지 파일을 묶어두는 역할만 수행
디렉터리를 복사한다면 목적지에 디렉터리를 만든 뒤 내용물을 복사한다!

 

 

 

 

파일입출력 - 멀티바이트 입/출력

- Multi-Byte 출력
원시형 데이터 및 UTF-8 문자열에 대한출력
자료형마다 분해 및 조립방법이 다르므로 명령 종류가 다르다
기본적으로 여러 조각의 바이트를 출력 또는 입력해야하므로 버퍼를 무조건 사용해야 한다
Single-Byte 보다 필요한 도구가 많아진다.

package api.io.multi;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

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

		// 준비물 :
		// -분해도구(DataOutputStream)
		// -버퍼(BufferedOutputStream)
		// -출력스트림(FileoutputStream)
		// -출력대상 파일(File)

		File target = new File("sample", "multi.txt");
		FileOutputStream out = new FileOutputStream(target);
		BufferedOutputStream buffer = new BufferedOutputStream(out);// 8192 byte
//		BufferedOutputStream buffer = new BufferedOutputStream(out,4096);//크기 지정
		DataOutputStream data = new DataOutputStream(buffer);

//		구조 : [프로그램] → data → buffer → out → target → [multi.txt]

//		data를 이용하여 출력 명령을 수행
//		=.write() 대신 자료형별로 준비된 명령을 사용
		data.writeInt(100); // 100을 int에 맞게 분해하세요(--> 버퍼로 가세요. 4/8192)
		data.writeDouble(100); // 100을 double에 맞게 분해하세요(--> 버퍼로 가세요. 12/8192)
		data.writeFloat(100); // 100을 float에 맞게 분해하세요(--> 버퍼로 가세요. 16/8192)
		data.writeChar(100); // 100을 char에 맞게 분해하세요(--> 버퍼로 가세요. 18/8192)
		data.writeByte(100); // 100을 byte에 맞게 분해하세요(--> 버퍼로 가세요. 19/8192)
		data.writeShort(100); // 100을 short에 맞게 분해하세요(--> 버퍼로 가세요. 21/8192)
		data.writeLong(100); // 100을 long에 맞게 분해하세요(--> 버퍼로 가세요. 29/8192)
		data.writeBoolean(true); // true를 boolean에 맞게 분해하세요(--> 버퍼로 가세요. 30/8192)

//		버퍼는 저장공간이 꽉 찬 경우만 자동 출력을 수행한다.
//		그 외의 상황이라면 수동 출력(flush)을 수행해야 한다.

//		data.flush();
		data.close();// close() 하면 자동으로 flush() 수행된다.
	}
}

 

- Multi-Byte 입력

package api.io.multi;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

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

		//준비물 : 
		//- 조립 도구(DataInputStream)
		//- 버퍼(BufferedInputStream)
		//- 입력스트림(FileInputStream)
		//- 입력 파일 객체(File)

		//도구 생성
		File target = new File("sample", "multi.txt");
		FileInputStream in = new FileInputStream(target);
		BufferedInputStream buffer = new BufferedInputStream(in);
		DataInputStream data = new DataInputStream(buffer);

		//[프로그램] ← data ← buffer ← in ← target ← [multi.txt]

		int a = data.readInt();					//파일에서 4byte를 읽어 int 형태로 조립한 뒤 반환
		double b = data.readDouble();		//파일에서 8byte를 읽어 double 형태로 조립한 뒤 반환
		float c = data.readFloat();			//파일에서 4byte를 읽어 float 형태로 조립한 뒤 반환
		char d = data.readChar();				//파일에서 2byte를 읽어 char 형태로 조립한 뒤 반환
		byte e = data.readByte();				//파일에서 1byte를 읽어 byte 형태로 조립한 뒤 반환
		short f = data.readShort();			//파일에서 2byte를 읽어 short 형태로 조립한 뒤 반환
		long g = data.readLong();			//파일에서 8byte를 읽어 long 형태로 조립한 뒤 반환
		boolean h = data.readBoolean();	//파일에서 1byte를 읽어 boolean 형태로 조립한 뒤 반환

		//통로 정리
		data.close();//--> buffer.close() --> in.close()

		System.out.println("a = " + a);
		System.out.println("b = " + b);
		System.out.println("c = " + c);
		System.out.println("d = " + d);
		System.out.println("e = " + e);
		System.out.println("f = " + f);
		System.out.println("g = " + g);
		System.out.println("h = " + h);
	}
}

a = 100
b = 100.0
c = 100.0
d = d
e = 100
f = 100
g = 100
h = true

 

 

Q. 이번주 로또번호 6개를 추첨하여 오름차순으로 정렬한 뒤 `sample/lotto.txt`에 저장

package api.io.multi;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Test03_1 {
	public static void main(String[] args) throws IOException {
		//로또번호 6개를 sample/lotto.txt에 저장
		//-> 복원추출, 비복원추출

		List<Integer> numbers = new ArrayList<>();
		for(int i=1; i<=45; i++) {
			numbers.add(i);
		}

		Collections.shuffle(numbers);

		List<Integer> partList = numbers.subList(0, 6);
		Collections.sort(partList);

		System.out.println(partList);

		//멀티바이트 출력 준비
		File target = new File("sample", "lotto.txt");
		FileOutputStream out = new FileOutputStream(target);
		BufferedOutputStream buffer = new BufferedOutputStream(out);
		DataOutputStream data = new DataOutputStream(buffer);

		for(int n : partList) {
			data.writeInt(n);
		}

		data.close();
	}
}

 

Q. sample/lotto.txt`에 저장된 로또번호를 불러와서 화면에 출력

package api.io.multi;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;

public class Test04_3 {
	public static void main(String[] args) throws IOException {
		//sample/lotto.txt 에 저장된 로또번호를 불러와서 화면에 출력

		Set<Integer> set = new TreeSet<>();

		//도구 생성
		File target = new File("sample", "lotto.txt");
		FileInputStream in = new FileInputStream(target);
		BufferedInputStream buffer = new BufferedInputStream(in);
		DataInputStream data = new DataInputStream(buffer);

		for(int i=0; i < 6; i++) {
			set.add(data.readInt());
		}
		data.close();

		System.out.println(set);
	}
}

[3, 14, 17, 30, 35, 44]

 

 

파일입출력 - 객체입출력 개요

객체 입출력(Object I/O)
객체는 만들어봐야 크기를 알 수 있다(new)
여러 개의 데이터가 섞여있으므로 얇게 펼쳐서 분해를 해야 한다

얇게 펼치는 작업을 직렬화(Serialize)라고 부른다
객체를 분해하면 다수의 byte 조각이 나오게 되므로 버퍼(Buffer)가 필요하다.

 

 

- 객체출력 

package api.io.object;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;

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

		////////////////////////////////////////////////////////////////////////////
		// 주의 ! 자격이 없는 클래스는 객체 입출력이 불가능하다(java.io.Serializable 인터페이스 상속여부)
		////////////////////////////////////////////////////////////////////////////

		//필요 도구
		//= 직렬화 및 분해 도구(ObjectOutputStream)
		//= 버퍼(BufferedOutputStream)
		//= 출력스트림(FileOutputStream)
		//= 출력 대상 파일 객체(File)

		File target = new File("sample", "time.h");
		FileOutputStream out = new FileOutputStream(target);
		BufferedOutputStream buffer = new BufferedOutputStream(out);
		ObjectOutputStream oData = new ObjectOutputStream(buffer);

		//[프로그램] → oData → buffer → out → target → [time.kh]

		Date d = new Date();
		oData.writeObject(d);//d라는 객체를 펼쳐서 뿌셔서 출력해라(--> 버퍼로 이동)

		//oData.flush();//buffer가 꽉 찬 상태가 아닐 때 강제로 비우는 명령
		oData.close();
	}
}

 

- 객체 입력

package api.io.object;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test03 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
	
		//필요 도구
		//= 역직렬화 및 조립 도구(ObjectInputStream)
		//= 버퍼(BufferedInputStream)
		//= 입력스트림(FileInputStream)
		//= 입력 파일 객체(File)

		File target = new File("sample", "time.h");
		FileInputStream in = new FileInputStream(target);
		BufferedInputStream buffer = new BufferedInputStream(in);
		ObjectInputStream oData = new ObjectInputStream(buffer);
//		ObjectInputStream oData = new ObjectInputStream(
//															new BufferedInputStream(
//																	new FileInputStream(target)));

//		주의 : 보관형태가 Object이기 때문에, 반드시 원래 형태로 다운캐스팅을 해야 사용 가능
		Date d = (Date)oData.readObject();

		oData.close();

		System.out.println(d);
		Format f = new SimpleDateFormat("yyyy-MM-dd");
		System.out.println(f.format(d));
	}
}

Wed Sep 15 22:08:00 KST 2021
2021-09-15

 

 

Q. 객체 입출력으로 로또 구현해보기

package api.io.object;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

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

		// 로또번호 추첨
		Random r = new Random();
		Set<Integer> lotto = new TreeSet<>();

		while (lotto.size() < 6) {
			int number = r.nextInt(45) + 1;
			lotto.add(number);
		}

		System.out.println(lotto);

//		객체 출력
		File target = new File("sample", "lotto2.txt");
		FileOutputStream out = new FileOutputStream(target);
		BufferedOutputStream buffer = new BufferedOutputStream(out);
		ObjectOutputStream oData = new ObjectOutputStream(buffer);
//		ObjectOutputStream oData = new ObjectOutputStream(
//															new BufferedOutputStream(
//																	new FileOutputStream(target)));

		oData.writeObject(lotto);

		oData.close();// flush+close
		System.out.println("로또번호 생성이 완료되었습니다");

	}
}

 

package api.io.object;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Set;

public class Test04 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {

		// 도구 준비
		File target = new File("sample", "lotto2.txt");
		if (!target.exists()) {
			System.err.println("파일이 존재하지 않습니다");
			System.exit(-1);
		}

		FileInputStream in = new FileInputStream(target);
		BufferedInputStream buffer = new BufferedInputStream(in);
		ObjectInputStream oData = new ObjectInputStream(buffer);

		// 경고는 Set의 내용물까지는 확신할 수 없기 때문에 발생한다.
		Set<Integer> lotto = (Set<Integer>) oData.readObject();

		oData.close();

		for (int number : lotto) {
			System.out.println(number);
		}
	}
}

14
21
36
37
42
45

 

 

내가 만든 클래스의객체 입출력

= java.io.Serializable을 상속받으면 가능

 

 

POJO(Plain Old Java Object) 클래스
파일입출력에 이 클래스를 활용할 계획이 있다면 java.io.Serializable을 상속받아 자격을 획득해야 한다
= 마킹 인터페이스(Marking Interface)

package api.io.object;

import java.io.Serializable;

//클래스에 부여할 수 있는 옵션
//1. transient 키워드를 이용해서 특정 필드를 입출력에서 제외할 수 있다.
//2. 클래스의 버전(SerialVersionUID)을 설정할 수 있다.
// = 클래스의 버전을 바꾸면 이전 버전의 모든 저장된 데이터를 사용할 수 없다.
// = 강제 업데이트를 시킬 수 있다.
public class Student implements Serializable {

	private static final long serialVersionUID = 2L;

	private String name;
	private int score;
	private transient String hobby;// 입출력 제외 설정(transient)

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	public String getHobby() {
		return hobby;
	}

	public void setHobby(String hobby) {
		this.hobby = hobby;
	}

	public Student(String name, int score, String hobby) {
		super();
		this.name = name;
		this.score = score;
		this.hobby = hobby;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", score=" + score + ", hobby=" + hobby + "]";
	}
}

 

- 출력

package api.io.object;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

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

		File target = new File("sample", "student.txt");
		FileOutputStream out = new FileOutputStream(target);
		BufferedOutputStream buffer = new BufferedOutputStream(out);
		ObjectOutputStream oData = new ObjectOutputStream(buffer);

		Student stu = new Student("피카츄", 80, "게임");

		oData.writeObject(stu);

		oData.close();
	}
}

- 입력

package api.io.object;

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

public class Test06 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {

		File target = new File("sample", "student.kh");
		FileInputStream in = new FileInputStream(target);
		BufferedInputStream buffer = new BufferedInputStream(in);
		ObjectInputStream oData = new ObjectInputStream(buffer);

		Student stu = (Student) oData.readObject();

		oData.close();

		System.out.println(stu);
	}
}

Student [name=피카츄, score=80, hobby=null]