~전편에 이어서~

ObjectStream을 활용해보자!

 


# 오늘의 코딩 #

[순서]

1. 먼저 내보낼 객체의 기반이 되는 'MyData' Class를 생성 (Serializable interface를 구현한 클래스) 

2. ObjectStream활용을 위한 클래스를 생성하여 write와 read method를 작성/실행해보자

 

#1. MyData Class

- 사용자 정보를 가지고 있으며 직렬화가 막혀있는 변수가 존재함

package test;

import java.io.Serializable;

/**
 * 사용자의 정보를 가진 클래스
 * @author user
 */
public class MyData implements Serializable{
		
	/**
	 * serialVersionUID : 이 클래스 파일이 JVM 외부로 빠져나갔을 때 파일을 검증하기 위한 용도의 Constant
	 * 객체가 JVM 외부로 나갔을 때 검증하기 위해서 ID를 부여함
	 * 1. 현재 JVM에서 빠져나간 객체임을 검증 가능
	 * 2. 시간에 대한 체크 가능
	 */
	private static final long serialVersionUID = -6444648902030740467L;
	private double height;
	private transient double weight; // 직렬화를 막기 위해서는 transient를 걸자 (직렬화 방지)
	private int age;
	private transient String name; // 직렬화 방지
	
	public MyData() {
	}

	public MyData(double height, double weight, int age, String name) {
		this.height = height;
		this.weight = weight;
		this.age = age;
		this.name = name;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	public double getWeight() {
		return weight;
	}

	public void setWeight(double weight) {
		this.weight = weight;
	}

	public int getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "MyData [height=" + height + ", weight=" + weight + ", age=" + age + ", name=" + name + "]";
	}
	
}//class

 

#2. UseObjectStream Class

1) MyData Class를 활용하여 객체 내보내기/읽기 Stream을 실행하는 class

package test;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 객체를 직렬화하여 JVM외부로 내보내거나 읽어들이는 클래스
 */
public class UseObjectStream {

	public void writeObj(MyData md) throws IOException, NotSerializableException {
		// 1. 스트림 생성
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(new File("C:/Users/user/Desktop/obj.txt")));
			// 2. 객체 스트림에 기록
			oos.writeObject(md);
			// 3. 스트림의 내용 분출
			oos.flush();
		} finally {
			// 4. 연결 끊기
			if (oos != null) {
				oos.close();
			}//end if
		}//end finally
	}// writeObj

	public MyData readObj() throws IOException, ClassNotFoundException {
		MyData md = null;

		// 1. 스트림 생성
		ObjectInputStream ois = null;
		try {
			ois = new ObjectInputStream(new FileInputStream(new File("C:/Users/user/Desktop/obj.txt")));
			// 2. 스트림에서 객체 읽기
			md = (MyData) ois.readObject(); // method 반환형이 object이므로 클래스로 casting 해줘야 값을 받아올 수 있음
		} finally {
			// 3. 연결 끊기
			if (ois != null) {
				ois.close();
			} // end if
		} // end fianlly
		return md;
	}// readObj

 

2) main maethod에서 실행해보자!! writeObj를 먼저 실행하면!

	public static void main(String[] args) {

		MyData md = new MyData(180.3, 73.2, 26, "김동동");
		UseObjectStream uos = new UseObjectStream();

		try {
			uos.writeObj(md);
			System.out.println("직렬화된 객체:" + md);
		} catch (NotSerializableException nse) {
			System.out.println("객체가 직렬화되지 않습니다.");
			nse.printStackTrace();
		} catch (IOException ie) {
			System.out.println("객체를 쓰는 동안 문제 발생");
			ie.printStackTrace();
		} // end catch

	}// main

}// class

# 출력 결과 #

- JVM외부로 나간 객체의 내용 & 설정한 경로에 작성된 파일

 

 

3) readObj method도 실행해보자!

		try {
			MyData md1 = uos.readObj();
			System.out.println("역직렬화된 객체:" + md1);
		} catch (ClassNotFoundException cnfe) {
			cnfe.printStackTrace();
		} catch (IOException ie) {
			ie.printStackTrace();
		} // end catch
		
	}// main

}// class

 

# 출력 결과 #

- MyData Class에서 직렬화 방지를 위해 transient로 막아둔 변수는 null로 읽힘 

  >> 해당 변수는 JVM외부로 나가지 않았다라는 것 확인!

 

 1. IO(Input/Output) Stream 

- JVM에서 JVM외부에 존재하는 데이터를 읽어들이거나(Input),

  JVM내부의 데이터를 JVM외부로 내보낼 때(Output) 사용하는 기술 (txt, dat만 가능)

- 독자 포맷(hwp,xls,ppt)이 있는 파일은 읽어 들일 수 있지만 내용을 확인할 수 없음

- 독자 포맷의 파일을 생성할 수 없음

- java.io.package에서 관련 클래스를 제공

- 8bit stream(byte 기반)과 16bit stram(문자열 기반)이 제공

- 단방향 스트림 (읽기 스트림은 읽기만 가능하고, 쓰기 스트림은 쓰기만 가능)

- 스트림은 연결해서 사용할 수 있음 (FileReader랑 BufferedReader 같이 사용하는 등)

- Stream은 사용 후 꼭 close()! // 스트림을 끊어서 메모리 누수(memory leak)을 막자

 

 1) 8bit Stream 

- byte 기반 스트림

- 모든 data를 읽고 쓸 수 있는 스트림

- 한 byte씩만 읽어들일 수 있음

- 파일 복사에 많이 씀

- 16bit Stream보다 속도가 빠름 / 단, 한 번에 보내고 받는 양은 적음

- 부모클래스는 java.io.InputStream, java.io.OutputStream

읽기 스트림 - InputStream
FileInputStream 파일에서 읽어 들이는 일
DatainputStream 자바의 기본 데이터형으로 읽어 들일 때
ObjectInputStream 객체를 읽어 들일 때

 

쓰기 스트림 - OutputStream
FileOutputStream 파일로 내보내는 일
DataOutputStream 자바의 기본 데이터형을 내보내는 일
ObjectOutputStream 객체를 내보내는 일

 

 2) 16bit Stream 

- 문자열 기반 스트림

- 문자열만 읽고 쓸 수 있는 스트림

- 문자열을 입력받기 위해서 고안한 Stream

- 8bit 보다 속도가 느림 / 단, 한 번에 보내고 받는 양은 큼

- 부모클래스는  java.io.Reader, java.io.Writer

읽기 스트림 - Reader
FileReader 파일에서 읽어 들이는 일
BufferedReader 16bit 스트림의 속도 향상을 위해 만들어진 Stream
InputStreamReader 8bit 스트림과 16bit 스트림을 연결할 때 사용

 

쓰기 스트림 - Writer
FileWriter 파일로 내보내는 일
BufferedWriter 쓰기속도 향상
OutputStreamWriter 8bit 스크림과 16bit 스트림을 연결할 때 사용

 

 

 2. java.io.File 

- HDD(하드디스크)에 존재하는 파일의 정보를 얻을 때, directory를 생성할 때, 파일 삭제할 때 사용

 

- 사용법)

 

<-- 파일 정보 -->

① 객체 생성 :

    File file = new File (“경로”); // C:/dev/env.bat

② 하기 method 활용

    - 절대경로 얻기 :

      > 파일에 접근할 수 있는 두가지 경로 : C:/dev/env.bat or c:/dev/env.bat – 드라이브 문자 대소문자 상관없음

      > String str = file.getAbsolutePath();

    - 규범경로 얻기 :

      > 파일에 접근할 수 있는 하나의 경로 : C:/dev/env.bat – 드라이브 문자 항상 대문자

      > try {String path = file.getCannonicalPath(); // IOException 존재하므로 try~catch

         } catch (IOException ie) {  }

    - 경로 얻기 : String path = file.getPath();

    - 디렉토리명 얻기 : String directory = file.getParent() ; // C:/dev/

    - 파일명 얻기 : String fileName = file.getName(); / env.bat

    - 파일인지? : boolean flag = file.isFile();

    - 폴더인지? : boolean flag = file.isDirectory();

    - 읽기 가능? : boolean flag = file.canRead();

    - 쓰기 가능? : boolean flag = file.canWrite();

    - 실행 가능? : boolean flag = file.canExecute();

    - 숨김파일 : boolean flag = file. isHidden();

    - 마지막 수정일자 : long modified = file.lastmodified();

    - 파일 있는지 : file.exists();

 

<-- Directory 생성 -->

① 객체 생성 : 생성할 폴더명을 가진 File 생성

    FIle file = new File (“e:/dev/temp1”)

② 폴더 생성 : 폴더가 존재하면 false 반환, 존재하지 않으면 폴더를 생성하고 true 반환

    file.mkdir(); // 상위폴더가 존재하지 않으면 폴더를 생성할 수 없음 // dev 폴더 없으면 생성 불가 

    file.mkdirs(); // 상위폴더가 존재하지 않으면 상위 폴더부터 폴더를 생성함 // dev부터 만들고 temp1 생성

 

<-- 파일 삭제 -->

① 삭제할 파일명으로 File을 생성

     File file = new File(“경로”);

② 파일 삭제

           file.delete();

 

<-- 파일명 변경 -->

① 원본 파일명으로 File을 생성

           File file = new File (“경로”);

② 변경할 파일명으로 File 생성

           File refile = new File (“변경할 경로”);

③ 변경할 이름을 설정 : file.renameTo(refile);

+ Recent posts