File 클래스

haribo·2021년 2월 27일
0

Java

목록 보기
13/17

Java.io.File

  • File 클래스 : 파일 또는 폴더에 대한 정보를 제공하는 클래스
  • File 클래스 객체 : 정보를 조회하고자 하는 파일이나 폴더의 경로에 대한 문자열을 생성자 파라미터로 전달하는 형태로 만들 수 있다. 이 때, 파라미터로 전달되는 경로가 실제로 존재하지 않더라도 FIle 객체 생성이 가능하다. (메모장의 새 파일을 켜서 저장하지 않아도 그 파일은 존재했었던 것 처럼)
  • C:/photo/food.jpg 파일에 대한 객체 생성 예시
File file = new File("C:/photo/food.jpg);

File file = new File("C:/photo", "food.jpg");

경로

  • 운영체제간의 호환성 유지를 위해 '/' 슬래시를 사용한다. (윈도우 기반에서는 역슬래시를 사용하지만 이 경우 이스케이프 문자를 사용하여 \ 형식으로 사용해야하고, 가급적 다른 운영체제와 호환성을 위해 슬래시를 사용하는 것이 좋다. (리눅스와 유닉스에선 슬래시만 사용))
  • 절대경로 : 작업 디렉토리와 관계없이 절대적인 위치를 의미하는 경로이다. (최상단 루트로 시작한다.)
    • 리눅스 : /etc/httpd/conf/httpd.conf
    • 윈도우 : C:/Windows/System32/drivers/etc/hosts
  • 상대경로 : 작업 디렉토리를 기준으로 상대적인 위치를 의미하는 경로
    • 리눅스 : ./conf/httpd.conf
    • 윈도우 : ../drivers/etc/hosts
    • .. → 부모 . → 자신
  • 디렉토리 : 폴더개념. (윈도우에선 폴더라고 불러서. 스테이플러는 제품이름이고 호치키스는 상표명인데 상표로도 통용되는것처럼)

Java.io.File 클래스

  • 이클립스 사용시 작업 디렉토리는 현재 프로젝트의 폴더가 된다. (workspace - project)
  • ex : Workspace가 C:/java이고 프로젝트가 30-File인 경우의 작업위치는 C:/java/30-File.
import java.io.File;

public class Main01 {
	public static void main(String[] args) {
		// 절대경로나 상대경로를 생성자 파라미터로 전달한다.
		// 이클립스에서 상대경로를 사용할 경우, 현재 프로젝트가
		// 기준이 된다.
		File f1 = new File("src/Main01.java");
		
		// 전달된 경로가 파일인지 검사
		// --> 존재하지 않는 파일로 검사할 경우 무조건 false
		boolean is_file = f1.isFile();
		System.out.println("isFile=" + is_file);
		
		// 전달된 경로가 디렉토리인지 검사
		// --> 존재하지 않는 디렉토리로 검사할 경우 무조건 false
		boolean is_dir = f1.isDirectory();
		System.out.println("isDirectory=" + is_dir);
		
		// 전달된 경로가 숨김형태인지 검사
		// --> 존재하지 않는 파일로 검사할 경우 무조건 false
		boolean is_hidden = f1.isHidden();
		System.out.println("isHidden=" + is_hidden);
		
		// 절대경로 값을 추출
		String abs = f1.getAbsolutePath();
		System.out.println("절대경로: " + abs);
		
		// 생성자에 전달된 파일이나 디렉토리가 물리적으로 존재하는지를 검사
		boolean is_exist = f1.exists();
		System.out.println("존재여부: " + is_exist);
		
		System.out.println("-------------------------------");
		
		// 디렉토리 정보 객체 생성
		File f2 = new File("a/b/c/target");
		System.out.println("isFile: " + f2.isFile());
		System.out.println("isDirectory: " + f2.isDirectory());
		System.out.println("isHidden: " + f2.isHidden());
		System.out.println("절대경로: " + f2.getAbsolutePath());
		System.out.println("존재여부: " + f2.exists());
		
		// 경로에 따른 디렉토리 생성
		f2.mkdirs(); // make directory
		
		System.out.println("-------------------------------");
		

	}

}

InputStream과 OutputStream

문자 인코딩이란?

  • 문자나 기호들의 집합을 컴퓨터에서 저장하거나 통신에 사용할 목적으로 부호화 하는 방법.
    • 모스부호 : 전건을 길게, 또는 짧게 두드려서 라틴 알파벳 표현
    • 아스키(American Standard Code for Information Interchange) : 라틴 알파벳, 숫자, 특수 문자 등을 정수와 그에 대응되는 7비트 이진수로 표현
    • UTF-8 : 8비트 이진수로 표현하는 방법
  • 인코딩 : 부호화. 저장할때. 소리는 파동. 파동을 세밀하게 끊으면 음질이 좋아지고 용량이커짐. 자연에 존재하는 어떠한 현상을 기계화 시키는 법.
  • 디코딩 : 복호화. 불러올때.

<참고> - 메모장의 인코딩형식

스트림이란?

  • 입출력에서 스트림이란 디바이스의 입출력 방식이 Character 단위이든 block 단위이든 관계없이 1바이트씩 연속적으로 전달하는 형태로, 추상화된 상태를 의미한다. (디바이스 상관없이 보내려면 뚜렷한 형태보단 추상화가 필요하단걸로 이해하자)
  • 입출력 장치(하드웨어)는 개별적인 특성이 있으므로 읽고, 쓰는 단위가 각각 다르지만 스트림은 이러한 일련의 과정을 추상화하여 모든 디바이스를 Character단위로만 사용하도록 한다.
  • 즉, 입출력 디바이스의 특성을 무시하고 하나의 단일한 입출력 인터페이스로 다룰 수 있도록 하는 것이 stream
  • 파이프. 어떠한 입출력방식에서 디바이스 입출력방식 무시 (기존방식 : 가구점 용달트럭 → 스트림 : 이케아 택배단위 부품으로 보내기. 부품 하나라도 빠지면 가구가 완성될 수 없음. 유실되면안됨) 운영체제한테 부탁하는 자바의 방법 (언어마다 다 다름)

자바의 스트림 관련 클래스

  • 스트림 관련 클래스들은 각각 InputStream (입력/읽기), OutputStream(출력/저장)과 관련된 인터페이스를 상속받기 떄문에 모두 동일한 메서드를 가지고 있다.
  • 프로그래머는 상황에 따라 적절한 클래스를 사용하기만 하면 동일한 방법으로 스트림을 사용할 수 있다.
  • java.io패키지
    • OutputStream 인터페이스 (파일 쓰기 관련 기능)
      • FileOutputStream
      • ByteArrayOutputStream
    • InputStream 인터페이스 (파일 읽기 관련 기능)
      • FileInputStream
      • ByteArrayInputStream

파일 저장 과정

  • 저장을 위한 빈파일 생성하기 : OutputStream의 객체 생성
  • 파일에 내용 쓰기 : 저장할 내용을 byte 배열로 변환 후, 변환된 배열을 OutputStream의 write() 메서드에게 파라미터로 전달한다.
  • 파일 닫기 : OutputStream 객체로 close() 메서드를 호출하여 스트림을 닫는다.
  • 유의사항 : OutputStream은 끊길수있으니까 각각의 단계마다 예외처리를 강제적으로 요구함. try~catch 블록이 형성되는 과정에서 변수의 유효성 범위 (블록밖에 변수 지정)에 대한 처리에 유의해야함.

파일 읽기 과정

  • 파일을 읽기 위한 InputStream 객체 생성
  • 읽은 내용을 담기 위한 빈 byte 배열 생성 : 효율적인 메모리 관리를 위해 파일의 용량크기 만큼 배열사이즈 지정 (available 함수)
  • 파일의 내용 읽기 : byte 배열을 InputStream객체의 read()메서드에게 파라미터로 전달
  • 사용이 완료된 스트림 닫기 : InputStream 객체의 close() 메서드를 호출하여 스트림을 닫는다.
  • 읽은 내용을 문자열로 변환하기 : byte 배열을 String 클래스의 생성자에게 전달하여 문자열로 변환한다. 이 과정에서 어떤 인코딩을 사용할지를 함께 설정해야한다.

<실습>

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

public class Main02 {
	public static void main(String[] args) {
		// 저장할 파일의 경로
		final String PATH = "./test.txt";
		
		// 파일에 저장할 내용
		String write_string = "가나다라마바사nabcdefg";
		
		/** 특정 인코딩 방식 적용 */
		// 객체나 배열이 선언과 할당에 대한 블록이 서로 분리되어 있을 경우
		// 명시적으로 빈 영역임을 알리기 위하여 null로 초기화
		byte[] buffer = null;
		try {
			buffer = write_string.getBytes("utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		/** 파일 저장 절차 시작 */
		// finally 블록에서 인식하기 위해서 선언부를 위로 이동시킨다.
		OutputStream out = null;
		try {
			out = new FileOutputStream(PATH);
			// 파일쓰기
			out.write(buffer);
			System.out.println("[INFO] 파일 저장 성공 >> " + PATH);
		} catch (FileNotFoundException e) {
			System.out.println("[ERROR] 지정된 경로를 찾을 수 없음. >> " + PATH);
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("[ERROR] 파일 저장 실패 >> " + PATH);
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("[ERROR] 알 수 없는 에러 >> " + PATH);
			e.printStackTrace();
		} finally {
			
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

Helper

  • 거의 모든 프로그램들은 파일 저장 및 파일 불러오기 기능을 필요로 한다.
  • 프로그램 특성 요소는 저장하는 파일 형식과 읽어들이는 내용을 어떻게 활용하는가에 대한 측면이다.
  • 입출력 처리방법은 자바언어를 사용하는 대부분의 프로그램들이 앞서 소개한 내용과 동일하고, 그 기능들이 여러곳에서 사용되기 때문에 helper클래스 형태로 이 기능을 함축해 놓으면 필요한 시점에 코드를 재사용할 수 있게 된다.

→ 파일 입출력기능은 대부분의 프로그램들이 필요로 하고 여러곳에서 쓰이기 때문에 helper로 지정하여 필요한 시점에 코드를 재사용 하자.

package study.java.helper;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

public class FileHelper {
	// ------ 싱글톤 객체 생성 시작 ------
	private static FileHelper current;

	public static FileHelper getInstance() {
		if (current == null) {
			current = new FileHelper();
		}
		return current;
	}

	public static void freeInstance() {
		// 객체에 null을 대입하면 메모리에서 삭제된다.
		current = null;
	}

	// 기본 생성자를 private으로 은닉하게 되면 new를 통한 객체 생성이 금지된다.
	private FileHelper() {
		super();
	}
	// ------ 싱글톤 객체 생성 끝 ------

	/**
	 * 주어진 경로에 data 값을 기록하고 저장한다.
	 * 
	 * @param filePath - 저장할 파일 경로
	 * @param data     - 저장할 내용을 담은 스트림
	 * @return boolean - 성공시 true, 실패시 false
	 */
	public boolean write(String filePath, byte[] data) {
		boolean result = false;
		/** 파일 저장 절차 시작 */
		// finally 블록에서 인식하기 위해서 선언부를 위로 이동시킨다.
		OutputStream out = null;
		try {
			out = new FileOutputStream(filePath);
			// 파일쓰기
			out.write(data);
			System.out.println("[INFO] 파일 저장됨 >> " + filePath);
			// 저장에 성공하였으므로, 결과값을 true로 변경
			result = true;
		} catch (FileNotFoundException e) {
			System.out.println("[ERROR] 지정된 경로를 찾을 수 없음. >> " + filePath);
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("[ERROR] 파일 저장 실패 >> " + filePath);
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
			e.printStackTrace();
		} finally {

			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * 주어진 경로의 파일을 읽고, 내용을 스트림으로 리턴한다.
	 * 
	 * @param filePath - 읽어야 할 파일의 경로
	 * @return 읽혀진 내용
	 */
	public byte[] read(String filePath) {
		byte[] data = null;
		/** 파일 읽기 */
		InputStream in = null;
		try {
			in = new FileInputStream(filePath);

			// 읽은 내용을 담기 위한 배열은 파일의 용량만큼 사이즈를 할당한다.
			// in.available() --> 열고 있는 파일의 크기
			data = new byte[in.available()];

			// 파일 읽기 - 파라미터로 전달된 배열 안에, 파일의 내용을 담아준다.
			in.read(data);

			System.out.println("[INFO] 파일 읽기 성공 >> " + filePath);
		} catch (FileNotFoundException e) {
			System.out.println("[ERROR] 지정된 경로를 찾을 수 없음. >>" + filePath);
			e.printStackTrace();
		} catch (IOException e) {
			System.out.println("[ERROR] 파일 읽기 실패 >> " + filePath);
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} // end try~catch~finally

		return data;
	}

	/**
	 * 파일을 저장한다.
	 * 
	 * @param filePath - 저장할 파일 경로
	 * @param content  - 저장할 내용
	 * @param encType  - 인코딩 형식
	 * @return boolean - 성공시 true, 실패시 false
	 */
	public boolean writeString(String filePath, String content, String encType) {
		boolean result = false;
		byte[] data = null;
		
		try {
			data = content.getBytes(encType);
		} catch (UnsupportedEncodingException e) {
			System.out.println("[ERROR] 인코딩 지정 에러");
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
			e.printStackTrace();
		}
		
		result = this.write(filePath, data);
		return result;
	}

	
	/**
	 * 파일의 내용을 문자열로 리턴한다.
	 * 
	 * @param filePath - 읽어야 할 파일의 경로
	 * @param encType  - 인코딩 형식
	 * @return String - 읽은 내용에 대한 문자열
	 */
	public String readString(String filePath, String encType) {
		String content = null;

		byte[] data = this.read(filePath);

		// 내용을 문자열로 변환한다.

		try {
			content = new String(data, encType);
			content = content.trim();
		} catch (UnsupportedEncodingException e) {
			System.out.println("[ERROR] 인코딩 지정 에러");
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("[ERROR] 알 수 없는 에러 >> filePath");
			e.printStackTrace();
		}

		return content;
	}

}

import study.java.helper.FileHelper;

public class Main04 {

	public static void main(String[] args) {
		String encType = "UTF-8";
		String filePath = "myfile.txt";
		String content = "안녕하세요. 자바 프로그래밍";
		
		boolean result = FileHelper.getInstance().writeString(
				filePath, content, encType);
		System.out.println(result);
		if (!result) {
			System.out.println("파일 저장에 실패했습니다.");
			return;
		}
		
		String read = FileHelper.getInstance().readString(filePath, encType);
		System.out.println(read);

	}

}
이 포스트는 itpaper.co.kr에서 제공되는 강의자료를 바탕으로 작성되었습니다.
profile
그림 그리는 백엔드 개발자

0개의 댓글