백엔드/Java의 정석

TIL 정리_32

ran4 2022. 3. 19. 20:05

File

파일은 기본적이면서도 가장 많이 사용되는 입출력 대상이기 때문에 중요하다

자바에서는 File 클래스를 통해서 파일과 디렉토리를 다룰 수 있도록 하고 있다

-> File 인스턴스는 파일일 수도 있고 디렉토리일 수도 있다

 

File의 생성자와 경로에 관련된 메서드

생성자/메서드 설명
File(String fileName) 주어진 문자열을 이름으로 갖는 파일을 위한 File
인스턴스를 생성한다. 파일뿐만 아니라 디렉토리도 같은 방법으로 다룬다
fileName은 주로 경로를 포함해서 지정해주지만, 파일 이름만 사용해도 되는데, 이 경우 프로그램이 실행되는 위치가 경로(path)로 간주된다.
File(String pathName, String fileName)
File(File pathName, string fileName)
파일의 경로와 이름을 따로 분리해서 지정할 수 있도록 한 생성자. 이 중 두 번째 것은 경로를 문자열이 아닌 File인스턴스인 경우를 위해서 제공된 것이다.
File(URI uri) 지정된 uri로 파일을 생성
String getName() 파일이름을 String으로 변환
String getPath() 파일의 경로(path)String으로 반환
String getAbsoulutePath()
File getAbsoluteFile()
파일의 절대경로를 String으로 반환
파일의 절대경로를 File로 반환
String getParent()
File getParentFile()
파일의 조상 디렉토리를 String으로 반환
파일의 조상 디렉토리를 File로 반환
String getCanonicalPath()
File getCanonicalFile()
파일의 정규경로를 String으로 반환
파일의 정규경로를 File로 반환

 

경로와 관련된 File의 멤버변수

멤버변수 설명
static String pathSeparator OS에서 사용하는 경로 구분자. 윈도우 “;”, 유닉스“:”
static char pathSeparatorChar OS에서 사용하는 경로 구분자 윈도우 ‘;’, 유닉스 ‘:’
static String separator OS에서 사용하는 이름 구분자 윈도우 “\”, 유닉스 “/”
static char separatorChar OS에서 사용하는 이름 구분자 윈도우 ‘\’, 유닉스 ‘/’

->파일의 경로와 디렉토리나 파일의 이름을 구분하는데 사용되는 구분자가 OS마다 다를 수 있기 때문에 OS 독립적으로 프로그램을 작성하기 위해서는 위의 멤버변수들을 이용해야 한다

 

 

절대경로(absolute path)는 파일시스템의 루트(root)0로부터 시작하는 파일의 전체 경로를 의미한다

하나의 파일에 대해 둘 이상의 절대경로가 존재할 수 있다 //OS마다 다르다

-> 현재 디렉토리를 의미하는 ‘.’와 같은 기호나 링크를 포함하는 경우가 이에 해당한다

 

정규경로(canonical path) 기호나 링크 등을 포함하지 않는 유일한 경로를 의미한다

 

File인스턴스를 생성했다고 해서 파일이나 디렉토리가 생성되는 것은 아니다

새로운 파일을 생성하기 위해서는 File인스턴스를 생성한 다음 출력 스트림을 생성하거나

createNewFile()을 호출해야 한다 

 


1. 이미 존재하는 파일을 참조할 때 :
File f = new File(“파일경로”, “FileEx1.java”);

2. 기존에 없는 파일을 새로 생성할 때 :
File f = new FIle(“파일경로”, “NewFile.java”);
f.createNewFile(); //새로운 파일이 생성된다

 

printFileList(File dir)는 디렉토리에 포함된 파일과 디렉토리의 목록을 출력하는 메서드이다

파일을 목록을 출력하고 디렉토리인 경우 ArrayList에 담았다가 printFileList(File dir)을 재귀호출한다 //재귀호출만으로도 처리가 가능함

 

FilenameFilteraccept메서드 하나만 선언되어 있으며 메서드만 구현해주면 된다

public interface FilenameFilter {

boolean accept(File dir, String name); }

 

직렬화(serialization)

객체를 데이터 스트림으로 만드는 것을 의미한다

객체에 저장된 데이터를 스트림에 쓰기위해 연속적인 데이터로 변환한다

역직렬화(deserialization) : 스트림으로부터 데이터를 읽어서 객체를 만드는 것

 

직렬화는 객체가 컴퓨터에 저장되었다가 다시 꺼내 쓸 수 있도록 하며 네트웍을 통해 컴퓨터간에 서로 객체를 주고받을 수 있게한다

 

**간단하게 되짚어보는 객체지향

객체는 클래스에 정의된 인스턴스 변수의 집합이다

사실 객체에는 메서드가 포함되지 않는다

->객체를 저장한다는 것은 객체의 모든 인스턴스 변수의 값을 저장한다는 것과 같은 의미이다

 

ObjectInputStream, ObjectOutputStream

직렬화(스트림에 객체를 출력)에는 ObjectInputStream을 사용하고

역직렬화(스트림으로부터 객체를 입력)에는 ObjectOutputStream을 사용한다

각각 InputStream/OutputStream을 상속받지만 기반스트림을 필요로하는 보조스트림이다

 

객체 생성시 입출력 스트림 지정

ObjectInputStream(InputStream in)

ObjectOutputStream(OutputStream out)

 

파일에 객체를 저장(직렬화)

FileOutputStream fos = new FileOutputStream(“objectfile.ser”);

ObjectOutputStream out = new ObjectOutputStream(fos);

out.writeObject(new UserInfo());

->위 코드는 objectfile.ser이라는 파일에 UserInfo객체를 직렬화하여 저장한다

->역직렬화는 입력스트림을 사용하고 writeObject() 대신 readObject()를 사용한다

//readObject()의 반환타입이 Object이기 때문에 객체 원래의 타입으로 형변환 해야한다

 

defaultReadObject() defaultWriteObject() : 자동 직렬화 수행

 

직렬화가 가능한 클래스 Serializable, transient

직렬화하고자 하는 클래스가 java.io.Serializable 인터페이스를 구현하도록 하면 된다

 

public class UserInfo implements java.io.Serializable {
String name;
String password;
int age;
}

 

Serializable는 빈 인터페이스지만 직렬화를 고려하여 작성한 클래스인지 판단하는 기준이 된다

public interface Serializable { }

조상클래스가 Serializable을 구현하면 자손도 직렬화가 가능하다

->구현하지 않을시 조상클래스에 정의된 인스턴스 변수가 직렬화 대상에서 제외된다

->인스턴스 변수의 타입이 아닌 실제로 연결된 객체의 종류에 의해 결정된다

 

transient

제어자 transient를 붙여서 직렬화 대상에서 제외되도록 할 수 있으며

password와 같이 보안상 직렬화되면 안 되는 값에 대해 transient를 사용할 수 있다

 

ArrayList와 같은 객체를 직렬화하면 ArrayList에 저장된 모든 객체들과 각 객체의 인스턴스 변수가 참조하고 있는 객체들까지 모두 직렬화된다

->직렬화 할 객체가 많을때는 각 객체를 개별적으로 직렬화하는 것보다 ArrayList와 같은 컬렉션에 저장해서 직렬화하는 것이 좋다

*보통은 확장자를 직렬화의 약자인 ser로 한다

 

 

직렬화가 가능한 클래스의 버전관리

직렬화된 객체를 역직렬화 할 때는 직렬화 했을 때와 같은 클래스를 사용해야한다

-> 클래스의 내용이 변경된 경우 역직렬화에 실패하며 예외가 발생한다

java.io.InvalidClassException : local class incompatible //클래스의 버전이 다른경우

 

static상수나 transient가 붙은 인스턴스변수가 추가되는 경우에는 직렬화에 영향을 미치지 않기 때문에 클래스의 버전을 다르게 인식하도록 할 필요는 없다

 

네트웍으로 객체를 직렬화하여 전송하는 경우 클래스가 조금만 변경되어도 해당 클래스를 재배포하는 것은 프로그램을 관리하기 어렵게 만든다

->클래스를 수동으로 관리해야한다

 

class MyData implements java.io.Serializable {
int value1;
}

 

클래스 내에 serialVersionUID를 정의하면 클래스의 내용이 바뀌어도 자동생성된 값으로 변경되지 않는다

 

'백엔드 > Java의 정석' 카테고리의 다른 글

TIL 정리_33  (0) 2022.03.20
TIL 정리_31  (0) 2022.03.18
TIL 정리_30  (0) 2022.03.17
TIL 정리_29  (0) 2022.03.16
TIL 정리_28  (0) 2022.03.15