자바 파일과 i/o[input / output] - 두 대상 간의 데이터를 주고 받는것
자바 입출력 스트림의 종류
데이터 기본 단위 : 바이트 스트림
-바이트 스트림은 1바이트를 입/출력 할 수 있는 스트림
-파일의 복사
문자 스트림
-유니코드로 된 문자를 입/출력 하는 스트림
-2바이트를 입/출력 - 세계 모든 언어로 구성된 파일을 입/출력 하기에 적합
-이미지,동영상과 같은 바이너리 데이터는 입/출력 할 수 없음
-문자 데이터만 입/출력 가능
프로그램에서 성능 => 속도
버퍼 스트림[보조, 필터 스트림]
-단독 사용 불가
-스트림의 기능을 향상 시키거나 새로운 기능을 추가하기 위해 사용
-문자 입력 스트림으로부터 문자를 읽어 들이거나 문자 출력 스트림으로 문자를 내보낼 때 버퍼링을 함으로써 문자,문자 배열, 문자열 라인 등을 보다 효율적으로 처리
*****참고*****
FileInputStream
FileOutputStream
해당 객체로 일괄 처리 / 객체 직렬화 :
ObjectInputStream - 읽기 -> 복원 (클래스의 메소드 :인스턴스복원)
ObjectOutputStream - 쓰기 -> 저장 (클래스의 메소드 :인스턴스저장)
파일에 있는 데이터를 읽어 들이는 것을 input
파일에 있는 데이터를 내보내는 것을 output
stream [스트림] - 흐름 , 물줄기
-연속적인 데이터의 흐름
-데이터를 운반[입출력]하는데 사용되는 연결통로
-하나의 스트림으로 입출력을 동시에 수행할 수 없다.(단방향 통신)
-읽기,쓰기가 동시에 되지 않음
-읽는 스트림과 쓰는 스트림을 하나씩 열어[instance 생성] 사용해야 함
-FiFo 구조[ first in first out] - 먼저 들어간 것이 먼저 나오는 형태 -> 데이터의 순서가 바뀌지 않음
-스트림은 지연될 수 있음
inputStream의 개념
출력 :- file로 쓰는 것 [ 하드디스크에 저장되어 있는 파일]
- usb와 같은 외부 메모리 장치
- 네트워크로 연결되어 있는 컴퓨터
- 사운드 카드, 오디오카드 같은 멀티 미디어 장치
입출력 대상이 달라지면 프로그램 상에서의 입출력 방식도 달라지는 것이 보통이다.
하지만 자바에서는 입출력대상에 상관없이 입출력의 진행 방식이 동일 하도록 별도의 'i/o모델'을 정의하고 있다.
InputStream class
InputStream in = new FileInputStream("run.exe);
int bData = in.read(); / 1byte 데이터
in.close();
-대표적인 메소드 : read() - 더 이상 읽어들일 데이터가 없다면 '-1'을 반환 , close() - 입력 스트림 소멸
OutputStream class
write(), cloes()
OutputStream out = new FileOutputStream("home.bin);
out.write(1); / 4바이트 int형 정수 1의 하위 1바이트만 전달된다.
ouut.close();
bufferedReader 와 bufferedWriter
-text기반 파일은 buffered 이용
-입출력 효율을 높이기 위해 버퍼(char[])를 사용하는 보조스트림
-라인 단위의 입출력이 편리하다.
I/O 파일 입출력 관련 예제 |
package ex.io1;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class MemoUtil {
File[] list;
private File utilMemo;
//현재 시간을 저장하는 메서드
public static String nowDateTime() {
LocalDateTime current = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yy년 MM월 dd일 hh시 mm분");
String now = current.format(formatter);
return now;
}
// String 타입으로 리턴해주는 스캐너 메서드
public static String getUserInput() {
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
return input;
}
//저장된 파일의 목록을 보여주는 메서드
public void listFile() {
System.out.println("찾을 경로의 폴더를 입력해주세요.");
String rootFolder = getUserInput();
utilMemo = new File(rootFolder);
if(utilMemo.exists()) {
list = utilMemo.listFiles();
for(int i = 0; i < list.length; i++) {
System.out.println(list[i].getName());
}
}else {
System.out.println("잘못된 경로입니다 다시 입력하세요.");
}
}
//저장된 파일을 찾는 메서드
public void findFile() {
System.out.println("찾을 경로의 폴더를 입력해주세요");
String findFolder = getUserInput();
utilMemo = new File(findFolder);
if(utilMemo.exists()) {
System.out.println("찾을 파일의 제목을 입력해주세요.");
String memoFile = getUserInput();
try {
BufferedReader in = new BufferedReader(new FileReader(utilMemo+"\\"+memoFile+".txt"));
String str;
while(true) {
str = in.readLine();
if(str == null) {
break;
}
System.out.println(str);
}
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else {
System.out.println(findFolder+"의 폴더가 존재하지 않습니다.");
}
}
public void writeFile() {
// 1.콘솔기반으로 메모장 기능을 만들어 봅시다.
//제목,내용,날짜
System.out.println("파일에 메모할 내용을 입력해주세요.");
System.out.print("제목을 입력하세요: >> ");
String title = getUserInput();
System.out.print("작성자를 입력하세요. : >>");
String name = getUserInput();
System.out.print("내용을 입력하세요.: >>");
String content = getUserInput();
System.out.println("날짜와 시간은 현재시간으로 저장됩니다.");
String nowT = nowDateTime();
// ①File 클래스를 이용해서 저장 폴더 생성
//경로 생성
System.out.println("저장할 경로와 폴더명을 입력해주세요.");
String newDir = getUserInput();
File memoF = new File(newDir);
if(!memoF.exists()) {
//경로의 폴더를 만들어 주는 메서드
memoF.mkdirs();
System.out.println("메모장 폴더를 생성합니다.");
}
// ②문자기반 스트림을 이용해서 날짜와 제목, 메모를 파일에 저장
//스캐너로 입력받은 문자열을 write메소드에 인자로 전달
try {
// ③파일의 이름은 날짜와 메모의 제목을 이용해서 생성
BufferedWriter bWrite = new BufferedWriter(new FileWriter(newDir+"\\"+title+".txt"));
bWrite.write("제목 :"+title);
bWrite.newLine();
bWrite.write("작성자 :"+name);
bWrite.newLine();
bWrite.write("내용 :"+ content);
bWrite.newLine();
bWrite.write("작성 시간 :"+nowT);
bWrite.close();
System.out.println("작성을 완료하였습니다.");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
===========================================================================================================
package ex.io1;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
public class MemoTest {
public static void main(String[] args) {
//저장된 파일의 내용을 출력해주는 기능의 인스턴스 생성
MemoUtil memoUtil = new MemoUtil();
int num = Integer.parseInt(MemoUtil.getUserInput());
while(!(num == 4)) {
showMenu();
switch(num) {
case 1:
System.out.println("1.메모장 작성");
// 메모장 기능을 구현하고 경로 폴더를 지정하고 쓰는 메서드
memoUtil.writeFile();
break;
case 2:
System.out.println("2.메모장 파일 읽기");
// 파일 읽기 기능을 구현해봅시다.
memoUtil.findFile();
break;
case 3:
System.out.println("3.메모리스트 출력");
// 메모리스트를 보여줍니다.
memoUtil.listFile();
break;
case 4:
System.out.println("프로그램이 종료됩니다.");
System.exit(0);
break;
}
}
}
public static void showMenu(){
System.out.println("=============================");
System.out.println("=============메뉴=============");
System.out.println("1.메모장 작성");
System.out.println("2.메모장 파일 읽기");
System.out.println("3.메모장 리스트 출력");
System.out.println("4.프로그램 종료");
System.out.println("=============================");
}
}
직렬화(serialization) :
-인스턴스가 파일에 저장되는 과정(저장을 위해 거치는 과정)을 가리켜 '직렬화' 라고 한다.
-객체를 '연속적인 데이터'로 변환하는 것. 반대과정은 '역직렬화' 라고 한다,
-객체의 인스턴스변수들의 값을 일렬로 나열하는 것
직렬화의 대상이 되는 인스턴스의 클래스는 java.io.serializable 인터페이스를 구현해야 한다
직렬화의 대상에서 제외 - transient .
실제 프로그램 개발에서는 절대 경로가 아닌 상대경로를 이용하는 것이 일반적이다. 그래야 실행 환경 및 실행위치의 변경에 따른 문제점을 최소화 할 수 있기 때문이다.
직렬화 예제 |
=======================================================================================
직렬화를 위한 클래스 생성
package ex1.io3;
import java.io.Serializable;
import java.util.*;
import com.test_14.FootballPlayer;
public class Player implements Serializable,Comparable<Player>{
String name;
int number;
String team;
int age;
public Player(String name, int number, String team, int age) {
this.name = name;
this.number = number;
this.team = team;
this.age = age;
}
public void showData() {
System.out.println("이름:"+name);
System.out.println("번호:"+number);
System.out.println("팀:"+team);
System.out.println("나이:"+age);
}
public int hashCode() {
return age % 3;
}
@Override
public int compareTo(Player o) {
int result = this.team.compareTo(o.team);
//같은 팀이라면
if(result == 0) {
result = this.name.compareTo(o.name);
//이름이 같다면
if(result == 0) {
// 나이로 비교해서 정렬
result = this.age - o.age;
}
}
return result;
}
public boolean equals(Object obj) {
boolean result = false;
if (obj != null && obj instanceof Player) {
Player fb = (Player) obj;
if (this.team.equals(fb.team) && this.name.equals(fb.name)) {
result = true;
}
}
return result;
}
public String toString() {
return team+ name +age +number;
}
}
=====================================================================================
package ex1.io3;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class PlayerList {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
// file의 경로지정
File playerInfo = new File("C:\\myTextEx\\player");
if(!playerInfo.exists()) {
playerInfo.mkdirs();
System.out.println("player 폴더를 생성하였습니다!");
}
// 인스턴스 저장
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(playerInfo+"\\Player.ser"));
List<Player> player = new ArrayList<>();
player.add(new Player("son",7,"tot",28));
player.add(new Player("park",7,"mu",38));
player.add(new Player("cha",1,"ger",33));
player.add(new Player("ji",5,"ch",22));
player.add(new Player("son",10,"tot",27));
out.writeObject(player);
out.close();
System.out.println("저장을 완료하였습니다.");
// 인스턴스 복원
ObjectInputStream in = new ObjectInputStream(new FileInputStream(playerInfo+"\\Player.ser"));
ArrayList<Player> rePlayer =(ArrayList<Player>) in.readObject();
in.close();
System.out.println("인스턴스 복원 완료!");
//인스턴스 출력
System.out.println("인스턴스 출력");
Iterator itr = rePlayer.iterator();
while(itr.hasNext()) {
System.out.println(itr.next());
}
}
}