inputstream_read
package sec02.exam01_inputstream_read;
import java.io.FileInputStream;
import java.io.InputStream;
public class ReadExample1 {
public static void main(String[] args) throws Exception{
InputStream is= new FileInputStream("C:/Temp/test.txt"); // <- 5바이트임. 1바이트씩 읽는다. 바이트는 1바이트씩 4바이트 int의 끝자락에 붙어서 저장된다.
int readByte;
while((readByte = is.read()) != -1) { //5바이트므로, 총 5번 돈다. 6바이트 읽을때에 -1이 들어가서 빠져나간다.
System.out.println(readByte);
}
/*
97
98
99
100
101
*/ //이렇게 출력된다.
System.out.println();
//이렇게 작성해도 된다.
is= new FileInputStream("C:/Temp/test.txt");
while(true) {
readByte = is.read();
if(readByte == -1) break;
System.out.println((char)readByte); //char 로 강제 타입 변환하면 문자가 출력된다.
}
is.close();
}
}
package sec02.exam01_inputstream_read;
import java.io.FileInputStream;
import java.io.InputStream;
public class ReadExample2 {
public static void main(String[] args) throws Exception{
InputStream is =new FileInputStream("C:/Temp/test.txt");
int readByteNo;
byte[] readBytes = new byte[3];
String data = "";
while((readByteNo = is.read(readBytes)) != -1) {
System.out.println(readByteNo);// 3 2 가 출력됨. 3개 읽고, 2개 읽어서...
data += new String(readBytes,0,readByteNo); //readBytes에 저장된 0부터 readByteNo까지 읽어서 문자열로 저장 .
}
System.out.println(data);
is.close();
}
}
package sec02.exam01_inputstream_read;
import java.io.FileInputStream;
import java.io.InputStream;
public class ReadExample3 {
public static void main(String[] args) throws Exception{
InputStream is =new FileInputStream("C:/Temp/test.txt");
int readByteNo;
byte[] readBytes = new byte[8];
readByteNo = is.read(readBytes,2,3); //인덱스 2부터 3개를 읽어서 readBytes에 저장
for(int i = 0;i<readBytes.length;i++) {
System.out.println(readBytes[i]); //즉 비어있는 나머지는 0으로 출력된다. 인덱스 2부터 3칸까지만 97 98 99 가 저장된것을 확인할 수 있다.
}
is.close();
}
}
outputstream_write
package sec02.exam02_outputstream_write;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteExample1 {
public static void main(String[] args) throws Exception{
OutputStream os = new FileOutputStream("C:/Temp/test.txt");
byte[] data = "ABC".getBytes();
for(int i = 0;i<data.length;i++) {
os.write(data[i]);
}
os.flush();
// flush -> 가능하면 이걸 꼭 써주세요.
//출력 스트림에서 write를 하면 데이터가 잠시 버퍼에 쌓였다가 출력이 되는데, 버퍼가 꽉 차지 않으면 출력이 되지 않는다.
//그래서 강제적으로 출력하라는 뜻으로 flush를 사용하는 것이다.
os.close();
}
}
package sec02.exam02_outputstream_write;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteExample2 {
public static void main(String[] args) throws Exception{
OutputStream os = new FileOutputStream("C:/Temp/test.txt");
byte[] data = "ABC".getBytes();
os.write(data); //바이트 배열을 줘서 한번에 쭉 출력한다.
os.flush();
os.close();
}
}
package sec02.exam02_outputstream_write;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class WriteExample3 {
public static void main(String[] args) throws Exception{
OutputStream os = new FileOutputStream("C:/Temp/test.txt");
byte[] data = "ABC".getBytes();
os.write(data,1,2); //바이트 배열을 줘서 한번에 쭉 출력한다. 시작인덱스와 문자개수이다.
os.flush(); //반드시 flush해줘라...
os.close(); //더이상 사용하지 않을때는 닫아주고.
}
}
reader_read
package sec02.exam03_reader_read;
import java.io.FileReader;
import java.io.Reader;
public class ReadExample1 {
public static void main(String[] args) throws Exception{
//이 에제 실행했을 경우에 문자가 깨져서 출력된다... 왜그런지 모르겠네... 다른게 없는데.
Reader reader = new FileReader("C:/Temp/test.txt");
int readData;
while((readData = reader.read()) != -1) {
System.out.print((char)readData);
}
reader.close();
}
}
package sec02.exam03_reader_read;
import java.io.FileReader;
import java.io.Reader;
public class ReadExample2 {
public static void main(String[] args) throws Exception{
Reader reader = new FileReader("C:/Temp/test.txt");
int readCharNo;
char[] cbuf = new char[4];
readCharNo = reader.read(cbuf,1,2);
for(int i = 0;i<cbuf.length;i++) {
System.out.println(cbuf[i]);
}
reader.close();
}
}
package sec02.exam03_reader_read;
import java.io.FileReader;
import java.io.Reader;
public class ReadExample3 {
public static void main(String[] args) throws Exception{
Reader reader = new FileReader("C:/Temp/test.txt");
int readCharNo;
char[] cbuf = new char[2];
String data = "";
while((readCharNo = reader.read(cbuf)) != -1) {
data += new String(cbuf,0,readCharNo);
}
System.out.println(data);
reader.close();
}
}
writer_write
package sec02.exma04_writer_write;
import java.io.FileWriter;
import java.io.Writer;
public class WriteExample1 {
public static void main(String[] args) throws Exception{
Writer writer = new FileWriter("C:/Temp/test.txt");
char[] data = "홍길동".toCharArray();
for(int i = 0;i<data.length;i++) {
writer.write(data[i]);
}
writer.flush(); //버퍼 강제로 비우기
writer.close();
}
}
package sec02.exma04_writer_write;
import java.io.FileWriter;
import java.io.Writer;
public class WriteExample2 {
public static void main(String[] args) throws Exception{
Writer writer = new FileWriter("C:/Temp/test.txt");
char[] data = "홍길동".toCharArray();
writer.write(data); //모든 문자를 출력 / for문보다 효율적이다.
writer.flush(); //버퍼 강제로 비우기
writer.close();
}
}
package sec02.exma04_writer_write;
import java.io.FileWriter;
import java.io.Writer;
public class WriteExample3 {
public static void main(String[] args) throws Exception{
Writer writer = new FileWriter("C:/Temp/test.txt");
char[] data = "홍길동".toCharArray();
writer.write(data,1,2); //시작인덱스와 쓸 문자 수
writer.flush(); //버퍼 강제로 비우기
writer.close();
}
}
package sec02.exma04_writer_write;
import java.io.FileWriter;
import java.io.Writer;
public class WriteExample4 {
public static void main(String[] args) throws Exception{
Writer writer = new FileWriter("C:/Temp/test.txt");
String data = "안녕 자바 프로그램";
// writer.write(data);
writer.write(data,3,2);//자바 가 저장됨.
writer.flush(); //버퍼 강제로 비우기
writer.close();
}
}
system_in_out
package sec03.exam01_system_in_out;
import java.io.InputStream;
public class SystemInExample1 {
public static void main(String[] args) throws Exception{
System.out.println("==메뉴==");
System.out.println("1. 예금 조회");
System.out.println("2. 예금 출금");
System.out.println("3. 예금 입금");
System.out.println("4. 종료 하기");
System.out.print("메뉴를 선택하세요: ");//출력하고 난 이후에 연이어서 키보드로 입력하기 위해서 ln을 붙이지 않음.
InputStream is = System.in;
char inputChar = (char) is.read(); //키보드로 입력한 한 문자
switch(inputChar) {
case '1':
System.out.println("예금 조회를 선택하셨습니다.");
break;
case '2':
System.out.println("예금 출금를 선택하셨습니다.");
break;
case '3':
System.out.println("예금 입금를 선택하셨습니다.");
break;
case '4':
System.out.println("종료 하기를 선택하셨습니다.");
break;
}
}
}
package sec03.exam01_system_in_out;
import java.io.InputStream;
public class SystemInExample2 {
public static void main(String[] args) throws Exception{
InputStream is = System.in;
byte[] datas = new byte[100];
System.out.print("이름: ");
int nameBytes = is.read(datas);
String name = new String(datas,0,nameBytes-2);// 마지막요소에서 2를 뺐다. 엔터키를 빼기 위해 2를 뺀것이다.
System.out.print("하고 싶은말: ");
int commentBytes = is.read(datas);
String comment = new String(datas,0,commentBytes-2);
System.out.println("입력한 이름: "+name);
System.out.println("입력한 하고 싶은말: "+comment);
}
}
package sec03.exam01_system_in_out;
import java.io.IOException;
import java.io.OutputStream;
public class SystemOutExample {
public static void main(String[] args) throws IOException{
OutputStream os = System.out;
for(byte b = 48;b<58;b++) { //48은 0의 아스키값이다. 57이 9
os.write(b);
}
os.write(13); //엔터키의 캐리지리턴 13값이다. -> 개행
for(byte b = 97;b<123;b++) { //z는 122
os.write(b);
}
os.write(13);
String hangul = "가나다라마바사아자차카타파하";
byte[] hangulBytes = hangul.getBytes();
os.write(hangulBytes);
os.flush();
}
}
console
package sec03.exam02_console;
import java.io.Console;
public class ConsoleExample {
public static void main(String[] args) {
Console console = System.console(); //이클립스에서 실행하면 null을 리턴한다. 그래서 반드시 명령프롬프트에서 실행하라
System.out.print("아이디: ");
String id = console.readLine();
System.out.print("패스워드: ");
char[] charPass = console.readPassword();
String strPassword = new String(charPass);
System.out.println("----------------");
System.out.println(id);
System.out.println(strPassword);
}
}
scanner
package sec03.exam03_scanner;
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("문자열 입력> ");
String inputString = scanner.nextLine();
System.out.println(inputString);
System.out.println();
System.out.print("정수 입력> ");
int inputInt = scanner.nextInt();
System.out.println(inputInt);
System.out.println();
System.out.print("실수 입력> ");
double inputDouble = scanner.nextDouble();
System.out.println(inputDouble);
System.out.println();
}
}
file
package sec04.exam01_file;
import java.io.File;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileExample {
public static void main(String[] args) throws Exception{
File dir = new File("C:/Temp/Dir");
File file1 = new File("C:/Temp/file1.txt");
File file2 = new File("C:/Temp/file2.txt");
File file3 = new File(new URI("file:///C:/Temp/file3.txt"));
if(dir.exists() == false) {dir.mkdirs();}
if(file1.exists() == false) {file1.createNewFile();}
if(file2.exists() == false) {file2.createNewFile();}
if(file3.exists() == false) {file3.createNewFile();}
File temp = new File("C:/Temp");
File[] contents = temp.listFiles(); // 해당 디렉토리 안에 있는 서브 디렉토리나 파일들을 파일 객체로 만들어 파일 배열로 만든다.
System.out.println("날짜 시간 형태 크기 이름");
System.out.println("-----------------------------------------------------");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a HH:mm");
for(File file:contents) {
System.out.print(sdf.format(new Date(file.lastModified())));//마지막 수정된 시간-> 리턴타입이 long이다. 이걸 날짜 객체로 만들어준다.
if(file.isDirectory()) { //디렉토리라면?
System.out.print("\t<DIR>\t\t\t"+file.getName());
}else {
System.out.print("\t\t\t"+file.length()+"\t"+file.getName());
}
System.out.println();
}
}
}
fileinputstream
package sec04.exam02_fileinputstream;
import java.io.FileInputStream;
public class FileInputStreamExample {
//자신의 소스코드를 읽어서 출력하는 코드
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream(
"C:/Users/user/Desktop/java/javastudy5/src/sec04/exam02_fileinputstream/FileInputStreamExample.java");
int data;
while ((data = fis.read()) != -1) { //가능하면 byte배열로 읽어라. 왜냐면 이렇게 하나씩 읽으면 너무 비효율적임.
System.out.write(data); // 이때의 write()는 System.out의 메소드이다. System.out은 OutputStream 타입의 필드이기 때문에
// write()메소드를 사용할 수 있다.
}
//System.out.flush();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
fileoutputstream
package sec04.exam03_fileoutputstream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileOutputStreamExample {
public static void main(String[] args) throws Exception{
//사진 복사하기. 동영상 음악 문자파일도 다 복사가 가능하다. 바이트기반의 입출력 스트림 사용하면 왠만하면 다 가능
String originalFileName = "C:/Users/user/Desktop/java/javastudy5/src/sec04/exam03_fileoutputstream/yein.jpg"; //현재 파일의 경로를 지정 //InputStream 사용
String targetFileName = "C:/Temp/yein.jpg"; //목적지 //OutputStream 사용
FileInputStream fis = new FileInputStream(originalFileName);
FileOutputStream fos = new FileOutputStream(targetFileName);
int readByteNo;
byte[] readBytes = new byte[100];
while((readByteNo = fis.read(readBytes)) != -1) {
fos.write(readBytes,0,readByteNo);
}
fos.flush(); // 항상 해주기
fis.close();
fos.close();
System.out.println("복사가 잘 되었습니다.");
}
}
file_reader
package sec04.exam04_file_reader;
import java.io.FileReader;
public class FileReaderExample {
public static void main(String[] args) throws Exception{
FileReader fr = new FileReader("C:/Users/user/Desktop/java/javastudy5/src/sec04/exam04_file_reader/FileReaderExample.java");
int readCharNo;
char[] cbuf = new char[100];
while((readCharNo = fr.read(cbuf)) != -1) {
String data = new String(cbuf,0,readCharNo);
System.out.println(data);
}
fr.close();
}
}
file_writer
package sec04.exam04_file_writer;
import java.io.File;
import java.io.FileWriter;
public class FileWriterExample {
public static void main(String[] args) throws Exception{
File file = new File("C:/Temp/file.txt");
FileWriter fw = new FileWriter(file);
fw.write("FileWriter는 한글로 된 "+"\r\n"); //개행시킨다.
fw.write("문자열을 바로 출력할 수 있다. "+"\r\n"); //뒤에 추가된건 . 캐리지 리턴과 라인피드임 -> 개행
fw.flush();
fw.close();
System.out.println("파일에 저장되었습니다.");
}
}
inputstreamreader
package sec05.exam01_inputstreamreader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class InputStreamReaderExample {
public static void main(String[] args) throws Exception{
InputStream is = System.in; //콘솔로부터 입력받겠다는 뜻. //InputStream은 바이트 기반이다. 이걸 보조 스트림을 통해 문자를 다루기 더 쉬운 Reader계열의 보조스트림에 연결시킨다.
Reader reader = new InputStreamReader(is); //보조 스트림을 연결해준다.
int readCharNo;
char[] cbuf = new char[100];
while((readCharNo = reader.read(cbuf)) != -1) { //ctrl+ z를 누르면 콘솔에서 -1을 리턴한다. -> 종료
String data = new String(cbuf,0,readCharNo); //0인덱스에서 읽은 문자 수만큼 결합을 했다.
System.out.println(data);
}
reader.close();
is.close(); //위에 코드까지 써도 되긴하는데, 가능하면 오리지널 스트림도 닫아주는것이 낫다.
}
}
outputstreamswriter
package sec05.exam02_outputstreamwriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class OutputStreamWriterExample {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("C:/Temp/file.txt");
Writer writer = new OutputStreamWriter(fos);
String data = "바이트 출력 스트림을 문자 출력 스트림으로 변환";
writer.write(data);
writer.flush();
writer.close();
fos.close();
System.out.println("파일 저장이 끝났습니다.");
}
}
bufferedinputstream
package sec05.exam03_bufferedinputstream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
public class BufferedInputStreamExample {
public static void main(String[] args) throws Exception{
long start = 0;
long end = 0;
//버퍼 사용하지 않았을 때 시간 측정하기
FileInputStream fis1 = new FileInputStream("C:/Users/user/Desktop/java/javastudy5/src/sec05/exam03_bufferedinputstream/yein.jpg");
start = System.currentTimeMillis(); //현재 시간을 long값으로 ...
while((fis1.read()) != -1) {} //얼마나 빨리 파일의 끝까지 읽느냐를 테스트함.
end = System.currentTimeMillis();
System.out.println("사용하지 않았을 때: "+(end-start)+"ms");
fis1.close();
//버퍼 사용했을 때 시간 측정
FileInputStream fis2 = new FileInputStream("C:/Users/user/Desktop/java/javastudy5/src/sec05/exam03_bufferedinputstream/yein.jpg");
BufferedInputStream bis = new BufferedInputStream(fis2);
start = System.currentTimeMillis();
while((bis.read()) != -1) {}
end = System.currentTimeMillis();
System.out.println("사용했을 때 "+(end-start)+"ms");
bis.close();
fis2.close();
//결과는 740ms vs 8ms 이다. 즉 차이가 상당히 나는 것을 알 수 있다.
}
}
bufferedreader
package sec05.exam04_bufferedreader;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
public class BufferedReaderExample {
public static void main(String[] args) throws Exception{
InputStream is = System.in;
Reader reader = new InputStreamReader(is); //바이트 기반 스트림을 문자기반 스트림으로 변환해줌.
BufferedReader br = new BufferedReader(reader); //입력 성능 향상 <- 문자기반스트림에 버퍼를 제공해준다. //InputStream에 연결된 보조스트림이 2개가 된다.
//BufferedReader는 주로 readLine()을 자주 사용한다. 하나하나읽는 것보다는 효율적이어서.
System.out.print("입력: ");
String lineString = br.readLine(); //입력한 한 행을 한꺼번에 읽어들인다.
System.out.println("출력: " + lineString);
br.close();
reader.close();
is.close();
//스트림을 클로즈되지 않아도 프로그램이 종료되면 사실 스트림은 자동으로 close()된다.
}
}
bufferedoutputstream
package sec05.exam05_bufferedouputstream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class BufferedOutputStreamExample {
public static void main(String[] args) throws Exception{
//파일 복사 성능 테스트 하기
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
int data = -1;
long start = 0;
long end = 0;
fis = new FileInputStream("C:/Users/user/Desktop/java/javastudy5/src/sec05/exam05_bufferedouputstream/yein.jpg");
bis = new BufferedInputStream(fis);
fos = new FileOutputStream("C:/Temp/yein.jpg");
start = System.currentTimeMillis();
while((data = bis.read()) != -1) {
fos.write(data);
}
fos.flush();
end = System.currentTimeMillis();
fos.close();
bis.close();
fis.close();
System.out.println("사용하지 않았을 때: "+(end-start)+"ms");
fis = new FileInputStream("C:/Users/user/Desktop/java/javastudy5/src/sec05/exam05_bufferedouputstream/yein.jpg");
bis = new BufferedInputStream(fis);
fos = new FileOutputStream("C:/Temp/yein.jpg");
bos = new BufferedOutputStream(fos); //<- 이부분이 달라졌다.
start = System.currentTimeMillis();
while((data = bis.read()) != -1) {
bos.write(data);
}
fos.flush();
end = System.currentTimeMillis();
bos.close();
fos.close();
bis.close();
fis.close();
//위에 close()된 순서가 달라지면 에러가 발생한다. 왜인지는 자세히 모르겠다. 순서대로 닫아줘야 하는건가 ?
// 그점 제외하고는 사용했을때랑 안했을때 성능차이가 상당히 많이 난다. 거의 200배 정도...
System.out.println("사용했을 때: "+(end-start)+"ms");
}
}
datainputstream_dataoutputstream
package sec05.exam06_datainputstream_dataoutputstream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class DataInputOutputStreamExample {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("C:/Temp/primitive.dat"); //.dat -> 바이트 데이터가 저장이 된다.
DataOutputStream dos = new DataOutputStream(fos);
dos.writeUTF("홍길동"); //문자를 출력하고 싶다면? 이거 써도 됨.
dos.writeDouble(95.5);
dos.writeInt(2);
dos.writeUTF("감자바"); //문자를 출력하고 싶다면? 이거 써도 됨.
dos.writeDouble(90.3);
dos.writeInt(2);
dos.flush();
dos.close();
FileInputStream fis = new FileInputStream("C:/Temp/primitive.dat"); //이번엔 읽어보자.
DataInputStream dis = new DataInputStream(fis); //연결시킴.
//두번 값 넣었으니까 두번 돌자.
for(int i = 0;i<2;i++) {
String name = dis.readUTF();
double score = dis.readDouble();
int order = dis.readInt();
System.out.println(name+":"+score+":"+order);
}
dis.close();
fis.close();
}
}
printstream
package sec05.exam07_printstream;
import java.util.Date;
public class PrintfExample {
public static void main(String[] args) {
System.out.printf("상품의 가격:%d원\n",123);
System.out.printf("상품의 가격:%6d원\n",123);
System.out.printf("상품의 가격:%-6d원\n",123);
System.out.printf("상품의 가격:%06d원\n",123);
System.out.printf("반지름이 %d인 원의 넓이:%10.2f\n",10,Math.PI*10*10);
System.out.printf("%6d | %-10s |%10s\n",1,"홍길동","도적");
Date now = new Date();
System.out.printf("오늘은 %tY년 %tm월 %td일 입니다.\n",now,now,now);
System.out.printf("오늘은 %1$tY년 %1$tm월 %1$td일 입니다.\n",now);
System.out.printf("현재 %1$tH시 %1$tM분 %1$tS초 입니다.\n",now);
}
}
package sec05.exam07_printstream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStreamExample {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("C:/Temp/file.txt");
PrintStream ps = new PrintStream(fos); //OutputStream이니까 PrintWriter가 아니라 PrintStream으로 연결했다.
ps.println("[프린터 보조 스트림]");
ps.print("마치 ");
ps.println("프린터가 출력하는 것처럼 ");
ps.println("데이터를 출력합니다. ");
ps.flush();
ps.close();
fos.close();
}
}
objectinputstream_objectoutputstream
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Child extends Parent implements Serializable{
public String field2;
//엄밀하게 다지면 재정의는 아니다. Serializable에 정의된 메소드가 아니기 때문이다. 하지만 Serializable이 구현이 되면 객체가 출력되기 전에 입력되기 전에 각각 이 두 메소드가 실행되기 때문이다. 콜백메소드라고 보는게 맞다.
//반드시 접근제한자가 private여야 한다. 이게 아니면 실행도 안된다.
private void writeObject(ObjectOutputStream out) throws IOException{
out.writeUTF(field1); //String이니까 이거 사용 //수동으로 해줘야 한다.
out.defaultWriteObject(); // 원래 있던 기능 사용하기 위해서
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
field1 = in.readUTF(); //문자열부터 출력했으니까 문자열부터 읽자 .
in.defaultReadObject();
}
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.Serializable;
public class ClassA implements Serializable{
int field1;
ClassB field2 = new ClassB(); //클래스 타입의 필드 -> classB도 serializable 했으므로 내부 필드도 바이트에 포함이 될 것이다.
static int field3;
transient int field4; //바이트로 변환되지 않음. 제외
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.Serializable;
public class ClassB implements Serializable{
int field1; //얘도 바이트 배열에 포함이 될 것이다.
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.Serializable;
public class ClassC implements Serializable{
//내가 직접 UID를 생성하면, 컴파일러는 자기가 스스로 만들지 않고, 개발자가 정한 UID를 사용한다. 그래서
//아무리 필드가 추가되고, 수정이 되어도 예외가 발생하지 않는다. 항상 고정값을 갖기 때문에 복원이 실패하지 않는다.
//클래스 이름에 커서를 갖다 놓고 ctrl+1 을 누른다. 이후에 add serialVersionUID를 클릭해서 생성한다.
private static final long serialVersionUID = -1265691405514514962L; //이게 추가되면 잘 작동한다. (다른 필드가 추가되어도!)
int field1;
int field2;
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class NonSerializableParentExample {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("C:/Temp/Object.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Child child = new Child();
child.field1 = "홍길동";
child.field2 = "홍삼원";
oos.writeObject(child); //Child의 writeObject() 가 실행된다.
oos.flush();
oos.close();
fos.close();
FileInputStream fis= new FileInputStream("C:/Temp/Object.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
Child v = (Child) ois.readObject(); //Child의 readObject() 가 실행된다.
System.out.println("field1: "+v.field1);
System.out.println("field2: "+v.field2);
//잘 복원되는 것을 확인할 수 있다. Child에서 재정의가 안되면 field1의 값은 null이 들어가게 된다.
ois.close();
fis.close();
}
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectInputOutputStreamExample {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("C:/Temp/Object.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(new Integer(10));// Integer 객체
oos.writeObject(new Double(3.14));
oos.writeObject(new int[] {1,2,3});
oos.writeObject(new String("홍길동"));
oos.flush(); oos.close();
FileInputStream fis = new FileInputStream("C:/Temp/Object.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
Integer obj1 = (Integer)ois.readObject();
Double obj2 = (Double)ois.readObject();
int[] obj3 = (int[])ois.readObject();
String obj4 = (String)ois.readObject();
ois.close(); fis.close();
//잘 읽어오는 것을 확인할 수 있음.
System.out.println(obj1);
System.out.println(obj2);
System.out.println(obj3[0]+","+obj3[1]+","+obj3[2]);
System.out.println(obj4);
}
}
package sec05.exam08_objectinputstream_objectoutputstream;
public class Parent {
public String field1;
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializableExample {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("C:/Temp/Object.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
ClassA classA = new ClassA();
classA.field1 = 1;
classA.field2.field1 = 2;
classA.field3 = 3;
classA.field4 = 4;
oos.writeObject(classA);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("C:/Temp/Object.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
ClassA v = (ClassA) ois.readObject(); //객체를 읽어들인다.
System.out.println("field1: "+v.field1);
System.out.println("field2.field1: "+v.field2.field1);
System.out.println("field3: "+v.field3);
System.out.println("field4: "+v.field4); //얘는 0이 출력된다 trasient했기 때문이다. 출력할때 바이트화가 되지 않아서 출력이 안된거다. 그래서 읽어들일때도 기본값인 0 이 들어가있는거다.
}
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SerialVersionUIDExample {
public static void main(String[] args) throws Exception{
//객체를 저장하는 실행 클래스
FileOutputStream fos = new FileOutputStream("C:/Temp/Object.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
ClassC classC = new ClassC(); //저장할 객체
classC.field1 = 1;
oos.writeObject(classC);
oos.flush();
oos.close();
fos.close();
}
}
package sec05.exam08_objectinputstream_objectoutputstream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class SerialVersionUIDExample2 {
public static void main(String[] args) throws Exception{
//복원하는 실행 클래스
FileInputStream fis = new FileInputStream("C:/Temp/Object.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
ClassC classC = (ClassC) ois.readObject(); //readObject()를 실행하면서 SerialVersionUID를 검사한다. 서로 다르다면 예외가 발생한다.
System.out.println(classC.field1);
ois.close();
fis.close();
}
}
필기
package io;
/*
java.io 패키지
자바의 기본적인 데이터 입출력 (IO: Input/Output) API 제공
바이트 기반 스트림과 문자 기반 스트림
바이트 기반 스트림: 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 받고 보낼 수 있다.
문자 기반 스트림:
문자만 받고 보낼 수 있도록 특화되어 있다.
InputStream
바이트 기반 입력 스트림의 최상위 클래스로 추상 클래스이다. (new를 통해 객체를 생성할 수 없다. )
read()메소드가 있다...
close()메소드
InputStream을 더 이상 사용하지 않을 경우 호출해 준다.
InputStream에서 사용했던 시스템 자원을 풀어준다.
OutputStream
InputStream과는 다르게 flush()메소드가 있다. ->버퍼에 잔류하는 모든 바이트를 출력한다.
OutputStream은 바이트 기반 출력 스트림의 최상위 클래스로 추상 클래스이다.
write(int b)에서 매개타입이 int타입인데, (int는 4바이트) 여기서 4바이트를 출력하는게 아니라 끝 한 바이트만 출력을 한다.
write()메소드를 사용하고 난 뒤에는 반드시 flush() 메서드를 사용해야만 데이터가 완전하게 출력된다.
<Reader 클래스>
문자 기반 입력 스트림의 최상위 클래스로 추상 클래스이다.
read() 한 문자를 읽고 int를 리턴하는데, 한문자는 2바이트이므로 4바이트 int중에서 끝 2바이트에 하나의 문자가 저장된다.
<Writer 클래스>
문자 기반 출력 스트림의 최상위 클래스로 추상 클래스이다.
------------------------------------------------------------------
콘솔(Concole)
시스템을 사용하기 위해 키보드로 입력을 받고 화면으로 출력하는 소프트웨어
<System.in 필드>
InputStream 타입의 입력 스트림이므로 InputStream 변수에 대입할 수 있다.
InputStream is = System.in;
읽은 byte는 키보드의 아스키 코드 이다.
int asciiCode = is.read();
아스키 코드로부터 문자 읽기
char inputChar = (char) is.read();
한글 한자는 2바이트이다. 그래서 2바이트 이상을 읽어야 하기 때문에 byte 배열에 저장해야 한다.
byte[] byteData = new byte[15];
int readByteNo = System.in.read(byteData);
키보드의 엔터를 바이트로 받게 되면, 엔터키 = 캐리지리턴(값:13) + 라인피드(값:10) 으로
해서 각각 13값과 10값으로 2바이트를 먹는다.
<System.out 필드>
PrintStream(OutputStream의 하위 스트림이다.) 타입의 출력 스트림이므로 OutputStream으로 타입 변환할 수 있다.
OutputStream os = System.out;
아스키 코드를 출력하면 콘솔에는 문자가 출력된다.
문자열을 출력하려면 바이트 배열을 얻어햐 한다.
PrintStream ps = System.out;
ps.println(...);
이걸 줄여서 사용하면 System.out.println(...); 이 된다.
<Console 클래스>
자바 6부터 콘솔에서 입력된 문자열을 쉽게 읽을 수 있도록 Console 클래스 제공
Console console = System.console();
이클립스에서 System.console() 은 null을 리턴하기 때문에
명령 프롬프트에서 반드시 실행해야 한다.
String <- readLines() :엔터키를 입력하기 전의 모든 문자열을 읽음
char[] <- readPassword() : 키보드 입력 문자를 콘솔에 보여주지 않고 문자열을 읽음.
<Scanner 클래스>
Console클래스의 단덤: 문자열은 읽을 수 있지만, 기본 타입(정수, 실수) 값은 바로 읽을 수 없다.
java.util.Scanner
콘솔로부터 기본 타입의 값을 바로 읽을 수 있다.
Scanner scanner = new Scanner(System.in);
파일 입출력
< File 클래스 >
파일 시스템의 파일을 표혀나는 클래스
-> 파일 크기, 파일 속성, 파일 이름 등의 정보 제공
-> 파일 생성 및 삭제 기능 제공
-> 디렉토리를 생성하고 디렉토리에 존재하는 파일 리스트를 얻어내는 기능 제공
파일 또는 디렉토리 존재 유무 확인 메소드
boolean isExist = file.exists();
파일 및 디렉토리 생성 및 삭제 메소드
리턴타입 메소드 설명
boolean createNewFile() 새로운 파일을 생성
boolean mkdir() 새로운 디렉토리를 생성
boolean mkdirs() 경로상에 없는 모든 디렉토리를 생성
boolean delete() 파일 또는 디렉토리를 삭제
<FileInputStream>
파일로부터 바이트 단위로 읽어 들일 때 사용
그림, 오디오, 비디오, 텍스트 파일 등 모든 종류의 파일을 읽을 수 있다.
FileInputStream 객체가 생성될 때 파일과 직접 연결된다. 그래서
만약 파일이 존재하지 않으면 FileNotFoundException을 발생한다.
try- catch 문으로 예외 처리를 해야 한다.
InputStream의 하위 클래스이므로 사용 방법이 InputStream과 동일하다.
<FileOutputStream>
파일에 바이트 단위로 데이터를 저장할 때 사용
그림, 오디오, 비디오, 텍스트 등 모든 종류의 데이터를 파일로 저장할 수 있다.
파일이 이미 존재할 경우, 데이터를 출력하게 되면 파일을 덮어쓰게 된다.
그러므로 기존 파일 내용 끝에 데이터를 추가할 경우에는 두번째 매개변수로 true를 전달한다.
OutputStream 하위 클래스이므로 사용방법이 OutputStream과 동일하다.
<FileReader >
텍스트 파일로부터 데이터를 읽어 들일 때 사용
문자 단위로 읽기 때문에 텍스트가 아닌, 그림 오디오 비디오 등의 파일은 읽을 수 없다.
FileReader 객체가 생성될 때 파일과 직접 연결
만약 파일이 존재하지 않으면 FileNotFoundException 을 발생한다.
try-catch 문으로 예외 처리를 해야 한다.
Reader 하위 클래스이므로 사용 방법이 Reader와 동일하다.
<FileWriter>
텍스트 파일에 문자 데이터를 저장할 때 사용
텍스트가 아닌 그림, 오디오, 비디오 등의 데이터를 파일로 저장할 수 없다.
파일이 이미 존재할 경우, 데이터를 출력하게 되면 파일을 덮어쓰게 됨.
기존 파일 내용 끝에 데이터를 추가할 경우 두번째 매개변수로 true를 주면 된다.
Writer 하위 클래스이므로 사용 방법이 Writer와 동일
----------------------------------------------------------
<보조 스트림>
다른 스트림과 연결이 되어 여러가지 편리한 기능을 제공해주는 스트림
문자 변환, 입출력 성능 향상, 기본 데이터 타입 입출력, 객체 입출력 등의 기능을 제공
보조 스트림 생성
보조스트림 변수 = new 보조스트림(연결스트림)
보조 스트림은 체인 형식으로 여러개를 엮어서 연결할 수도 있다.
<문자 변환 보조 스트림>
소스 스트림이 바이트 기반 스트림이지만, 데이터가 문자일 경우 사용할 수 있다.
Reader 와 Writer는 문자 단위로 입출력하기 대문에 바이트 기반 스트림보다는
편리하다.
문자셋의 종류를 지정할 수 있기 때문에 다양한 문자를 입출력한다.
InputStreamReader
바이트 -> 문자
OutputStreamWriter
문자 -> 바이트
<성능 향상 보조 스트림>
입출력 성능에 영향을 미치는 입출력 소스
하드 디스크
느린 네트워크
버퍼를 이용한 해결
입출력 소스와 직접 작업하지 않고, 버퍼(buffer)와 작업하므로서 실행 성능을 향상
프로그램은 데이터를 메모리 버퍼에 고속전송한다. 버퍼는 하드디스크로 한번에 버퍼내용을 모두를 전송한다.
프로그램은 쓰기 속도가 향상되고,
버퍼가 차게 되면 데이터를 한꺼번에 하드 디스크로 보내므로써 출력 횟루를 줄여준다.
메모리를 버퍼에 만든다... 라는 개념으로 알면 된다.
예시:
BufferedInputStream,BufferedReader
BufferedInputStrea bis = new BufferedInputStream(바이트 입력 스트림);
BufferedReader br = new BufferedReader(문자 입력 스트림);
BufferedOutputStream, BufferedWriter
BufferedOutputStream bos = new BufferedOutputStream(바이트 출력 스트림);
BuggeredWriter bw = new BufferedWriter(문자 출력 스트림);
<기본 타입 입출력 보조 스트림>
DataInputStream dis = new DataInputStream(바이트 입력 스트림);
DataOutputStream dos = new DataOutputStream(바이트 출력 스트림);
<프린터 보조 스트림 >
기본 타입이거나 문자열을 출력을 할때 개행을 자주 해야 한다면
PrintStream이나 PrintWriter를 사용하는 것이 좋다.
PrintStream ps = new PrintStream(바이트 출력 스트림);
PrintWriter pw = new PrintWriter(문자 출력 스트림);
<객체 입출력 보조 스트림>
객체를 파일 또는 네트워크로 입출력할 수 있는 기능 제공
ObjectInputStream -> InputStream에 연결해서 사용한다. (역질렬화)
ObjectOutputStream -> OutputStream에 연결해서 사용한다. (직렬화)
예시:
ObjectInputStream ois = new ObjectInputStream(바이트 입력 스트림);
ObjectOutputStream oos = new ObjectOutputStream(바이트 출력 스트림);
oos.writeObject(객체);
객체타입 변수 = (객체타입) ois.readObject(); //Object 타입을 리턴하므로 형변환 필요함.
객체를 바이트배열로 만드는 작업을 직렬화 라고 부른다.
<직렬화가 가능한 클래스 Serializable>
자바는 Serializable 인터페이스를 구현한 클래스만 직렬화할 수 있도록 제한한다.
serializable 인터페이스 안에는 메소드 정의가 없기 대문에 그냥 implements만 해도 된다.
transient 키워드가 붙은 필드는 직렬화에서 제외
<SerialVersionUID 필드>
직렬화된 객체를 역직렬화할 때는 직렬화 했을 때와 같은 클래스를 사용
클래스의 이름이 같더라도 클래스의 내용이 변경된 경우 역직렬화는 실패 -> 시리얼버전uid가 달라지기 때문이다.
serialVersionUID는 같은 클래스임을 알려주는 식별자 역할
->Serializable 인터페이스가 구현되면 컴파일시에 자동적으로 serialVersionUID 정적 필드가 추가됨.
재컴파일하면 serialVersionUID의 값이 달라짐 . -> 즉 직렬화하고 난뒤에 클래스 컴파일하면 안됨. 만약 어쩔 수 없다면 밑에 방법을 이용. !!
불가피한 수정이 있을 경우 명시적으로 serialVersionUID 를 선언
static final long serialVersionUID = 정수값; <- serialver.exe로 자동생성 가능 (jdk의 bin폴더를 가라. )
(위처럼 상수로 선언)
-------------------------------------------------------------------------------------------
<writeObject()와 readObject() 메소드 >
private void writeObject(ObjectOutputStream out) throws IOException{
...
out.defaultWriteObject(); //원래 방식으로 ㄱㄱ 라는 뜻
}
- 직렬화 직전에 자동 호출한다.
- 추가 직렬화할 내용을 작성할 수 있다. 다만 맨 끝에는 out.default~~~ 가 반드시 와야 한다.
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
...
in.defaultReadObject();
}
- 역직렬화 직전에 자동 호출한다.
- 추가 역직렬화 할 내용을 작성할 수 있다.
---------------------------------------------------------------------------------------
위와 같은 재정의가 필요한 경우가 존재한다.
Parent <- Child 클래스가 상속관계에 있다고 가정할떄, Child만 Serializable을 구현했다면, Parent의 필드는 직렬화가 되지 않는다.
반대로 Parent에서만 Serializable이 되었다면, Chile와 Parent의 필드가 둘다 직렬화 될 수 있다. 상속관계에 있기 때문이다. 근데, Child만 Serializable을 구현했다면
Parent필드느 입출력 되지 않으므로 Parent필드가 추가적으로 입출력될 수 있도록 (<- 직렬화), 정의 해줄때 위에 있는 재정의에서 새롭게 코드를 추가해주는 것이다.
--> 밑에 설명이 조금 더 간단명확하다.
<추가 직렬하 및 역직렬화가 필요한 경우>
- 부모 클래스가 Serializable 구현하지 않고, 자식 클래스가 Serializable을 구현한 경우
- 부모 필드는 직렬화에서 제외됨.
- 따라서 writeObject()에서 부모 필드 직렬화가 필요하고
- readObject()에서 부모 필드 역직렬화가 필요하다.
*/
반응형
'Java' 카테고리의 다른 글
[이것이 자바다] 자바 NIO 공부 정리 (0) | 2020.12.30 |
---|---|
[이것이 자바다] 자바 네트워크1 공부 정리 (0) | 2020.12.27 |
[이것이 자바다] 자바 병렬처리 공부 정리 (0) | 2020.12.25 |
[이것이 자바다] 자바 스트림 공부 정리 (0) | 2020.12.24 |
[이것이 자바다] 자바 람다식 공부 정리 (0) | 2020.12.22 |