파일 입출력

전영덕·2023년 2월 6일
0

Java Study

목록 보기
36/36

1. 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")

2. 운영체제 간의 호환성 유지를 위한 "\"의 사용(역슬래시)

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

3. 절대경로

  • 내가 어떤 특정 파일을 찾을 때 경로를 C드라이브부터 모두 나열해서 찾기
  • 작업 디렉터리와 관계없이 절대적인 위치를 의미하는 경로
  • 윈도우 예시 : C:\Window/System32/drivers/etc/hosts
  • 리눅스 예시 : /etc/httpd/conf/http.conf

4. 상대경로

  • 작업 디렉터리를 기준으로 상대적인 위치를 의미하는 경로
  • 윈도우 예시 : ./conf/httpd.conf
  • 리눅스 예시 : ../drivers/etc/hosts

5. 문자 인코딩(charater encoding)

  • 문자나 기호들의 집합을 컴퓨터에서 저장하거나 통신에 사용할 목적으로 부호화 하는 방법
  • UTF-8 : 8비트 이진수로 표현하는 방법

6. 스트림이란?

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

7. 자바의 스트림 관련 클래스

  • 스트림 관련 클래스들은 각각 InputStream(입력/읽기), OutputStream(출력/저장)과 관련된 인터페이스를 상속받기 때문에 모두 동일한 메서드를 가지고 있다.
package file;

import java.io.File;

public class Main01 {

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

		// 파일클래스에 저장된 몇가지 기능
		// 전달된 경로가 파일인지 검사 -> 존재하지 않는 파일로 검사할 경우 무조건 false
		boolean is_file = f1.isFile();
		System.out.println("is_file = " + is_file);

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

		// 전달된 경로가 숨김 형태 인지 검사 -> 존재하지 않는 파일로 검사할 경우 무조건 false
		boolean is_hidden = f1.isHidden();
		System.out.println("is_hidden = " + 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("is_file : " + f2.isFile());
		System.out.println("is_Directory : " + f2.isDirectory());
		System.out.println("is_Hidden : " + f2.isHidden());
		System.out.println("절대 경로 : " + f2.getAbsolutePath());
		System.out.println("존재 여부 : " + f2.exists());

		// 경로에 따른 디렉토리 생성
		f2.mkdirs();
		System.out.println("------------------------------------------");
		System.out.println("is_file : " + f2.isFile());
		System.out.println("is_Directory : " + f2.isDirectory());
		System.out.println("is_Hidden : " + f2.isHidden());
		System.out.println("절대 경로 : " + f2.getAbsolutePath());
		System.out.println("존재 여부 : " + f2.exists());

		System.out.println("------------------------------------------");
		// 마지막 "/"이후 단어를 리턴
		System.out.println(f1.getName());
		System.out.println(f2.getName());

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

	}

}
  • 파일을 컴퓨터가 읽도록 인코딩하고 저장하기
package file;

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 = "자바수업 마지막";

		// 문자열을 파일로 저장하기 위해서는 byte배열로 변환해야한다.
		// 문자열로 파일을 변환하기 위해서 getBytes()메서드를 사용하는데,
		// 이 때 변환과정에서 사용될 인코딩 형식을 지정해주어야한다.

		byte[] buffer = null;
		// getBytes()메서드는 존재하지 않는 인코딩 형식에 대한 지정을 방지하기 위하여
        //예외처리를 강제적으로 요구한다.
		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);

			// try- catch구문으로 감싸느라 try에있는 buffer것은 변수의 유효범위가 다르게됨
			// buffer를 인식하지 못함. 그러니까 변수 선언 범위를 위쪽으로 빼내기(23 번줄로이동).

		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 지정된 경로를 " + "찾을 수 없음>>>" + PATH);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 파일 저장 실패 >> " + PATH);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("[ERROR] 알 수 없는 에러 >> " + PATH);
		}

		finally {
			try {
				out.close(); 
                // out.close(); 만하게되면 위와 마찬가지로 변수의 유효범위가 달라서 변수가 없는걸로 보임.
				// 이럴 때는 변수를 트라이 캐치 바깥으로 올림.
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
        
	}
}
  • 저장된 파일을 불러와서 읽고 출력하기
package file;

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

public class Main03 {
	public static void main(String[] args) {
		// 읽을 파일 경로
		final String PATH = "./test.txt";

		// 읽은 내용이 담겨질 스트림
		byte[] data = null;

		// 읽은 내용이 변환될 문자열
		String read_string = null;

		// 파일 읽기
		InputStream in = null;
		try {
			in = new FileInputStream(PATH);

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

			// 파일 읽기 - 파라미터로 전달된 배열 안에,
			// 파일의 내용을 담아준다.
			in.read(data);
			System.out.println("[INFO] 파일 읽기 성공 >>" + PATH);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 지정된 경로를 " + "찾을수 없습니다. >>" + PATH);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 파일 읽기 실패 >>" + PATH);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("[ERROR] 알 수 없는에러 >>" + PATH);
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// data배열에 내용이 있다면, 문자열로 변환하여 출력
		if (data != null) {
			try {
				// 문자열로 변환시에는 저장된 인코딩으로 지정
				read_string = new String(data, "utf-8");
				System.out.println(read_string);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				System.out.println("[ERROR] 인코딩 지정 에러");
			}
		}
	}
}
  • 통합형 예제
package file;

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

public class Main03 {

	public static void main(String[] args) {
		// 읽을 파일 경로
		final String PATH = "./test.txt";

		// 읽은 내용이 담겨질 스트림
		byte[] data = null;

		// 읽은 내용이 변환될 문자열
		String read_string = null;

		// 파일 읽기
		InputStream in = null;
		try {
			in = new FileInputStream(PATH);

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

			// 파일 읽기 - 파라미터로 전달된 배열 안에,
			// 파일의 내용을 담아준다.
			in.read(data);
			System.out.println("[INFO] 파일 읽기 성공 >>" + PATH);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 지정된 경로를 " + "찾을수 없습니다. >>" + PATH);
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("[ERROR] 파일 읽기 실패 >>" + PATH);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("[ERROR] 알 수 없는에러 >>" + PATH);
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// data배열에 내용이 있다면, 문자열로 변환하여 출력
		if (data != null) {
			try {
				// 문자열로 변환시에는 저장된 인코딩으로 지정
				read_string = new String(data, "utf-8");
				System.out.println(read_string);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				System.out.println("[ERROR] 인코딩 지정 에러");
			}
		}
	}
}

```java
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;

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

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

    public static void freeInstance() {
        current = null;
    }

    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 {
        	/*
        	 * 1.소프트웨어 아키텍처 세부 구현 지침과 UI 표준 및 지침을 반영하여ㆍ확인된 UI 설계를 구현할 수 있다.(10)
        	 */
        	out = new FileOutputStream(filePath);
            // 파일쓰기
            out.write(data);
            System.out.println("[INFO] 파일 저장 성공 >> " + filePath);
            // 저장에 성공하였으므로, 결과값을 true로 변경
            result = true;
        /*
         * 2.확인된 화면과 폼 흐름 설계에 따라ㆍ사용자 접근성을 고려한 화면과 폼의 흐름 제어를 구현할 수 있다.(5)
         */
        } catch (FileNotFoundException e) {
            System.out.println("[ERROR] 지정된 경로를 찾을 수 없음. >> " + filePath);
            e.printStackTrace();
        /*
         * 3.확인된 화면과 폼 흐름 설계에 따라ㆍ사용자 접근성을 고려한 화면과 폼의 흐름 제어를 구현할 수 있다.(5)
         */
        } catch (IOException e) {
            System.out.println("[ERROR] 파일 저장 실패 >> " + filePath);
            e.printStackTrace();
        /*
         * 4.확인된 화면과 폼 흐름 설계에 따라ㆍ사용자 접근성을 고려한 화면과 폼의 흐름 제어를 구현할 수 있다.(5)
         */
        } 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 {
        	/*
        	 * 5.구현된 화면ㆍ폼ㆍ메뉴ㆍ흐름을 테스트할 수 있는 테스트 케이스를 작성하고 단위 테스트를 수행하기 위한 테스트 조건을 명세화할 수 있다.(10)
        	 */
            in = new FileInputStream(filePath);

            // 읽은 내용을 담기 위한 배열은 파일의 용량만큼 사이즈를 할당한다.
            // in.available() --> 열고 있는 파일의 크기
            /*
             * 6.확인된 화면과 폼 흐름 설계에 따라ㆍ감성공학 기법을 고려하여 사용자가 접하는 화면ㆍ폼ㆍ메뉴ㆍ흐름을 구현할 수 있다.(10)
             */
            data = new byte[in.available()];
            // 파일 읽기 - 파라미터로 전달된 배열 안에, 파일의 내용을 담아준다.
            in.read(data);
            System.out.println("[INFO] 파일 읽기 성공 >> " + filePath);
	    /*
	     * 7.확인된 화면과 폼 흐름 설계에 따라ㆍ감성공학 기법을 고려하여 사용자가 접하는 화면ㆍ폼ㆍ메뉴ㆍ흐름을 구현할 수 있다.(5)
	     */
        } catch (FileNotFoundException e) {
            System.out.println("[ERROR] 지정된 경로를 찾을 수 없음. >> " + filePath);
            e.printStackTrace();
        /*
	     * 8.확인된 화면과 폼 흐름 설계에 따라ㆍ감성공학 기법을 고려하여 사용자가 접하는 화면ㆍ폼ㆍ메뉴ㆍ흐름을 구현할 수 있다.(5)
	     */
        } catch (IOException e) {
            System.out.println("[ERROR] 파일 읽기 실패 >> " + filePath);
            e.printStackTrace();
        /*
	     * 9.확인된 화면과 폼 흐름 설계에 따라ㆍ감성공학 기법을 고려하여 사용자가 접하는 화면ㆍ폼ㆍ메뉴ㆍ흐름을 구현할 수 있다.(5)
	     */
        } catch (Exception e) {
            System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
            e.printStackTrace();
        } 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 {
        	/*
    	     * 10.설계된 화면과 폼의 흐름을 확인하고ㆍ제약사항과 화면의 폼 흐름을 구현에 반영하도록 설계를 확인할 수 있다.(10)
    	     */
            data = content.getBytes(encType);
        /*
	     * 11.설계된 화면과 폼의 흐름을 확인하고ㆍ제약사항과 화면의 폼 흐름을 구현에 반영하도록 설계를 확인할 수 있다.(5)
	     */
        } catch (UnsupportedEncodingException e) {
            System.out.println("[ERROR] 인코딩 지정 에러");
            e.printStackTrace();
	    /*
	     * 12.설계된 화면과 폼의 흐름을 확인하고ㆍ제약사항과 화면의 폼 흐름을 구현에 반영하도록 설계를 확인할 수 있다.(5)
	     */
        } 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 {
        	/*
        	 * 13.구현을 위해 하위 시스템 단위의 내·외부 화면과 폼을 설계를 확인할 수 있다.(10)
        	 */
            content = new String(data, encType);
            content = content.trim();
        /*
    	 * 14.구현을 위해 하위 시스템 단위의 내·외부 화면과 폼을 설계를 확인할 수 있다.(5)
    	 */
        } catch (UnsupportedEncodingException e) {
            System.out.println("[ERROR] 인코딩 지정 에러");
            e.printStackTrace();
        /*
    	 * 15.구현을 위해 하위 시스템 단위의 내·외부 화면과 폼을 설계를 확인할 수 있다.(5)
    	 */
        } catch (Exception e) {
            System.out.println("[ERROR] 알 수 없는 에러 >> " + filePath);
            e.printStackTrace();
        }

        return content;
    }
}

0개의 댓글