지난 시간 스트림에 대해 배웠다.
스트림 : 데이터를 처리하기 위한 연산 방식의 표준화
중간연산자 : map(), filter(), distinct(). forEach()
최종연산자 : sum(), average(), max(), min()
정렬 : .sorted()
람다와 스트림은 자바를 하는 동안 아주 중요하다.
IO 입출력과 스트림
다른 공간에 있는 데이터를 서로 주고 받는다.
어제 배웠던 스트림과는 다른 의미의 스트림
여기서 스트림이란, 데이터를 운반하는데 사용되는 연결 통로
// Input(입력) / Output (출력)
// 컴퓨터 내부 또는 외부의 장치간 데이터 교환
// Stream : 데이터가 전송되는 통로
// 통로의 In, Out은 상대적 개념
// 바이트 기반 스트림 (사진, 동영상, 음성)
// 문자 기반 스트림
// 보조 스트림 (효율적으로 데이터를 주고 받기 위해 제공)
// 보조 스트림은 바이트 기반 보조 스트림과 문자 기반 보조 스트림이 있다.
// FIFO 구조
🍀 바이트 기반 스트림
// InputStream, OutputStream -> 인터페이스
// 상속받은 표준화된 기능들 오버라이딩
// InputStream
read(), read(byte[], b), read(byte[] b, int off, int len) 세 가지 형태로 데이터를 읽어올 수 있다.
// OutputStream
write(int b), write(byte[] b), write(byte[] b, int off, int len)
세 가지 형태로 데이터를 받아올 수 있다.
// 바이트 기반 보조 스트림
BufferedInputStream, BufferedOutputStream DataInputStream, DataOutputStream
🍀 문자 기반 스트림
// Reader, Writer -> 인터페이스
// Reader
// 데이터를 읽어온다
read(), read(char[] c), read(char[] c, int off, int len)
// Writer
writer(int c), writer(char[] c), writer(char[] c, int off, int len)
writer(String srt), writer(String str, int off, int len)
🍀 문자 기반 보조 스트림
BufferedReader, BufferWriter
배열을 이용해 입출력
toByteArray() : 스트림된 내용을 byte 배열로 반환 해 준다.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
public class IOTest1 {
public static void main(String[] args) {
byte[] inSrc = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] outSrc = null;
ByteArrayInputStream input = null;
ByteArrayOutputStream output = null;
input = new ByteArrayInputStream(inSrc); // 어느 대상으로부터 Input을 할지 대상을 정해야 한다
output = new ByteArrayOutputStream();
// input 에서 데이터를 받아 저장하는 곳
// 읽어오는 데이터는 1byte, int의 기본단위는 4byte
// 데이터의 크기와는 상관없이 읽어온다
int data = 0;
// -1 이 아닐 때까지 데이터를 읽어온다
while ((data = input.read()) != -1) {
output.write(data);
}
outSrc = output.toByteArray(); // 스트림된 내용을 byte 배열로 반환 해 준다.
System.out.println("input source : " + Arrays.toString(inSrc)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println("output source : " + Arrays.toString(outSrc)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
한번에 1byte 만 불러오기 때문에 성능이 떨어진다.
한번에 많은 양의 데이터를 보낼 수 있도록 처리할 수 있다.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
public class IOTest2 {
public static void main(String[] args) {
byte[] inSrc = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] outSrc = null;
byte[] temp = new byte[10];
ByteArrayInputStream input = null;
ByteArrayOutputStream output = null;
input = new ByteArrayInputStream(inSrc); // 어느 대상으로부터 Input을 할지 대상을 정해야 한다
output = new ByteArrayOutputStream();
// 읽어온 데이터를 배열 temp에 담는다
input.read(temp, 0, temp.length);
output.write(temp, 5, 5); // temp[5]부터 5개의 데이터를 write 한다.
outSrc = output.toByteArray(); // 스트림된 내용을 byte 배열로 반환 해 준다.
System.out.println("input source : " + Arrays.toString(inSrc)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println("temp : " + Arrays.toString(temp)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println("output source : " + Arrays.toString(outSrc)); // [5, 6, 7, 8, 9]
}
}
10byte를 읽어오고, output에 출력할 때는 temp[5] 부터 5byte을 출력했다.
= 필요한만큼 input 하고, 필요한만큼 output 한다
read()가 값을 읽어오는 방식
available()은 블락킹(blocking)없이 읽어올 수 잇는 바이트의 수를 반환한다.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import javax.print.event.PrintEvent;
public class IOTest3 {
public static void main(String[] args) {
byte[] inSrc = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] outSrc = null;
byte[] temp = new byte[4];
ByteArrayInputStream input = null;
ByteArrayOutputStream output = null;
input = new ByteArrayInputStream(inSrc);
output = new ByteArrayOutputStream();
System.out.println("input source : " + Arrays.toString(inSrc));
// IOException 타입으로 예외처리
// 4바이트씩 순서대로 읽어오는 구조가 아니기 때문에 available()을 이용해 다음 4바이트의 시작 위치를 찾아준다.
try {
while(input.available() > 0) {
input.read(temp); // 읽어온 값의 갯수 ( 4 -> 4 -> 2 )
output.write(temp);
outSrc = output.toByteArray();
printArrays(temp, outSrc);
}
}catch (IOException e) {}
}
static void printArrays(byte[] temp, byte[] outSrc) {
System.out.println("temp : " + Arrays.toString(temp));
System.out.println("Output Source : " + Arrays.toString(outSrc));
}
}
출력 :
input source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
temp : [0, 1, 2, 3]
Output Source : [0, 1, 2, 3]
temp : [4, 5, 6, 7]
Output Source : [0, 1, 2, 3, 4, 5, 6, 7]
temp : [8, 9, 6, 7]
Output Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 7]
Output Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 7] 에 보면 6, 7이 함께 읽힌다.
이를 해결하기 위해 코드를 수정해보았다.
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
public class IOTest4 {
public static void main(String[] args) {
byte[] inSrc = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] outSrc = null;
byte[] temp = new byte[4];
ByteArrayInputStream input = null;
ByteArrayOutputStream output = null;
input = new ByteArrayInputStream(inSrc);
output = new ByteArrayOutputStream();
try {
while (input.available() > 0) {
int len = input.read(temp); // 출력을 조절
output.write(temp, 0, len); // 원하는 위치만큼 write
}
} catch (IOException e) {
}
outSrc = output.toByteArray();
System.out.println("Input Source : " + Arrays.toString(inSrc));
System.out.println("temp : " + Arrays.toString(temp)); // [8, 9, 6, 7]
System.out.println("Output Source : " + Arrays.toString(outSrc)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
}
출력 :
Input Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
temp : [8, 9, 6, 7]
Output Source : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
read() 메소드 자체는 바뀌지 않았지만 Output 의 값은 9까지 들어갔다.
파일기반의 IO 스트림
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileViewer {
public static void main(String[] args) {
// FileInputStream , FileOutputStream
// 무조건 예외처리를 해야한다.
try {
FileInputStream fis = new FileInputStream("src/FileViewer.java");
int data = 0;
while ((data = fis.read()) != -1) {
char c = (char) data;
System.out.print(c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
결과 :
public static void main(String[] args) {
// FileInputStream , FileOutputStream
// 무조건 ìì¸ì²ë¦¬ë¥¼ í´ì¼íë¤.
try {
FileInputStream fis = new FileInputStream("src/FileViewer.java");
int data = 0;
while ((data = fis.read()) != -1) {
char c = (char) data;
System.out.print(c);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
한글 주석이 특수문자 처리되어 결과가 나온다.
복붙이 바로 이런 스트림을 이용한 것..!
파일 자체를 복사해 새로 생성하는 프로그램
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("src/FileCopy.java");
FileOutputStream fos = new FileOutputStream("FileCopy.bak");
int data = 0;
while((data = fis.read()) != -1) {
fos.write(data);
}
// 스트림을 사용할 때는 항상 닫아줘야 한다.
// 서버부하를 막기 위함.
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
실행 후 새로고침을 하면 복사한 파일이 생긴다.
보조스트림 연결해보기
main 스트림을 도와주는 역할을 한다.
보조스트림 자체로 구현 X
BufferedInputStream, BufferedOutputStream 보조스트림
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutputTest {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("123.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos, 5); // 생성자에 메인스트림을 연결해야 한다.
for (int i = '1'; i <= '9'; i++) {
bos.write(i);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
출력 : (파일에 출력됨)
12345
5바이트씩 가지고 와야 하는데 나머지는 5바이트를 채우지 못해 가지고 오지 않았다.
→ 버퍼에 데이터가 다 차지 않더라도 flush()를 이용해 데이터를 밀어줄 수 있다.
수정된 코드 :
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedOutputTest {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("123.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos, 5); // 생성자에 메인스트림을 연결해야 한다.
for (int i = '1'; i <= '9'; i++) {
bos.write(i);
}
bos.flush();
// 닫아주는 순서는 역순
bos.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
출력 : (파일에 출력됨)
123456789
→ 보조스트림을 닫아주는 것 만으로도 동작한다.
// bos.flush();
// 닫아주는 순서는 역순
bos.close();
// fos.close();
DataInputStream, DataOutputStream 보조스트림
8가지 기본 자료형의 단위로 읽고, 쓰기 가능
Output에서 write한 순서대로 read 해야한다
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class DataInputStreamTest {
public static void main(String[] args) {
// DataInputStrem, DataOutputStream
// 8가지 기본 자료형의 단위로 읽고, 쓰기 가능
// write한 순서대로 read 해야한다
try {
FileInputStream fis = new FileInputStream("sample.data");
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readInt());
System.out.println(dis.readFloat());
System.out.println(dis.readBoolean());
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
결과 :
10
20.0
true
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamTest {
public static void main(String[] args) {
// DataInputStrem, DataOutputStream
// 8가지 기본 자료형의 단위로 읽고, 쓰기 가능
try {
FileOutputStream fos = new FileOutputStream("sample.data");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeInt(10);
dos.writeFloat(20.0f);
dos.writeBoolean(true);
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
파일을 읽어와 연산 처리하기
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataInputStreamTest2 {
public static void main(String[] args) {
//int[] score = { 100, 90, 95, 85, 50 };
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
int sum = 0;
int count = 0;
// 최대값
// 최소값
// 합계
// 평균
try {
FileInputStream fis = new FileInputStream("score.data");
DataInputStream dis = new DataInputStream(fis);
while(dis.available() > 0) {
int score = dis.readInt();
max = Math.max(max, score);
min = Math.min(min, score);
sum += score;
count++;
}
}catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
double avg = (double) sum / count;
System.out.println("Max: " + max);
System.out.println("Min: " + min);
System.out.println("Sum: " + sum);
System.out.println("Avg: " + avg);
}
}
결과 :
Max: 100
Min: 50
Sum: 420
Avg: 84.0
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamTest2 {
public static void main(String[] args) {
int[] score = { 100, 90, 95, 85, 50 };
try {
FileOutputStream fos = new FileOutputStream("score.data");
DataOutputStream dos = new DataOutputStream(fos);
for(int i : score) {
dos.writeInt(i);
}
dos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
파일을 읽어와 연산 처리하기
- 배열에 스트림연산을 적용해 풀어보기
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
public class DataInputStreamTest3 {
public static void main(String[] args) {
FileInputStream fis = null;
DataInputStream dis = null;
ArrayList<Integer> list = new ArrayList<Integer>();
try {
fis = new FileInputStream("score.data");
dis = new DataInputStream(fis);
while(true) {
list.add(dis.readInt());
}
} catch (EOFException e) {
System.out.println("파일 읽기 완료");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(list);
// 배열의 데이터를 스트림을 이용해 int형의 일차원 배열 만들기
int[] arr = list.stream().mapToInt(i -> i).toArray();
int max = Arrays.stream(arr).max().getAsInt();
int min = Arrays.stream(arr).min().getAsInt();
int sum = Arrays.stream(arr).sum();
double avg = Arrays.stream(arr).average().getAsDouble();
System.out.println("Max: " + max);
System.out.println("Min: " + min);
System.out.println("Sum: " + sum);
System.out.println("Avg: " + avg);
}
}
결과 :
파일 읽기 완료
[100, 90, 95, 85, 50]
Max: 100
Min: 50
Sum: 420
Avg: 84.0
문자 기반 스트림
Reader, Writer -> 인터페이스
내일 이어서..
내일까지 자바를 배움.
'2024_UIUX 국비 TIL' 카테고리의 다른 글
UIUX _국비과정 0603 [오라클DB] (0) | 2024.06.24 |
---|---|
UIUX _국비과정 0531 [문자기반 보조 스트림, 파일클래스, 네트워크] (0) | 2024.06.24 |
UIUX_국비과정 0529 [람다와 스트림] (0) | 2024.06.24 |
UIUX _국비과정 0528 [람다식] (0) | 2024.06.24 |
UIUX _국비과정 0527 [스레드] (1) | 2024.06.24 |