기록

*21일차 (파일 입출력 IO) 본문

학원/강의

*21일차 (파일 입출력 IO)

pringspring 2022. 2. 22. 18:46

@파일입출력(IO)

 

 

 

 

 

*정의

  • input과 output의 약자로 컴퓨터 내부 또는 외부 장치와 프로그램 간의 데이터를 주고 받는 것
  • 다양한 매체에 존재하는 데이터들을 사용하기 위해 입출력 데이터를 처리할 공통적인 방법으로 "스트림" 이용

 

*Input

  • byte 기반 입력 스트림의 최상위 클래스로 추상클래스이다.

 

 

 

 

*Output

  • byte 기반 출력 스트림의 최상위 클래스로 추상클래스이다.

 

 

*Reader

  • 문자 기반 입력 스트림의 최상위 클래스로 추상클래스이다.

 

*Writer

  • 문자 기반 출력 스트림의 최상위 클래스로 추상클래스이다.

 

 

 

 

*FileInputStream

  • 정의 : 파일로부터 byte 단위로 읽어 들일 때 사용함.
  • 그림,오디오,비디오,txt 등 모든 종류의 파일을 읽을 수 있다.
  • InputStream과 사용방법 동일

  -객체생성

  • FileInputStream 객체가 생성될 때 파일과 직접 연결된다.
  • 만약 파일이 존재하지 않으면 FileNotFoundException이 발생하기 때문에 try-catch로 예외처리 할 것.

*FileReader

  • 정의 : txt파일로부터 character 단위로 읽어 들일 때 사용.
  • txt아닌 파일은 못 읽음
  • Reader와 사용방법 동일

  -객체생성

  • FileReader 객체가 생성될 때 파일과 직접 연결.
  • 만약 파일이 존재하지 않으면 FileNotFoundException이 발생하기 때문에 try-catch로 예외처리 할 것.

*FileWriter

  • 정의 : txt파일로부터 character 단위로 저장할 때 사용.
  • txt아닌 파일은 못 읽음
  • writer와 사용방법 동일

  -객체생성

  • FileWriter 객체가 생성될 때 파일과 직접 연결.
  • 만약 파일이 존재하지 않으면 파일 자동 생성
  • 파일이 이미 존재하면 덮어씀

 

 

@보조스트림

 

*정의

  • 스트림의 기능을 향상시키거나 새로운 기능을 추가하기 위해 사용된다.
  • 실제 데이터를 주고 받는 스트림이 아니기 때문에 입출력 처리 X
  • 스트림을 먼저 생성한 후 이를 이용해 보조스트림 생성

 

*종류

  1. 문자변환(In/OutputStreamReader)
  2. 입출력 성능 향상(BufferedIn/OutputStream)
  3. 기본 데이터 타입 출력(DatalnPut/OutputStream)
  4. 객체입출력(ObjectInput/OutputStream)

 

1.

 *정의

  • 소스 스트림이 byte 기반 스트림이지만 데이터가 문자일 경우 사용한다.
  • Reader와 Writer는 문자단위로 입출력을 하기 때문에 데이터가 문자인 경우에 byte 기반 스트림보다 편리하게 사용할 수 있다.

2.

 *정의

  • 느린 속도로 인해 입출력 성능에 영향을 미치는 입출력 소스를 이용하는 경우 사용
  • 입출력 소스와 직접 작업하지 않고 버퍼에 데이터를 모아 한꺼번에 작어해 실행 성능 향상됨 (입출력횟수를 줄임)

 

3.   

 *정의

  • 기본 자료형별 데이터 읽고 쓰기가 가능하도록 기능 제공
  • 입력된 자료형의 순서와 출력될 자료형의 순서가 일치해야 함

4.   

 *정의

  • 객체를 파일 or 네트워크로 입출력할 수 있는 기능을 제공한다.
  • 단 객체는 문자가 아니므로 byte기반 스트림으로 데이터를 변경해주는 작업인 직렬화를 반드시 해야함.

 

 

 

*직렬화(Serializable)

  • 정의 : Serializable 인터페이스를 implements하여 구현한다.
  • 단 객체 직렬화시 private 필드를 포함한 모든 필드를 바이트로 변환하지만 transient 키워드를 사용한 필드는 직렬화에서 제외

*역직렬화

  • 정의 : 직렬화된 객체를 역직렬화 할 때는 직렬화 했을 때와 같은 클래스를 사용
  • 클래스의 이름이 같더라도 클래스의 내용이 변경된 경우 역직렬화에 실패하게 됨.

 

 

#대상이 file인 입출력스트림

  • 기본스트림 FileInputStream | FileOutputStream
  • 보조스트림 BufferedInputStream | BufferedOutputStream
private void test1() {
		// 파일경로는 프로젝트 루트기준으로 조회한다.
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		
		try {
			bis = new BufferedInputStream(new FileInputStream("C:/Users/user1/Desktop/qrcode.pdf"));
			bos = new BufferedOutputStream(new FileOutputStream("qrcode.pdf"));
			
			// 이 파일이 존재하지 않으면 새로 생성
			// 해당경로가 디렉토리 또는 권한 부족시 FileNotFoundException을 던진다.
					
			int len = 0; // 읽어온 byte수
			byte[] bytes = new byte[8192]; // buffered reader 내부적으로 사용하는 버퍼크기
			// 파일을 모두 읽었으면 값없음(-1)을 리턴
			while((len = bis.read(bytes)) != -1) {
				System.out.println(len);
				bos.write(bytes, 0, len); // sampleCopy.txt에 출력 
			}
			
		} catch(IOException e) {
			e.printStackTrace();
		} finally {
			// 사용한 자원은 반드시 반납해야 한다.
			// 보조스트림만 반납하면 주스트림도 내부적으로 함께 반납된다.
			try {
				bis.close();
			} catch(IOException e) {
				e.printStackTrace();
			}
			
			try {
				bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

 

 

 

#객체를 입출력할 클래스는 반드시 Serializable 인터페이스를 구현해야 한다.

public class User implements Serializable {

	/**
	 * 직렬화된 정보와 일치하는 클래스인지 비교하는 고유값
	 */
	private static final long serialVersionUID = 1L;
	
	private String id;
	private String password;
	private int point;
	
	public User() {
		super();
		// TODO Auto-generated constructor stub
	}

	public User(String id, String password, int point) {
		super();
		this.id = id;
		this.password = password;
		this.point = point;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public int getPoint() {
		return point;
	}

	public void setPoint(int point) {
		this.point = point;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", password=" + password + ", point=" + point + "]";
	}
	
}

 

 

#ObjectIO

public static void main(String[] args) {
		ObjectIOStudy study = new ObjectIOStudy();
//		study.test1();
//		study.test2();
		study.test3();
	}
	
	/**
	 * 저장된 객체의 수를 모를때 처리 
	 */
	public void test3() {
		User[] users = new User[100]; // 모자라지 않을 크기로 선언
		int index = 0; // 인덱스관리 변수, 입력된 객체수
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.ser"));){
			while(true) {
				User user = (User) ois.readObject(); // 더이상 읽을 객체가 없을때 EOFException (End Of File) 
				users[index++] = user;
			}
		} catch (EOFException e) {
			// 모든 객체를 다 읽었을때
			for(int i = 0; i < index; i++) {
				System.out.println(users[i]);
			}
			
		} catch (ClassNotFoundException | IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 같은 파일에 대해서 입출력스트림을 동시에 처리하지 말것.
	 */
	public void test2() {
//		FileInputStream fis = new FileInputStream("users.ser");
//		ObjectInputStream ois = new ObjectInputStream(fis);
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.ser"));){
			User[] users = new User[3];
			for(int i = 0; i < users.length; i++) {
				users[i] = (User) ois.readObject(); // down casting
			}
			// users확인
			for(User user : users) {
				System.out.println(user);
			}
		} catch (ClassNotFoundException | IOException e) {
			// multi catch절(1.7) - 관련없는 예외클래스를 묶어서 처리할 수 있다.
			e.printStackTrace();
		}
	}
	
	/**
	 * ObjectInputStream | ObjectOutputStream
	 * - 객체단위로 읽고 쓰기 가능한 보조스트림.
	 * - FileInputStream | FileOutputStream 주스트림과 함께 사용해야 한다.
	 * 
	 * - 읽고 쓰기할 객체의 클래스는 Serializable인터페이스를 반드시 구현해야한다.
	 * - 직렬화 기능 반드시 필요.
	 */
	private void test1() {
		
		User[] users = new User[3];
		users[0] = new User("honggd", "1234", 1000);
		users[1] = new User("sinsa", "1234", 2000);
		users[2] = new User("sejong", "1234", 3000);
		
//		FileOutputStream fos = new FileOutputStream("users.ser");
//		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users.ser"));){
			for(int i = 0; i < users.length; i++) {
				System.out.println(i);
				oos.writeObject(users[i]); // User 객체 단위로 출력!
			}
			
		} catch(IOException e) {
			e.printStackTrace();
		}
		
		
		
	}

 

 

 

#SystemIO

  • 사용자로부터 정수를 여러개 입력받고 출력
  • System.in 과 BufferedReader 사용하기
private void test3() {
		System.out.println("정수를 입력하세요...");
		String input = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		try {
			int sum = 0;
			
			while((input = br.readLine()) != null) {
				if("exit".equals(input)) break;
				
				try {
					sum += Integer.parseInt(input);
				} catch (NumberFormatException e) {
					System.out.println("정수만 입력할 수 있습니다.");
				}
//				System.out.println(sum);
			}
			
			System.out.println("총합은 " + sum + "입니다.");
		} catch(IOException e) {
			e.printStackTrace();
		} 
		
	}

 

 

#System.in 주스트림(표준입력)

  • InputStreamReader 브릿지 스트림
  • BufferedReader 보조스트림(줄단위 읽어오는 readLine 메소드)
  • 대상과 연결된 주스트림 객체를 보조스트림 객체에 전달하고 → 보조스트림을 통해 제어한다.
  • 사용자 입력값을 개행문자단위로 읽어온다. 개행문자를 버리고 return
	private void test2() {
		InputStream systemIn = System.in;
		InputStreamReader isr = new InputStreamReader(systemIn);
		BufferedReader br = new BufferedReader(isr);
		
		String input = null;
		
		try {
			System.out.println("아무말 입력 : ");
			while((input = br.readLine()) != null) {
				if("exit".equals(input))
					break;
				System.out.println(input);
			}
		} catch(IOException e) {
			e.printStackTrace();
		}
		
	}

 

 

#표준입력 : 키보드 입력 System.in

  • Scanner(jdk 1.5)를 사용해 예외처리 없이 사용가능
  • 이전에는 BufferedReader를 이용해 처리

 

 

#표준출력 : 콘솔 입력 System.out

 

  1. 스트림 객체는 자원을 사용후 반드시 반납해야 한다.
  2. 다만 표준입출력은 반납하면 안됨. (한번 반납하면 재사용이 표준입출력 불가함)
	private void test1() {
		int input = 0;
		try {
			System.out.println("키보드로 값을 입력하세요 : ");
			while((input = System.in.read()) != -1) {
				System.out.println(input);
			}
		} catch(IOException e) {
			e.printStackTrace(); // 예외로그
		} 
	}

}

'학원 > 강의' 카테고리의 다른 글

*23일차  (0) 2022.02.24
*22일차 (Collection)  (0) 2022.02.23
*20일차 (Exception)  (0) 2022.02.21
*19일차 (문자열 자르기)  (0) 2022.02.17
*18일차 (추상클래스 / 인터페이스)  (0) 2022.02.16