
바이트 스트림: 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 입출력할 때 사용
문자 스트림: 문자만 입출력할 때 사용
package ch18.sec02.ex01;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class WriteExample {
public static void main(String[] args) {
try {
OutputStream os = new FileOutputStream("/Users/choijunha/Downloads/test1.db");
byte a = 10;
byte b = 20;
byte c = 30;
os.write(a);
os.write(b);
os.write(c);
os.flush();
os.close();
} catch(IOException e) {
System.out.println(e);
}
}
}
package ch18.sec02.ex01;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class ReadExample {
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("/Users/choijunha/Downloads/test1.db");
// write 할 때 3개 했다는 걸 알고 있는 경우
// byte a = (byte) is.read();
// byte b = (byte) is.read();
// byte c = (byte) is.read();
// System.out.println(a);
// System.out.println(b);
// System.out.println(c);
// 몇 개인지 모를 때
while (true) {
int data = is.read();
if (data == -1) break;
System.out.println(data);
}
is.close();
} catch(IOException e) {
System.out.println(e);
e.printStackTrace();
}
}
}
package ch18.sec02.ex02;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class WriteExample {
public static void main(String[] args) {
try {
OutputStream os = new FileOutputStream("/Users/choijunha/Downloads/test2.db");
byte[] array = {40, 50, 60, 70};
os.write(array);
os.flush();
os.close();
} catch(IOException e) {
System.out.println(e);
}
}
}
package ch18.sec02.ex02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class ReadExample {
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("/Users/choijunha/Downloads/test2.db");
// byte 배열을 준비 <- stream 저장
byte[] data = new byte[100];
// while (true) {
// int num = is.read(data); // 3 // 실제로 읽은 바이트 수는 num에 저장됨
// if (num == -1) break;
// for (int i = 0; i < num; i++) {
// System.out.println(data[i]);
// }
//
// }
int num = is.read(data);
for (int i = 0; i < num; i++) {
System.out.println(data[i]);
}
is.close();
} catch(FileNotFoundException e) {
System.out.println("파일을 찾을 수 없습니다.");
} catch(IOException e) {
System.out.println(e);
e.printStackTrace();
}
}
}
package ch18.sec03.ex03;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class FileOutputStreamExample {
public static void main(String[] args) throws Exception {
InputStream is = new FileInputStream("/Users/choijunha/Downloads/무제.png");
OutputStream os = new FileOutputStream("/Users/choijunha/Downloads/무제2.png");
// byte[] data = new byte[1024]; // read 해서 담을 자료구조의 크기보다 파일이 클 때
// while (true) {
// int num = is.read(data);
// if (num == -1) break;
// os.write(data, 0, num);
// }
is.transferTo(os);
os.flush();
os.close();
is.close();
}
}
package ch18.sec04;
import java.io.FileWriter;
import java.io.Writer;
public class WriterExample {
public static void main(String[] args) throws Exception {
// 문자
Writer writer = new FileWriter("/Users/choijunha/Downloads/test.txt");
// ch 한글
char a = 'A';
writer.write(a);
char b = 'B';
writer.write(b);
// ch 배열
char[] array = {'C', 'D', 'E'};
writer.write(array);
// 문자열
writer.write("FGH");
writer.flush();
writer.close();
}
}
package ch18.sec04;
import java.io.FileReader;
import java.io.Reader;
public class ReaderExample {
public static void main(String[] args) throws Exception {
// 문자
Reader reader = new FileReader("/Users/choijunha/Downloads/test.txt");
// 1문자씩;
while (true) {
int data = reader.read();
if (data == -1) break;
System.out.print((char)data); // 숫자(문자의 정수 표현) 대신 문자로 표현하기 위해 casting
}
reader.close();
reader = new FileReader("/Users/choijunha/Downloads/test.txt");
// 배열에
char[] data = new char[100];
int num = reader.read(data);
for (int i = 0; i < num; i++) {
System.out.print(data[i]);
}
reader.close();
}
}
package ch18.sec06;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
public class CharacterConvertStreamExample {
public static void main(String[] args) throws Exception {
write("한글입니다.");
String data = read();
System.out.println(data);
}
public static void write(String str) throws Exception {
OutputStream os = new FileOutputStream("/Users/choijunha/Downloads/test.txt"); // byte[]
Writer writer = new OutputStreamWriter(os, "utf-8");
writer.write(str);
writer.flush();
writer.close();
}
public static String read() throws Exception {
InputStream is = new FileInputStream("/Users/choijunha/Downloads/test.txt"); // byte[]
Reader reader = new InputStreamReader(is, "ms949");
char[] data = new char[100];
int num = reader.read(data);
reader.close();
return new String(data, 0, num);
}
}
package ch18.sec07;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class BufferExample {
public static void main(String[] args) throws Exception {
// copy() 입출력 stream
InputStream is = new FileInputStream("/Users/choijunha/Downloads/졸업증명서 최준하jpg.jpg");
OutputStream os = new FileOutputStream("/Users/choijunha/Downloads/졸업증명서 최준하jpg2.jpg");
// copy() 입출력 + buffer stream
InputStream is2 = new FileInputStream("/Users/choijunha/Downloads/졸업증명서 최준하jpg.jpg");
OutputStream os2 = new FileOutputStream("/Users/choijunha/Downloads/졸업증명서 최준하jpg2.jpg");
BufferedInputStream bis = new BufferedInputStream(is2);
BufferedOutputStream bos = new BufferedOutputStream(os2);
long nonBufferTime = copy(is, os);
System.out.println(nonBufferTime);
long BufferTime = copy(bis, bos);
System.out.println(BufferTime);
is.close();
os.close();
bis.close();
bos.close();
is2.close();
os2.close();
}
public static long copy(InputStream is, OutputStream os) throws Exception {
long start = System.nanoTime();
// 복사
while (true) {
int data = is.read();
if (data == -1) break;
os.write(data);
}
long end = System.nanoTime();
return end - start;
}
}
package ch18.sec08;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class DataInputOutputExample {
public static void main(String[] args) throws Exception {
// OutputStream os = new FileOutputStream("primitive.db");
// DataOutputStream dos = new DataOutputStream(os);
//
// dos.writeUTF("홍길동");
// dos.writeDouble(99.1);
// int num = 100;
// dos.writeInt(num);
//
// dos.writeUTF("이길동");
// dos.writeDouble(89.1);
// num = 200;
// dos.writeInt(num);
//
// dos.flush();
// dos.close();
// os.close();
InputStream is = new FileInputStream("primitive.db");
DataInputStream dis = new DataInputStream(is);
for (int i = 0; i < 2; i++) {
System.out.print(dis.readUTF());
System.out.print(dis.readDouble());
System.out.print(dis.readInt());
System.out.println();
}
dis.close();
is.close();
}
}
package ch18.sec08;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class DataInputOutputExample2 {
public static void main(String[] args) {
// OutputStream os = new FileOutputStream("primitive.db");
// DataOutputStream dos = new DataOutputStream(os);
//
// dos.writeUTF("홍길동");
// dos.writeDouble(99.1);
// int num = 100;
// dos.writeInt(num);
//
// dos.writeUTF("이길동");
// dos.writeDouble(89.1);
// num = 200;
// dos.writeInt(num);
//
// dos.flush();
// dos.close();
// os.close();
// InputStream is = null;
// DataInputStream dis = null;
// try() 안에서 선언, 생성된 resource 객체 (AutoClosable 구현) 는 자동으로 close()
try(
InputStream is = new FileInputStream("primitive.db");
DataInputStream dis = new DataInputStream(is);
) {
for (int i = 0; i < 2; i++) {
System.out.print(dis.readUTF());
System.out.print(dis.readDouble());
System.out.print(dis.readInt());
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
직렬화 - 객체를 출력하려면 필드값을 일렬로 늘어선 바이트로 변경
역직렬화 - 직렬화된 바이트를 객체의 필드값으로 복원
package ch18.sec10;
import java.io.Serializable;
public class Member implements Serializable {
/**
*
*/
private static final long serailVersionUID = 2L;
private String id;
private String name;
private transient String ssn;
public Member(String id, String name, String ssn) {
super();
this.id = id;
this.name = name;
this.ssn = ssn;
}
@Override
public String toString() {
return "Member [id=" + id + ", name=" + name + ", ssn=" + ssn + "]";
}
}
package ch18.sec10;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
public class ObjectOutputInputStreamExample {
public static void main(String[] args) throws Exception {
// OutputStream os = new FileOutputStream("member.data");
// ObjectOutputStream oos = new ObjectOutputStream(os);
//
// // 객체 생성
// Member m1 = new Member("aaa", "홍길동", "111-222");
//
// oos.writeObject(m1);
// oos.flush();
// oos.close();
// os.close();
InputStream is = new FileInputStream("member.data");
ObjectInputStream ois = new ObjectInputStream(is);
Member member = (Member) ois.readObject();
System.out.println(member);
ois.close();
}
}
람다 표현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것. 람다 표현식에는 이름은 없지만, 파라미터 리스트, 바디, 반환 형식, 발생할 수 있는 예외리스트는 가질 수 있다.
람다의 특징
익명 - 보통의 메서드와 달리 이름이 없으므로 익명이라 표현. 구현해야 할 코드에 대한 걱정이 줄어듦.
함수 - 람다는 메서드처럼 특정 클래스에 종속되지 않으므르소 함수라고 부름. 하지만 메서드처럼 파라미터 리스트, 바디, 반환 형식, 가능한 예외 리스트 포함.
전달 - 람다 표현식을 메서드 인수로 전달하거나 변수로 저장
간결성 - 익명 클래스처럼 많은 자질구레한 코드를 구현할 필요가 없다.
Lambda의 주요 장점
간결성: 익명 함수를 직접 선언할 필요 없이 간단한 구문으로 메소드의 동작을 정의할 수 있습니다.
함수형 프로그래밍 지원: Java에서 함수형 인터페이스와 함께 사용하여 함수형 프로그래밍 스타일을 채택할 수 있습니다.
병렬 처리와 함께 사용: 스트림 API와 함께 사용하여 병렬 처리를 용이하게 할 수 있습니다.
동시성은 하나의 코어에서 작업을 번갈아 가면서 실행해 여러 작업을 처리하는 것을 의미합니다. 이 방식은 CPU에서 처리 중인 작업을 변경하기 위해 콘텍스트 스위칭이 일어나 오버헤드가 발생합니다. 반면에 병렬성은 여러 코어에서 여러 작업을 처리하는 것을 의미합니다. 즉, 물리적인 시간 관점에서 여러 작업이 동시에 처리되는 방식입니다.
1. 블로킹 (Blocking)
블로킹 작업은 작업이 완료될 때까지 현재 스레드가 대기하는 방식입니다. 즉, 현재 작업이 끝나기 전까지는 다음 작업을 수행할 수 없습니다.
2. 논블로킹 (Non-blocking)
논블로킹 작업은 작업이 즉시 결과를 반환하며, 대기하지 않고 다음 작업을 진행할 수 있는 방식입니다. 작업이 완료되지 않은 경우에도 제어권이 즉시 반환됩니다.
3. 동기 (Synchronous)
동기 작업은 요청한 작업이 완료될 때까지 기다리는 방식입니다. 작업이 완료된 후에야 다음 작업을 진행할 수 있습니다. 블로킹과 동기 작업은 종종 함께 사용되지만, 항상 그런 것은 아닙니다.
4. 비동기 (Asynchronous)
비동기 작업은 요청한 작업이 백그라운드에서 수행되며, 작업이 완료되면 콜백이나 다른 메커니즘을 통해 결과를 통지받는 방식입니다. 비동기 작업은 보통 논블로킹 방식으로 구현됩니다.
블록킹과 동기 주요 차이점
1. 목적과 적용 범위
블로킹: 현재 스레드가 작업을 끝낼 때까지 멈춤.
동기: 작업이 완료될 때까지 함수가 리턴되지 않음.
2. 실행 흐름
블로킹: 특정 작업이 완료될 때까지 현재 스레드가 아무 것도 하지 않고 대기함.
동기: 작업이 완료될 때까지 다른 작업을 수행하지 않음. 이는 블로킹을 포함할 수도 있지만, 작업 전환이 없는 경우에도 동기 호출이 될 수 있음.
3. 블로킹과 동기의 관계
모든 블로킹 호출은 동기 호출입니다. 왜냐하면 블로킹이 작업을 완료할 때까지 기다리기 때문입니다.
하지만 모든 동기 호출이 블로킹 호출은 아닙니다. 예를 들어, 동기 메서드는 내부적으로 논블로킹 I/O를 사용하면서 폴링(polling) 메커니즘을 사용할 수도 있습니다.
결론적으로, 블로킹과 동기는 밀접하게 관련되어 있지만, 서로 다른 개념입니다. 블로킹은 현재 스레드가 특정 작업을 완료할 때까지 멈추는 것이고, 동기는 작업이 완료될 때까지 함수가 리턴되지 않는 방식입니다.