파일 입출력

9mond·2023년 7월 17일
0
post-thumbnail
post-custom-banner

1. java.io.file

  • File 클래스는 파일 또는 폴더에 대한 정보를 제공하는 클래스이다.
  • File 클래스의 객체는 정보를 조회하고자 하는 파일이나 폴더의 경로에 대한 문자열을 생성자 파라미터로 전달하는 형태로 만들 수 있다.
  • 이 때, 파라미터로 전달되는 경로가 실제로 존재하지 않더라도 File객체의 생성이 가능하다.

2. File 객체의 생성 예시

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

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

3. 경로 설정하기

  • 운영체제간의 호환성 유지를 위한 /의 사용
    -> 경로 문자열을 설정할 때 윈도우 기반에서는
    역 슬래시(\)를 사용하지만, 이 경우 이스케이프
    문자를 사용하여 \\의 형식으로 사용해야 하고,
    운영체제 호환성을 위해서 가급적 슬래시(/)를 사용하는 것이 좋다.

  • 절대 경로
    -> 작업 디렉토리(파일시스템의 관점에서 파일들을 묶어두는 개념. 폴더와 유사)와 관계없이 절대적인 위치를 의미하는 경로
    -> 윈도우 : C:/Windows/System32/drivers/etc
    시작 지점부터 찾아가는
    -> 리눅스 : /etc/httpd/conf/httpd.conf
    슬래시로 먼저 시작. 처음 "/"를 최상위

  • 상대 경로
    -> 작업 디렉토리를 기준으로 상대적인 위치를 의미하는 경로
    내가 현재 어느 위치에 있는가에 따라 달라짐
    -> 윈도우 : ../drivers/etc/hosts ex) mde ../는 앞의 폴더를 나가는 의미
    ./drivers/etc/hosts ex) System32 ./내 위치
    -> 리눅스 : ./conf/httpd.conf 리눅스도 ./내 위치를 표현

  • 예시)
import java.io.File;

public class Main01 {

	public static void main(String[] args) {
		// 절대경로나 상대경로를 생성자 파라미터로 전달한다.
		// 이클립스에서 상대경로를 사용할 경우, 현재 프로젝트가 기준이 된다.
		File file = new File("src/file/Main01.java");

		// 전달된 경로가 파일인지를 검사
		// -> 존재하지 않은 파일로 검사할 경우 무조건 false
		boolean is_faile = file.isFile();
		System.out.println("isFile : " + is_faile);

		// 전달된 경로가 디렉토리인지 검사
		// -> 존재하지 않은 디렉토리로 검사할 경우 무조건 false
		boolean is_dir = file.isDirectory();
		System.out.println("isDirectory : " + is_dir);

		// 전달된 경로가 숨긴 형태인지 검사
		// -> 애초에 존재하지 않은 파일로 검사할 경우 무조건 false
		boolean is_hidden = file.isHidden();
		System.out.println("isHidden : " + is_hidden);

		// 절대경로 값을 추출
		String abs = file.getAbsolutePath();
		System.out.println("절대경로 : " + abs);

		// 생성자에 전달된 파일이나 디렉토리가 물리적으로 존재하는지를 검사
		boolean is_exist = file.exists();
		System.out.println("존재여부 : " + is_exist);
		System.out.println("----------------------");

		// 디렉토리 정보 객체 생성
		File file2 = new File("a/b/c/target");
		System.out.println("isFile : " + file2.isFile());
		System.out.println("isDirectory : " + file2.isDirectory());
		System.out.println("isHidden : + " + file2.isHidden());
		System.out.println("절대경로 : " + file2.getAbsolutePath());
		System.out.println("존재여부 : " + file2.exists());

		// 경로에 따른 디렉토리 생성
		file2.mkdirs();
		System.out.println("-----------------------");

		// 마지막 "/" 이후의 단어를 리턴
		System.out.println(file.getName());
		System.out.println(file2.getName());

		// 처음부터 마지막 "/" 직전까지 리턴
		System.out.println(file.getParent());
		System.out.println(file2.getParent());

	}
}

4. 문자 인코딩

  • Character encoding이란
  • 문자나 기호들의 집합을 컴퓨터에서 저장하거나 통신에 사용할 목적으로 부호화하는 방법
  • UTF-8 : 8비트 이진수로 표현하는 방법
  • 아스키 코드(ASCII) : 라틴 알파벳, 숫자, 특수 문자등을 정수와 그에 대응하는 7비트 이진수로 표현

5. 스트림이란

  • 입출력에서 stream이란 디바이스의 입출력 방식이 character 단위이든 block 단위이든 관계없이 1바이트연속적으로 전달되는 형태로, 추상화된 상태를 의미한다.
  • 입출력 장치는 개별적인 특성이 있으므로 읽고, 쓰는 단위가 각각 다르지만, 스트림은 이러한 일련의 과정을 추상화하여 모든 디바이스를 character 단위로만 사용하고 있다.
  • 즉, 입출력 디바이스의 특성을 무시하고 하나의 단일한 입출력 인터페이스로 다룰 수 있도록 하는 것이 stream이다.

6. 자바 스트림 관련 클래스

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

7. 파일 저장 과정

  • 저장을 위한 빈 파일 생성하기
    -> OutputStream의 객체를 생성한다.

  • 파일에 내용 쓰기
    -> 저장할 내용을 byte 배열로 변환한다.
    -> 변환된 배열을 OutputSteam의 write() 메서드에게 파라미터로 전달한다.

  • 파일 닫기
    -> OutputSteam 객체로 close() 메서드를 호출하여 스트림을 닫는다.

  • 유의사항
    -> OutputSteam은 각각의 단계마다 예외처리를 강제적으로 요구한다.
    -> try~catch 블록이 형성되는 과정에서 변수의 유효성 범위에 대한 처리에 유의해야 한다.

  • 예시)
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"; // 정상적인 경로
//		final String PATH = "F:/gb_khs_0630/java/workspace/dAY11/src/file/test.txt";

		// 파일에 저장할 내용
		String write_string = "가나다라마바사abcdefg이 내용 저장";
		// 객체나 배열이 선언과 할당에 대한 블록이 서로 분리되어 있을 경우
		// 명시적으로 빈 영역임을 살리기 위하여 null로 초기화
		byte[] buffer = null; // 여기에 선언
		OutputStream out = null; // 선언 부분은 위에 정리

		// 특정 인코딩 방식 적용
		try {
			buffer = write_string.getBytes("utf-8"); // 밑에 try 구문에 넣고 catch구문 하나만 넣을 수도 있음
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		// 파일 저장 절차 시작
		try {
			out = new FileOutputStream(PATH);
			// 파일쓰기
			out.write(buffer); // buffer 변수의 유효성 범위가 서로 달라 인식하지 못한다.
								// buffer가 지역변수기 때문에 상단에 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 {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

8. 파일 읽기 과정

  • 파일을 읽기 위한 InputStream 객체 생성하기

  • 읽은 내용을 담기 위한 빈 byte 배열 생성하기
    -> 파일의 용량 크기 만큼 배열의 사이즈를 지정해야 한다.

  • 파일의 내용 읽기
    -> 읽은 내용을 담기 위한 byte 배열InputStream 객체read()메서드에게 파라미터로 전달한다.

  • 사용이 완료된 스트림 닫기
    -> InputStream 객체의 close() 메서드를 호출하여 스트림을 닫는다.

  • 읽은 내용을 문자열로 변환하기
    -> byte 배열String 클래스의 생성자에게 전달하여 문자열로 변환하기
    -> 이 과정에서 어떤 인코딩을 사용할지 함께 설정해야 한다.

  • 파일 읽고 쓰는 전체적인 절차의 예시)
package file;

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;
import java.security.PublicKey;

public class FileHelper {
	// 싱글톤
	private static FileHelper current;

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

	private FileHelper() {

		// 주어진 경로에 data값을 기록하고 저장한다.
		/*
		 * param filePath : 저장할 파일 경로 
		 * param data : 저장할 내용을 담을 스트림 
		 * return boolean : 성공시 true, 실패시 false
		 */
	}
	public boolean write(String filePath, byte[] data) {
		boolean result = false;
		OutputStream out = null;

		// 파일 저장 절차 시작
		try {
			out = new FileOutputStream(filePath);
			// 파일쓰기
			out.write(data); // buffer 변수의 유효성 범위가 서로 달라 인식하지 못한다.
								// buffer가 지역변수기 때문에 상단에 buffer 선언해놔야 함.
			System.out.println("[INFO]파일 저장 성공 >> " + filePath);
			result = true; // 저장에 성공했으므로, 결과값을 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 {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	// 주어진 경로에 파일을 읽고, 내용을 스트림으로 리턴
	/*
	 * param filePath : 읽어야할 파일의 경로 
	 * param byte[] :읽혀질 내용 
	 * return boolean : 성공시 true,실패시 false
	 */
	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) {
			e.printStackTrace();
			System.out.println("[ERROR] 지정된 경로를 찾을 수 없음 >> " + filePath);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 파일 읽기 실패 >> " + filePath);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		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[] buffer = null;

		try {
			buffer = content.getBytes(encType); // 밑에 try 구문에 넣고 catch구문 하나만 넣을 수도 있음
		} catch (UnsupportedEncodingException e) {
			System.out.println("[ERROR] 인코딩 지정 에러");
			e.printStackTrace();
		} catch (Exception e) {
			System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
			e.printStackTrace();
		}

		result = this.write(filePath, buffer);
		return result;
	}

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

		byte[] data = this.read(filePath); // this는 필수는 아님. 강조하기 위해

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

		return content;
	}

}
profile
개발자
post-custom-banner

0개의 댓글