상세 컨텐츠

본문 제목

ch6.16~ 보조스트림, 직렬화, 그외 여러 입출력클래스

패캠스프링/part2_java

by hippo0207 2022. 7. 13. 12:01

본문

16. 여러가지 보조 스트림 클래스들

보조 스트림

  • 실제 읽고 쓰는 스트림이 아닌 보조 기능을 제공하는 스트림
  • FilterInputStream과 FilterOutputStream이 보조 스트림의 상위 클래스들
  • 생성자의 매개변수로 또 다른 스트림(기반 스트림이나 다른 보조 스트림)을 가짐
  • Decorator Pattern으로 구현 됨(상속으로 하면 hierarchy(계층)가 복잡해지니 대신이거씀)
  • 상위 클래스 생성자

생성자 

protected FilterInputStream과(InputStream in) 생성자의 매개변수로 InputStream을 받습니다.
public FilterOutputStream(OutputStream out) 생성자의 매개변수로 OutputStream을 받습니다.

InputStreamReader와 OutputStreamWriter

    • 바이트 단위로 읽거나 쓰는 자료를 문자로 변환해주는 보조 스트림
    • FileInputStream으로 읽은 자료를 문자로 변환해주는 예
      public class InputStreamReaderTest {
      
      	public static void main(String[] args) {
      
      		try(InputStreamReader isr = new InputStreamReader(new FileInputStream("reader.txt"))){
      			int i;
      			while( (i = isr.read()) != -1){  //보조 스트림으로 읽습니다.
      				System.out.print((char)i);
      			}
      		}catch(IOException e) {
      			e.printStackTrace();
      		}
      	}
      }

BufferedInputStream과 BufferedOutputStream

  • 약 8k의 배열이 제공되어 입출력이 빠르게 하는 기능이 제공되는 보조 스트림
  • BufferedReader와 BufferedWriter는 문자용 입출력 보조 스트림
  • BufferedInputStream과 BufferedOutputStream을 이용하여 파일 복사하는 예
public class BufferedStreamTest {

	public static void main(String[] args) {

		long millisecond = 0;
		try(FileInputStream fis = new FileInputStream("a.zip");
				FileOutputStream fos = new FileOutputStream("copy.zip");
				BufferedInputStream bis = new BufferedInputStream(fis);
				BufferedOutputStream bos = new BufferedOutputStream(fos)){
		
			millisecond = System.currentTimeMillis();
			
			int i;
			while( ( i = bis.read()) != -1){
				bos.write(i);
			}
			
			millisecond = System.currentTimeMillis() - millisecond;
		}catch(IOException e) {
			e.printStackTrace();
		}
		
		System.out.println("파일 복사 하는 데 " + millisecond + " milliseconds 소요되었습니다.");
	}
}

>>BufferedInputStream, BufferedOutputStream  안쓰면 한번에 한바이트씩 읽고쓰니 오래걸림

DataInputStream과 DataOutputStream

  • 자료가 메모리에 저장된 상태 그대로 읽거나 쓰는 스트림
  • DataInputStream 메서드
  • DataOutputStream 메서드 
  • public class InputStreamReaderTest {
    
    	public static void main(String[] args) {
    
    		try(InputStreamReader isr = new InputStreamReader(new FileInputStream("reader.txt"))){
    			int i;
    			while( (i = isr.read()) != -1){  //보조 스트림으로 읽습니다.
    				System.out.print((char)i);
    			}
    		}catch(IOException e) {
    			e.printStackTrace();
    		}
    	}
    }

BufferedInputStream과 BufferedOutputStream

      • 약 8k의 배열이 제공되어 입출력이 빠르게 하는 기능이 제공되는 보조 스트림
      • BufferedReader와 BufferedWriter는 문자용 입출력 보조 스트림
      • BufferedInputStream과 BufferedOutputStream을 이용하여 파일 복사하는 예
      public class BufferedStreamTest {
      
      	public static void main(String[] args) {
      
      		long millisecond = 0;
      		try(FileInputStream fis = new FileInputStream("a.zip");
      				FileOutputStream fos = new FileOutputStream("copy.zip");
      				BufferedInputStream bis = new BufferedInputStream(fis);
      				BufferedOutputStream bos = new BufferedOutputStream(fos)){
      		
      			millisecond = System.currentTimeMillis();
      			
      			int i;
      			while( ( i = bis.read()) != -1){
      				bos.write(i);
      			}
      			
      			millisecond = System.currentTimeMillis() - millisecond;
      		}catch(IOException e) {
      			e.printStackTrace();
      		}
      		
      		System.out.println("파일 복사 하는 데 " + millisecond + " milliseconds 소요되었습니다.");
              
              Socket socket = new Socket();
              
              BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
              
              br.readLine(문자읽고~~);
      	}
      }

DataInputStream과 DataOutputStream

      • 자료가 메모리에 저장된 상태 그대로 읽거나 쓰는 스트림
      • DataInputStream 메서드

      • DataOutputStream 메서드

public class DataStreamTest {

	public static void main(String[] args) {


		try(FileOutputStream fos = new FileOutputStream("data.txt");
				DataOutputStream dos = new DataOutputStream(fos))
		{
		
			dos.writeByte(100); >>> byte로 썼으면
			dos.writeChar('A');
			dos.writeInt(10);
			dos.writeFloat(3.14f);
			dos.writeUTF("Test");
		}catch(IOException e) {
			e.printStackTrace();
		}
		
		try(FileInputStream fis = new FileInputStream("data.txt");
				DataInputStream dis = new DataInputStream(fis))
		{
		
			System.out.println(dis.readByte()); >> byte로 읽어야 함
			System.out.println(dis.readChar());
			System.out.println(dis.readInt());
			System.out.println(dis.readFloat());
			System.out.println(dis.readUTF());
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}

17. 직렬화

serialization 이란?

  • 인스턴스의 상태를 그대로 파일 저장하거나 네트웍으로 전송하고 (serialization) 이를 다시 복원(deserializatio) 하는 방식
  • 자바에서는 보조 스트림을 활용하여 직렬화를 제공함
  • ObjectInputStream과 ObjectOutputStream
ObjectInputStream(InputStream in) InputStream을 생성자의 매개변수로 받아 ObjectInputStream을 생성합니다.
ObjectOutputStream(OutputStream out) OutputStream을 생성자의 매개변수로 받아 ObjectOutputStream을 생성합니다.

Serializable 인터페이스

  • 직렬화는 인스턴스의 내용이 외부로 유출되는 것이므로 프로그래머가 해당 객체에 대한 직렬화 의도를 표시해야 함
  • 구현 코드가 없는 marker interface
  • transient : 직렬화 하지 않으려는 멤버 변수에 사용함 (Socket등 직렬화 할 수 없는 객체)
class Person implements Serializable{
	
	private static final long serialVersionUID = -1503252402544036183L;

	String name;
	transient String job; >> socket처럼 직렬화안되는 개체는 저렇게하면됨
	
	public Person() {}

	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString()
	{
		return name + "," + job;
	}
}


public class SerializationTest {

	public static void main(String[] args) throws ClassNotFoundException {

		Person personAhn = new Person("이순신", "대표이사");
		Person personKim = new Person("김유신", "상무이사");
		
		try(FileOutputStream fos = new FileOutputStream("serial.out");
				ObjectOutputStream oos = new ObjectOutputStream(fos)){
			
			oos.writeObject(personAhn);
			oos.writeObject(personKim);
		
		}catch(IOException e) {
			e.printStackTrace();
		}
			
		try(FileInputStream fis = new FileInputStream("serial.out");
			ObjectInputStream ois = new ObjectInputStream(fis)){
			
			Person p1 = (Person)ois.readObject();
			Person p2 = (Person)ois.readObject();
			
			System.out.println(p1);
			System.out.println(p2);
		}catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Externalizable 인터페이스

  • writerExternal()과 readExternal()메서드를 구현해야 함
  • 프로그래머가 직접 객체를 읽고 쓰는 코드를 구현 할 수 있음
class Person implements Externalizable{
	
	String name;
	String job;
	
	public Person() {}

	public Person(String name, String job) {
		this.name = name;
		this.job = job;
	}
	
	public String toString()
	{
		return name + "," + job;
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeUTF(name);
		//out.writeUTF(job);
	}

	@Override
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		name = in.readUTF();
		//job = in.readUTF();
	}
	
}

18. 그 외 여러가지 입출력 클래스들

File 클래스

  • 파일 개념을 추상화한 클래스
  • 입출력 기능은 없고, 파일의 이름, 경로, 읽기 전용등의 속성을 알수 있음
  • 이를 지원하는 여러 메서드들이 제공됨
public class FileTest {

	public static void main(String[] args) throws IOException {

		File file = new File("D:\\JAVA_LAB\\Chapter6\\newFile.txt"); 
        // 파일은 없어도 디렉토리는 있어야 함
		file.createNewFile(); // 이거 써야 파일생성함
		
		System.out.println(file.isFile());
		System.out.println(file.isDirectory());
		System.out.println(file.getName());
		System.out.println(file.getAbsolutePath());
		System.out.println(file.getPath());
		System.out.println(file.canRead());
		System.out.println(file.canWrite());
		
		file.delete();
	}
}

RandomAccessFile 클래스

  • 입출력 클래스 중 유일하게 파일에 대한 입력과 출력을 동시에 할 수 있는 클래스
  • 파일 포인터가 있어서 읽고 쓰는 위치의 이동이 가능함
  • 다양한 메서드가 제공됨
public class RandomAccessFileTest {

	public static void main(String[] args) throws IOException {
		RandomAccessFile rf = new RandomAccessFile("random.txt", "rw");
		rf.writeInt(100);
		System.out.println("파일 포인터 위치:" + rf.getFilePointer()); //int 4byte라 4
		rf.writeDouble(3.14); // double : 8byte
		System.out.println("파일 포인터 위치:" + rf.getFilePointer()); // 4+8 , 12
		rf.writeUTF("안녕하세요"); // 한글은 3byte씩 15 + 끝에 null 2byte
		System.out.println("파일 포인터 위치:" + rf.getFilePointer()); 12+17 =29
	
		rf.seek(0); // 다시 맨앞으로 가라
		System.out.println("파일 포인터 위치:" + rf.getFilePointer());
		
		int i = rf.readInt();
		double d = rf.readDouble();
		String str = rf.readUTF();
	
		System.out.println("파일 포인터 위치:" + rf.getFilePointer());
		System.out.println(i);
		System.out.println(d);
		System.out.println(str);
	}
}

=========
파일 포인터 위치 : 4
파일 포인터 위치: 12
파일 포인터 위치: 29
파일 포인터 위치:0
파일 포인터 위치:29
100
3.14
안녕하세요

관련글 더보기

댓글 영역