프로그래밍/java

[자바/Java] 입출력(io) / 보조스트림 / BufferredInputStream / DataInputStream / OutputStreamWriter / ObjectInputStream

pupu91 2022. 9. 11. 13:27
반응형

 

기본 스트림과 필터(보조) 스트림

java.io 패키지의 입출력 스트림은 기본 스트림과 필터 스트림으로 분류할 수 있다.

기본 스트림은 외부 데이터에 직접 연결이 되는 스트림이고, 필터 스트림은 외부 데이터에 직접 연결하는 것이 아니라 기본 스트림에 추가로 사용할 수 있는 스트림이다. 주로 성능을 향상 시키는 목적으로 사용되며 생성자를 보면 구분이 가능하다. 생성자 쪽에 매개변수로 다른 스트림을 이용하는 클래스는 필터 스트림이라고 볼 수 있다.

 

 

 

보조스트림

- 스트림의 기능을 향상시키거나 새로운 기능을 추가하기 위해서 사용

- 실제 데이터를 주고 받는 스트림이 아니기 때문에 입출력 처리 불가능

- 기반 스트림을 먼저 생성한 후 이를 이용하여 보조 스트림을 생성

 

보조 스트림의 종류

- 입출력 성능 향상 :  BufferredInputStream / BufferedOutputStream

- 기본 데이터 타입 출력 : DataInputStream / DataOutputStream

- 형변환  : InputStreamReader / OutputStreamWriter

- 객체 입출력 : ObjectInputStream/ObjectOutputStream

ex)
    기반 스트림 생성
    FileInputStream fis = new FileInputStream("sample.txt");
   
    보조스트림 생성
    BufferedInputStream bis = new BufferedInputStream(fis); 
    
    보조스트림으로부터 데이터 읽어오기
    bis.read();

 

 

 

 


입출력 성능 향상 보조 스트림

                      - 느린 속도로 인해 입출력 성능에 영향을 미치는 입출력 소소를 이용하는 경우 사용

                      - 입출력 소스와 직접 작업하지 않고, 버퍼에 데이터를 모아 한꺼번에 작업을 하여 실행 성능을 향상 

                      - 입출력 횟수를 줄임

                      - BufferedInputStream, BufferedReaderStream, BufferedOutputStream, BufferedWriterStream

 

 

 


 

BufferedWriterStream

BufferedWriter bw = null;

        try {
              bw = new BufferedWriter(new FileWriter("src/com/greedy/section03/filterstream/testBuffered.txt"));

              bw.write("안녕하세요\n");
              bw.write("반갑습니다\n");

              버퍼를 이용하는 경우 버퍼가 가득 차면 자동으로 내보내기를 하지만
              버퍼가 가득 차지 않은 상태에서는 강제로 내보내기를 해야한다.
              이 때 flush()를 해주면 파일에 기록 된다.

              bw.flush();

            } catch (IOException e) {
                    e.printStackTrace();
            } finally {
                close()를 호출하면 내부적으로 flush()를 하고 나서 자원을 반납한다.
                if(bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                }
          }

 

 

 

BufferedReader

- 버퍼에 미리 읽어온 후 한 줄 단위로 읽어들이는 기능을 제공하며, 기본 스트림보다 성능을 개선시킴
- readLine()  :버퍼의 한 줄을 읽어와서 문자열로 반환
BufferedReader br = null;
		
		try {
			br = new BufferedReader(new FileReader("src/com/greedy/section03/filterstream/testBuffered.txt"));
			
			String temp;
			while((temp = br.readLine()) != null) {
				System.out.println(temp);
			}
		
		
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

 

 

 

 

 


형변환 보조 스트림

                              - 기본 스트림이 byte 기반 스트림이고, 보조 스트림이 char 기반 스트림인 경우에 사용

                              - 형변환 보조스트림을 사용하여 타입을 같게하는 중간역할

                              -  InputStreamReader , OutputStreamWriter 

 

 


표준 스트림

자바에서는 콘솔이나 키보드 같은 표준 입력 장치로부터 데이터를 입출력하기 위한 스트림을 표준 스트림 형태로 제공하고 있다. System 클래스의 필드 in, out, err가 대상 테이터의 스트림을 의미하며, 모두 byte타입이다.

- System.in (InputStream) : 콘솔로부터 데이터를 입력 받는다.

- System.out (PrintStream) : 콘솔로 데이터를 출력한다.

- System.err (PrintStream) : 콘솔로 데이터를 출력한다.

 

 

InputStreamReader / OutputStreamWriter

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
→ System.in을 InputStreamReader로 변환하여 바이트기반 스트림을 문자 기반 스트림으로 변환 후 버퍼를 이용한
보조스트림과 연결
          
          try {
                        System.out.print("문자열 입력 : ");
                        String value = br.readLine();
                        System.out.println("value : " + value);

                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        if(br != null) {
                            try {
                                br.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }

-----------------------------------------------------------------------------------------------        
         
            출력을 위한 것도 동일한 방식으로 사용할 수 있음. try-with-resource 문으로 작성
		
		try(BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out))) {
			
			bw.write("java oracle jdbc");
			
		} catch (IOException e) {
			e.printStackTrace();
		}

 

 

 

 

 


기본 데이터 타입 보조 스트림

                                   - 외부 데이터로부터 읽어오는 데이터를 바이트 형으로만 읽어오면

                                      정수, 문자, 문자열 등 여러 데이터 타입을 취급하는 경우 별도로 처리를 해주어야한다

                                       ex) 정수을 입력 받아 처리하려면 parsing을 해주어야 함.

                                   - 데이터 자료형 별로 데이터를 읽고 쓰기 가능하도록 기능을 추가한 보조스트림

                                   - DataInputStream, DataOutputStream 

 

 


DataInputStream/ DataOutputStream 

데이터형별로 파일에 기록하는 DataOutputStream 인스턴스 생성 

    try (DataOutputStream dout 
                    = new DataOutputStream(
                            new FileOutputStream("src/com/greedy/section03/filterstream/score.txt"))) {

                파일에 자료형별로 기록(문자열은 UTF 데이터타입 기준으로해서 입출력)
                dout.writeUTF("김영희");
                dout.writeInt(95);
                dout.writeChar('A');

                dout.writeUTF("김철수");
                dout.writeInt(87);
                dout.writeChar('B');

                dout.writeUTF("홍길동");
                dout.writeInt(73);
                dout.writeChar('C');

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
-----------------------------------------------------------------------------------------------------------

데이터형 별로 읽어오는 DataInputStream 인스턴스 생성

	try (DataInputStream din 
			= new DataInputStream(
				new FileInputStream("src/com/greedy/section03/filterstream/score.txt"))) {
			
			
          무한루프로 읽어들이게 되면 파일에 더 이상 읽을 것이 없는 경우 EOFException을 발생시킨다.
		  (End Of File Exception)
		  catch 블럭에 EOFException을 핸들링하는 코드를 추가한다.
			
		  while(true) { 
			파일에 기록한 순서대로 읽어들이지 않는 경우 에러 발생 또는 올바르지 않은 값을 읽어온다.
			System.out.println(din.readUTF() + "," + din.readInt() + "," + din.readChar());
		  }
			
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (EOFException e) {
			System.out.println("파일 읽기를 완료하였습니다.");
		} catch (IOException e) {
			e.printStackTrace();
		} 
		
	}

 

 

 

 

 

반응형

객체 입출력 보조 스트림

                                            - 객체 단위로 파일 또는 네트워크로 입출력 할 수 있는 기능을 제공

                                            - ObjectInputStream, ObjectOutputStream


 

 

 

직렬화와 역직렬화

-  자바 시스템 내부에서 사용되는 객체 또는 데이터를 외부에서도 사용할 수 있도록 바이트(byte) 형태로

  데이터를 변환하는 기술.

- 반대로 바이트로 변환 된 데이터를 다시 객체로 변환하는 기술을 역직렬화라고 함.

- 객체로 입출력하기 위해서는 반드시 직렬화 처리해야 함.

- 직렬화 대상 클래스에 Serializable 인터페이스만 구현하면, 직렬화가 필요한 경우 데이터를 직렬화 처리

 

 

serialVersionUID 필드

- 직렬화된 클래스와 같은 클래스임을 알려주는 식별자

- 컴파일 시 JVM이 자동으로 serialVersionUID 정적필드를 추가해 주기 때문에 별도로 작성하지                                             않아도 오류는 나지 않지만 자동 생성 시 역직렬화에서 예상하지 못한 InvalidClassException을                                           유발할 수 있으므로 명시해 줄 것을 권장

 

 

1) 직렬화 대상 클래스

public class MemberDTO implements java.io.Serializable{
	
	private static final long serialVersionUID = 5694096515393919238L;
	private String id;
	private String pwd;
	private String name;
	private int age;
	private char gender;
	private /*transient*/ double point;
         → 직렬화 대상에서 제외하고 싶은 필드의 경우 transient 키워드를 이용. 제외하면 초기값으로 나옴 
	
	public MemberDTO() {}

	public MemberDTO(String id, String pwd, String name, int age, char gender, double point) {
		super();
		this.id = id;
		this.pwd = pwd;
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.point = point;
	}

	public String getId() {
		return id;
	}

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

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public char getGender() {
		return gender;
	}

	public void setGender(char gender) {
		this.gender = gender;
	}

	public double getPoint() {
		return point;
	}

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

	@Override
	public String toString() {
		return "MemberDTO [id=" + id + ", pwd=" + pwd + ", name=" + name + ", age=" + age + ", gender=" + gender
				+ ", point=" + point + "]";
	}
	
	

}

 

 

 

 

2)  ObjectOutputStream

MemberDTO[] outputMembers = {
				new MemberDTO("user01", "pass01", "김영희", 25, '여', 1250.7),
				new MemberDTO("user02", "pass02", "김철수", 28, '남', 1221.6),
				new MemberDTO("user03", "pass03", "유관순", 16, '여', 1234.3)
		};
		try (ObjectOutputStream oos 
				= new ObjectOutputStream(
						new FileOutputStream("src/com/greedy/section03/filterstream/testObjectStream.txt"))) {
			
			for(int i = 0; i < outputMembers.length; i++) {
				oos.writeObject(outputMembers[i]); // Object단위로 출력하는 메소드
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

 

 

 

 

 

 

 

3) ObjectInputStream

MemberDTO[] inputMembers = new MemberDTO[3]; //읽어왔을때 담을 공간 만들기
		
try (ObjectInputStream ois 
		= new ObjectInputStream(
			new FileInputStream("src/com/greedy/section03/filterstream/testObjectStream.txt"))) {
			
	for(int i = 0; i < inputMembers.length; i++) {
		inputMembers[i] = (MemberDTO) ois.readObject();
		//inputMembers라는 멤버dto배열 쪽에  ois(오브젝트인풋스트림)을 통해서 readObject(하나의 객체를 읽어오겠다)
	 }
			
			
	} catch (FileNotFoundException e) {
			e.printStackTrace();
	} catch (IOException e) {
			e.printStackTrace();
	} catch (ClassNotFoundException e) {//읽어온 Object를 역직렬화 할 수 있는 Class가 없다면 발생
			e.printStackTrace();
	}
		
		
	파일에서 readObject한 결과 출력
	for(MemberDTO member : inputMembers) {
		System.out.println(member);
	}
		
}

 

 

 

반응형