gwooden_코린이
java_입출력스트림_221207(13일차) 본문
1. 입출력 스트림
(입출력을 한번에 처리해주는 스트림이 없어서 따로 처리해줘야 된다.)
큐 -> FIFO
먼저 들어간게 먼저 나오는 형식
스택 -> FILO 또는 LIFO
먼저 들어간게 제일 마지막에 나오는 형식
단향방 : 한쪽 방향으로만 처리가 가능한 방식 (입력 밖에 못함)
출력을 하고 싶으면 출력 스트림이 따로 있어야 됨
반이중 : 하나의 통로로 입출력이 가능하지만 동시에 처리 불가 (대표적인 예 : 무전기)
전이중 : 주고 받고 다 되는 방식 (대표적이 예 : 인터넷, 채팅 등)
입력 ex) 키보드, 마우스 |
입력 스트림 ---------> |
->(도착치) 프로그램 (출발지)-> |
출력 스트림 ---------> |
출력 ex) 모니터, 프린터 |
바이트 기반 처리 : 영상, 음악, 그림, 사진
InputStream, OutpurStream
문자 기반 처리 : 문자열 (글자를 처리할 때 사용)
Reader, Writer
.read()는 1byte 정수를 가지고 온다.
.read(byte[] b) : 배열 b의 크기만큼 읽어오다가 데이터 -1이 됐을때 리턴
(앞에서 부터 순차적으로 채워주는 방식)
.read(byte[] b, int off, int len) : 최대 len만큼 바이트를 읽음 배열 b[off]에서 부터 저장
(int off에 넣어줄 위치를 설정할 수 있다)
.close() : 스트림 닫아주는 메서드
데이터가 열려있으면 메모리 관리가 어려워 열려있는 데이터를 닫은 상태로 다른 코드가 이루어져야 메모리 관리에 효율적이다.
- 인풋
package kjh221207;
import java.io.FileInputStream;
public class Sample02 {
public static void main(String[] args) {
try { //괄호안에 경로를 설정하면 경로에 있는 데이터를 가져와서 fis 변수에 저장됨
FileInputStream fis = new FileInputStream("src/kjh221207/Sample01.java");
int data = 0; //종료시키게 하기 위한 변수 하나 선언
//.available() <-- 경로가 담긴 변수를 배열을 설정한 [] 괄호안에 넣은수 해당 메서드를 붙이면 변수안에 있는 데이터만큼 배열방이 자동으로 설정됨
byte[] buf = new byte[fis.available()];
//.read() <-- 괄호안에 자료형 타입, 변수를 넣어서 할수도 있다.
while((data=fis.read(buf)) != -1) {
//new String(buf, 0, data) <-- 몇번째 배열방 부터 읽어올건지 지정
System.out.print(new String(buf, 0, data));
}
} catch(Exception e) {
}
}
}
package kjh221207;
import java.io.FileInputStream;
public class Sample02 {
public static void main(String[] args) {
try { //괄호안에 경로를 설정하면 경로에 있는 데이터를 가져와서 fis 변수에 저장됨
FileInputStream fis = new FileInputStream("src/kjh221207/Sample01.java");
int data = 0; //종료시키게 하기 위한 변수 하나 선언
//.available() <-- 해당 메서드는 경로가 담긴 변수에 배열방을 자동으로 설정해줌
byte[] buf = new byte[fis.available()];
System.out.println("크기 : " + fis.available());
//.read() <-- 괄호안에 자료형 타입, 변수를 넣어서 할수도 있다.
//.read(buf, 0, buf.length) <-- (배열변수에서, 몇번째 방부터 , 몇번째 방까지 불러오는 설정)
while((data=fis.read(buf, 0, buf.length)) != -1) {
//new String(buf, 0, data) <-- 몇번째 배열방 부터 읽어올건지 지정
System.out.print(new String(buf, 0, data));
}
} catch(Exception e) {
}
}
}
.read()
.read(char[] c) 문자를 저장하는 배열을 만들때
.read(char[] c, int off, int len)
package kjh221207;
import java.io.FileInputStream;
public class Sample02 {
public static void main(String[] args) {
// <-- fis를 만들어서 쓸건데 아직 뭐에 쓸지 미정상태
// 이런 미정상태에서는 null 값으로 비워두는게 좋다.
FileInputStream fis = null;
try { //괄호안에 경로를 설정하면 경로에 있는 데이터를 가져와서 fis 변수에 저장됨
//위에서 객체를 만들어둘 준비를
fis = new FileInputStream("src/kjh221207/Sample01.java");
int data = 0; //종료시키게 하기 위한 변수 하나 선언
//.available() <-- 해당 메서드는 경로가 담긴 변수에 배열방을 자동으로 설정해줌
byte[] buf = new byte[fis.available()];
System.out.println("크기 : " + fis.available());
//.read() <-- 괄호안에 자료형 타입, 변수를 넣어서 할수도 있다.
//.read(buf, 0, buf.length) <-- (배열변수에서, 몇번째 방부터 , 몇번째 방까지 불러오는 설정)
while((data=fis.read(buf, 0, buf.length)) != -1) {
//new String(buf, 0, data) <-- 몇번째 배열방 부터 읽어올건지 지정
System.out.print(new String(buf, 0, data)); //new String <-- 한글깨진걸 임시방편으로 해결해놓은거
}
} catch(Exception e) {
//무조건 실행시켜주는 기능 finally
} finally {
//.close()를 사용하려면 무조건 try|catch를 같이 사용해야 된다.
try {
//메모리 관리를 위해서 위에 데이터 입력이 끝난 겨우 닫아줘야 되기 때문에 사용
fis.close();
}catch(Exception e) {
}
}
}
}
.close를 하는 이유
변수나 instance(자원)들은 memory에 있는 value(값)와 address(주소)를 제어하는 것인데 입출력할 File 또는 데이터는 저장 장치 공간에 존재하는것 이므로 외부에 있는 자원이고 이 자원을 사용하려면 외부 자원을 열어야 되는데 이때 메모리로 가지고 와야하며 메모리에 남은 공간을 차지하고 있기 때문에 다 사용하고 나면 다시 연결을 해제 해줘야 한다. |
2. 문자(바이트 출력)스트림
Reader - 2byte
package kjh221207;
import java.io.FileReader;
public class Sample03 {
//tharows Exception <-- try | catch가 귀찮을 경우 하지만 단점도 존재 예외처리를 따로 해주고 싶을때 불가능
public static void main(String[] args) {
FileReader fr = null;
try {
fr = new FileReader("src/kjh221207/Sample01.java");
int data = 0;
while((data = fr.read()) != -1) {
System.out.print((char)data);
}
} catch(Exception e) {
} finally {
try {
fr.close();
} catch(Exception e) {
}
}
}
}
package kjh221207;
import java.io.BufferedReader;
import java.io.FileReader;
public class Sample04 {
public static void main(String[] args) {
//순수하게 스트림만 사용하게 되면 속도가 느린 단점이 생기거나 데이터가 순차적으로 안가는 단점 등이 있다.
//메인 스트림 안에 보조 스트림을 끼우는것 (덮여씌우는 느낌)
FileReader fr = null;
BufferedReader br = null; //보조 스트림 (단독으로는 사용 불가)
//BufferedReade <-- 한글자씩 처리하는게 아닌 줄 단위로 처리해서 속도 향상
try {
fr = new FileReader("src/kjh221207/Sample01.java");
br = new BufferedReader(fr); //메인 스트림 fr에 들어있는 경로는 br값에도 가져오기
//줄 단위로 읽어와서 자료형 타입은 String 사용
String txt = null;
//.readLine() <-- 줄단위로 읽어와야 되기 때문에 read가 아닌 readLine
while((txt = br.readLine())!= null) {
System.out.println(txt);
}
} catch (Exception e) {
} finally {
try { //스트림을 닫을려면 연결한 역순으로 닫아야 된다.
//연결 순으로 처리하게 되면 단점으로는 메모리 누수가 생길 수 있다. (불필요한 찌꺼기 데이터 발생 위험)
br.close();
fr.close();
} catch(Exception e) {
}
}
}
}
- 아웃풋
바이트 출력 스트림 - OutputStream
XXXOutputStream
package kjh221207;
import java.io.FileOutputStream;
//아웃풋
public class Sample05 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {//, true <-- 해당 코드를 넣으면 출력할 데이터 값이 계속해서 누적되어 저장된다.
fos = new FileOutputStream("test.txt", true);
//단순히 값을 내보낼때
fos.write(65);
fos.write(66);
fos.write(67);
} catch (Exception e) {
} finally {
try {
fos.flush(); //스트림에 남아있는 내용(찌꺼기)을 다 내보낸 후
fos.close(); //스트림을 닫아준다.
} catch(Exception e) {
}
}
}
}
package kjh221207;
import java.io.FileOutputStream;
//아웃풋
public class Sample05 {
public static void main(String[] args) {
FileOutputStream fos = null;
try { //, true <-- 해당 코드를 넣으면 출력할 데이터 값이 계속해서 누적되어 저장된다.
fos = new FileOutputStream("test.txt", true);
//배열방 내보내기
byte[] b =new byte[26];
byte data = 65;
for(int i = 0; i<26; i++) {
b[i] = data;
data++;
}
//배열에 있는 모든 값을 내보낸다.
fos.write(b);
} catch (Exception e) {
} finally {
try {
fos.flush(); //스트림에 남아있는 내용(찌꺼기)을 다 내보낸 후
fos.close(); //스트림을 닫아준다.
} catch(Exception e) {
}
}
}
}
//배열에 있는 모든 값을에서 0번방 부터 시작해서 5개만 내보낸다
fos.write(b, 0, 5);
package kjh221207;
import java.io.FileOutputStream;
import java.io.PrintStream;
//아웃풋
public class Sample05 {
public static void main(String[] args) {
FileOutputStream fos = null;
PrintStream ps = null;
try {
fos = new FileOutputStream("test.txt", true);
ps = new PrintStream(fos); //보조 스트림, 보조할 대상을 소괄호안에 넣는다.
//프린트스트림을 이용하며 원하는 스타일로 편하게 내보낼 수 있다.
ps.println("가나다");
ps.print(123);
ps.println(true);
ps.print(3.14);
} catch (Exception e) {
} finally {
try {
fos.flush(); //스트림에 남아있는 내용(찌꺼기)을 다 내보낸 후
fos.close(); //스트림을 닫아준다.
} catch(Exception e) {
}
}
}
}
3. 문자 출력 시스템 - Writer
OutputStream(바이트 byte)
- write(int i); 정수를 보낼때
- write(byte[] b); 배열을 보낼 때
- write(byte[] b, int off, int len);
Wirter(문자)
- write(int i);
- write(char[] c); 위와 비교했을때 byte가 아닌 자료형 타입이 바뀜
- write(char[] b, int off, int len);
- write(String str);
- write(String str, int off, int len);
package kjh221207;
import java.io.FileWriter;
public class Sample06 {
public static void main(String[] args) {
//문자 출력 스트림 - Writer
FileWriter fw = null;
try {
fw = new FileWriter("test2.txt");
fw.write('A'); //문자
char[] buf = {'B', 'C', 'D'}; //배열방 생성
fw.write(buf); //배열전체
fw.write(buf, 1, 2); //배열방, 1번 방 부터 해서, 2개만
fw.write("가나다"); //문자열
String str = "가나다라"; //문자열 변수 선언 값은 "가나다라"
fw.write(str); //str 변수 안에 있는 문자열
fw.write(str, 2, 2); //str 문자열 값에 두 번째 부터해서 2개만
} catch(Exception e) {
} finally {
try {
fw.flush(); //찌꺼기 깔끔띠 하기
fw.close(); //청소된 후 스트림 종료시키기
} catch(Exception e) {
}
}
}
}
package 속도비교;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Sample01 {
public static void main(String[] args) throws Exception { //예외처리 떠넘기기
/** ======버퍼 사용 전======= **/
/** 인풋, 아웃풋 메인스트림 */
FileInputStream fis = null;
FileOutputStream fos = null;
/** 인풋, 아웃풋 보조스트림 */
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
int data = 0;
long start = 0;
long end = 0;
fis = new FileInputStream("src/속도비교/apple.jpg"); //내보내기
fos = new FileOutputStream("src/apple.jpg"); //들여보내기
start = System.currentTimeMillis(); //시작 시간
while((data=fis.read()) != -1 ) { //읽어오고
fos.write(data); //내보내고
}
fos.flush(); //찌꺽스 처리
end = System.currentTimeMillis();
fos.close();
fis.close();
System.out.println("버퍼 사용 X : " + (end - start));
/** =========버퍼 사용 후======= **/
fis = new FileInputStream("src/속도비교/apple.jpg");
bis = new BufferedInputStream(fis); //인풋 보조스트림 사용
fos = new FileOutputStream("src/apple.jpg");
bos = new BufferedOutputStream(fos); //아웃풋 보조스트림 사용
start = System.currentTimeMillis(); //시작 시간
//버퍼 사용 부터는 읽어오는 것하고 내보내는 건 버퍼인 보조 스트림 변수 사용
while((data=bis.read()) != -1 ) { //읽어오고
bos.write(data); //내보내고
}
bos.flush(); //퍼버 찌꺽스 처리
end = System.currentTimeMillis();
bis.close();
bos.close();
fos.close();
fis.close();
System.out.println("버퍼 사용 O : " + (end - start));
}
}
4. 기본타입 입출력 보조 스트림
바이트 스트림 -> 입출력 단위 : 바이트 -> 기본타입 : int, char, double, long
(기본 데이터 타입을 거들어 주어 입출력해주는 방식)
- DataInputStream dis = new DataInputStream(바이트 스트림)
ex) read 뒤에 자료형 타입을 붙여준다.
.readInt() 정수형을 읽어올때
.readDouble() 실수형을 읽어올때
.readUTF() 문자열을 읽어올때
- DataOutputStream dos = new DataOutputStream(바이트 스트림)
ex) write 뒤에 자료형 타입을 붙여준다.
.writeInt() 정수형을 내보낼때
.writeDouble() 실수형을 내보낼때
.writeUTF() 문자열을 내보낼때
package 보조시스템;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
public class Sample01 {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("test3.txt");
DataOutputStream dos = new DataOutputStream(fos);
dos.writeUTF("가나다");
dos.writeDouble(12.5);
dos.writeInt(5);
dos.writeBoolean(true);
dos.flush();
dos.close();
fos.close();
}
}
FileInputStream fis = new FileInputStream("test3.txt");
DataInputStream dis = new DataInputStream(fis);
//아웃풋에 입력한 값과 인풋에 입력한 값 순서가 똑같아야 된다.
System.out.println(dis.readUTF());
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
System.out.println(dis.readBoolean());
5. 객체 입출력 보조 시스템
객체 -> 바이트 기반 스트림 사용
객체 출력 -> 객체를 일렬로 바이트로 변경 : 직렬화
객체 입력 -> 바이트 일렬로 객체를 가져와야 함 :역직렬화
- ObjectInputStream
- ObjectOutputStream
package 객체입출력;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class Sample01 {
public static void main(String[] args) throws Exception {
/** 메인 */
/** 단순 내보내는 기능 */
writeList(); //호출 (맨 하단에 있는 writeList 값이 불러와진다.)
//readList를 호출해서 list에 넣는다.
List<Board> list = readList();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for(Board b : list) {
System.out.println(b.getBno() + "\t" + b.getTitle() + "\t" +
b.getContent() + "\t" + b.getWriter() +
"\t" + sdf.format(b.getDate()) );
}
}
/** 출력 관련 작업 */
public static void writeList() throws Exception {
/** 컬렉션 프레임워크 */
//순서가 있는 list를 사용해 여러개 객체를 담는다.
List<Board> list = new ArrayList<>();
/** 컬렉션 프레임 워크 내부에 객체를 채워넣기*/
//.add 매서드로 Board 객체 타입에 맞춰 값을 설정
//새로운 객체 생성 후 list배열방에 객체의 값이 각 방에 들어간다.
list.add(new Board(1, "java", "객체지향", "김자가", new Date() ));
list.add(new Board(2, "js", "절차향", "제이씨", new Date() ));
list.add(new Board(3, "jsp", "음향", "호섭이", new Date() ));
/** 출력 스트림 작업 */
FileOutputStream fos = new FileOutputStream("board.db");
/** 오브젝트 객체 출력 보조 스트림 */
ObjectOutputStream oos = new ObjectOutputStream(fos);
/** 리스트에 있는 값을 내보내기 */
oos.writeObject(list);
/** 마무리 작업 */
oos.flush();
oos.close();
fos.close();
}
/** 입력 관련 작업 */
public static List<Board> readList() throws Exception {
/** 입력 스트림 */
FileInputStream fis = new FileInputStream("board.db");
/** 오브젝트 객체 입력 보조 스트림 */
ObjectInputStream ois = new ObjectInputStream(fis);
// (List<Board>) <-- 형변환 시켜준후 ois안에 "board.db를 list에 보관
List<Board> list = (List<Board>) ois.readObject();
ois.close();
fis.close();
return list;
}
}
package 객체입출력;
import java.io.Serializable;
import java.util.Date;
public class Board implements Serializable { //직렬화 사용하려면 직렬화 인터페이스 구현 필수
/**
* 해당 클래스에 고유번호를 넣어준것
* 직렬화 역직렬화 할때 클래스 이름과 상관없이 시리얼넘버로 체킹하여 실행된다.
* 동일한 클래스인지 판단하기 위해
* 추가된 데이터가 다른 곳으로 가지지 않기 위해 방지하는 차원에서 해당 시리얼넘버가 필요
*/
private static final long serialVersionUID = 1L;
//접근제한자가 없어도 직렬화 포함 or 있어도 직렬화 포함
private int bno;
private String title;
private String content;
private String writer;
private Date date;
//ClassA c =new ClassA(); <-- 이것도 직렬화 포함됨
//Static String content; <--직렬화 제외
//transient String writer; <--직렬화 제외
public Board(int bno, String title, String content, String writer, Date date) {
this.bno = bno;
this.title = title;
this.content = content;
this.writer = writer;
this.date = date;
}
public int getBno() {
return bno;
}
public void setBno(int bno) {
this.bno = bno;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
6. File 클래스 -> 파일의 정보
package 파일클래스;
import java.io.File;
public class Sample01 {
public static void main(String[] args) {
//절대경로
File f = new File("test.txt");
//상대경로
// File f = new File("src/kjh221207/apple.jpg");
//.isFile 메서드는 파일인지 아닌지 true/false로 리턴
System.out.println(f.isFile());
//.isDirectory 폴더인지 확인해주는 메서드
System.out.println(f.isDirectory());
//.getName 파일명 확인해주는 메서드
System.out.println(f.getName());
//.getAbsolutePath 경로 알려주는 메서드
System.out.println(f.getAbsolutePath());
//.canRead 읽기 권한에 대한 메서드
System.out.println(f.canRead());
//.canWrite 쓰기 권한에 대한 메서드
System.out.println(f.canWrite());
//.length byte 크기 알려주는 메서드
System.out.println(f.length() + "byte");
}
}
입출력을 이용해서
RESULT.TXT에
TEST.TXT에 있는 값을 거꾸로 해서
package 문제;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Comparator;
public class Kjh01 {
public static void main(String[] args) throws Exception {
ArrayList<String> lines = new ArrayList<>();
FileReader fr = new FileReader("test.txt");
BufferedReader br = new BufferedReader(fr);
while(true){
String line = br.readLine();
if(line == null)
break;
lines.add(line);
}
br.close();
fr.close();
lines.sort(Comparator.reverseOrder());
PrintWriter pw = new PrintWriter("result.txt");
for(String line : lines) {
pw.println(line);
}
pw.close();
}
}
package 문제;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Comparator;
public class Kjh01 {
public static void main(String[] args) throws Exception {
ArrayList<String> lines = new ArrayList<>();
int sum = 0;
double avg;
FileReader fr = new FileReader("test2.txt");
BufferedReader br = new BufferedReader(fr);
while(true){
String line = br.readLine();
if(line == null)
break;
lines.add(line);
}
for(String line : lines) {
sum = sum + Integer.parseInt(line); //형변환! 문자열을 불러와서 정수로 바꿔준다.
}
avg = (double)sum / lines.size();
System.out.println("합 : " + sum + " 평균 : " + avg);
}
}