File, Files

황상익·2024년 11월 15일

Inflearn JAVA

목록 보기
60/61

File

파일이나 폴더를 생성, 삭제, 정보 확인 가능

package chap55.io.file;

import java.io.File;
import java.io.IOException;
import java.util.Date;

//예전에 쓰던 방식
public class OldFileMain {
    public static void main(String[] args) throws IOException {
        File file = new File("temp/example.txt");
        File directory = new File("temp/exampleDir");

        //1. Exists : 파일이나 디렉토리의 존재 여부 확인
        System.out.println("file = " + file.exists());

        //2. createNewFile : 새파일 생성
        boolean created = file.createNewFile();
        System.out.println("created = " + created);

        //3. mkdir() : 새 디렉토리를 생성
        boolean dirCreated = directory.mkdir();
        System.out.println("dirCreated = " + dirCreated);

        //4. delete : 파일이나 디렉토리를 삭제
//        boolean deleted = file.delete();
//        System.out.println("deleted = " + deleted);

        //5. isFile : 파일인지 확인
        System.out.println("file = " + file.isFile());

        //6. isDirectory : 디렉토리인지 확인
        System.out.println("directory.isDirectory() = " + directory.isDirectory());

        //7. getName() : 파일이나 디렉토리 이름을 변환
        System.out.println("file.getName() = " + file.getName());

        //8. length() : 파일의 크기를 바이트로 변환
        System.out.println("file.length() = " + file.length() + "bytes");

        //9. renameTo(File dest) : 파일의 이름을 변경하거나 이동
        File newFile = new File("temp/newExample.txt");
        boolean renamed = file.renameTo(newFile);
        System.out.println("renamed = " + renamed);

        //10. lastModified() : 마지막으로 수정된 시간을 반환
        long lastModified = newFile.lastModified();
        System.out.println("lastModified = " + new Date(lastModified));
    }
}

Files

File을 사용하던거에 비해 성능이 훨씬 개선
수많은 Util 기능 함유.

package chap55.io.file;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class NewFilesMain {
    public static void main(String[] args) throws IOException {

        Path file = Path.of("temp/example.txt");
        Path directory = Path.of("temp/exampleDir");

        // 1. exists(): 파일이나 디렉토리의 존재 여부를 확인
        System.out.println("file = " + Files.exists(file));

        // 2. createFile(): 새 파일을 생성
        try {
            Files.createFile(file);
            System.out.println("File created");
        } catch (FileAlreadyExistsException e) {
            System.out.println(file + "File already exists");
        }

        // 3. createDirectory(): 새 디렉토리를 생성
        try {
            Files.createDirectory(directory);
            System.out.println("Directory created");
        } catch (FileAlreadyExistsException e) {
            System.out.println(directory + "Directory already exists");
        }

        // 4. delete(): 파일이나 디렉토리를 삭제
//        Files.delete(file);
//        System.out.println("File deleted");

        // 5. isReqularFile() : 일반파일인지 확인
        System.out.println("file = " + Files.isRegularFile(file));

        // 6. isDirectory() : 디렉토리인지 확인
        System.out.println("Files.isDirectory(directory) = " + Files.isDirectory(directory));

        //7. getFilesName() : 파일이나 디렉토리의 이름 확인
        System.out.println("file = " + file.getFileName());

        //8. size() : 파일의 크기를 바이트 단위로 변환
        System.out.println("Files.size(file)  = " + Files.size(file) + "bytes");

        // 9. move(): 파일의 이름을 변경하거나 이동
        Path newFile = Paths.get("temp/newExample.txt");
        Files.move(file, newFile, StandardCopyOption.REPLACE_EXISTING);
        System.out.println("File moved/renamed");

        // 10. getLastModifiedTime(): 마지막으로 수정된 시간을 반환
        System.out.println("Last modified: " + Files.getLastModifiedTime(newFile));

        // 추가: readAttributes(): 파일의 기본 속성들을 한 번에 읽기
        BasicFileAttributes attrs = Files.readAttributes(newFile, BasicFileAttributes.class);
        System.out.println("==Attributes==");
        System.out.println("Creation time : " + attrs.creationTime());
        System.out.println("Is directory : " + attrs.isDirectory());
        System.out.println("Is regular file : " + attrs.isRegularFile());
        // 파일 시스템 다루다 보면 symbolic link라는 것이 있음
        System.out.println("Is symbolic link : " + attrs.isSymbolicLink());
        System.out.println("Size : " + attrs.size());
    }
}

경로 표시

package chap55.io.file;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class OldFilePath {
    public static void main(String[] args) throws IOException {
        File file = new File("temp/..");
        System.out.println("path = " + file.getPath());
        //절대 경로
        //처음 부터 내가 입력한 모든 경로
        System.out.println("Absolute path = " + file.getAbsolutePath());

        //정규 경로
        //경로의 계산이 모두 끝난 경로 (하나만 가능)
        System.out.println("Canonical path = " + file.getCanonicalPath());

        File[] files = file.listFiles();
        for (File f : files) {
            System.out.println((f.isFile() ? "F" : "D") + " | " + f.getName());
        }
    }
}
  • 절대 경로 : 처음부터 입력한 모든 경로 표기
  • 상대 경로 : 경로의 계싼이 모두 끝난 경로, 정규 경로는 하나만 존재

Files 경로 표시

package chap55.io.file;


import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Stream;

public class NewFilesPath {
    public static void main(String[] args) throws IOException {
        Path path = Path.of("temp/.."); // /.. 상위 결로 부터 ~ ....
        System.out.println("path = " + path);
        System.out.println("Absolute Path = " + path.toAbsolutePath()); // 절대 경로
        System.out.println("Canonical path = " + path.toRealPath()); // 상대 경로

        Stream<Path> pathStream = Files.list(path);
        List<Path> list = pathStream.toList();
        pathStream.close();;

        for (Path p : list) {
            System.out.println((Files.isRegularFile(p) ? "F" : "D") + " | " + p.getFileName());
        }
    }
}

Files로 문자 파일 읽기

FileReader, FileWriter 같은 복잡한 스트림 클래스 사용, 모든 문자를 읽으려면 반복문을 사용해서 파일의 끝까지 읽어야 하는 과정 추가. => Files는 이런 문제를 코드 한줄로 깔끔하게 정리

package chap55.io.file;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

public class ReadTextFileV1 {

    private static final String PATH = "temp/hello2.txt";

    public static void main(String[] args) throws IOException {
        String writeString = "abc\n가나다";
        System.out.println("==Write String==");
        System.out.println(writeString);

        Path path = Path.of(PATH);
        Files.writeString(path, writeString, StandardCharsets.UTF_8);
        String readString = Files.readString(path, StandardCharsets.UTF_8);

        System.out.println("==Read String==");
        System.out.println(readString);
    }
}
  • Files.writeString : 파일 쓰기
  • Files.readString : 파일에서 모든 문자 읽기

Files - 라인 단위로 읽기

package chap55.io.file;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public class ReadTextFileV2 {

    private static final String PATH = "temp/hello2.txt";

    public static void main(String[] args) throws IOException {
        String writeString = "abc\n가나다";
        System.out.println("==Write String==");
        System.out.println(writeString);

        Path path = Path.of(PATH);

        //파일 쓰기
        Files.writeString(path, writeString, StandardCharsets.UTF_8);
        //파일 읽기

        //line 단위로 읽기
        System.out.println("==Read String==");

        //지금은 파일을 한번에 모아서 한줄 씩 처리
        //용량이 클 경우 outOfMemory 발생
        //lambda 처리 하면 한줄씩 메모리 구현 가능
        List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);

        //라인 단위로 출력을 하기 위함
        for (int i = 0; i < lines.size(); i++) {
            System.out.println((i + 1) + ": " + lines.get(i));
        }
    }
}
  • Files.readAllLines : 파일을 한번에 다 읽고, 라인 단위로 list에 나눠 저장
  • Files.lines(path) : 파일을 한줄 다위로 나눠 읽고, 메모리 사용량을 줄임.
    *) 추후에 람다 스트림을 알게 되면
try(Stream<String> lineStream = Files.lines(path, UTF_8)){
lineStream.forEach(line -> System.out.println(line));
}

사용이 가능

파일 복사 최적화

package chap55.io.file.copy;

import java.io.FileOutputStream;
import java.io.IOException;

public class CreateCopyFile {
    private static final int FILE_SIZE = 200 * 1024 * 1024; //200MB

    public static void main(String[] args) throws IOException {
        String fileName = "temp/copy.dat";
        long startTime = System.currentTimeMillis();

        //OutputStream을 사용하는데 byte룰 사용하는 것
        FileOutputStream fos = new FileOutputStream(fileName);
        byte[] buffer = new byte[FILE_SIZE];
        fos.write(buffer);
        fos.close();

        long endTime = System.currentTimeMillis();
        System.out.println("File created: " + fileName);
        System.out.println("File size: " + FILE_SIZE / 1024 / 1024 + "MB");
        System.out.println("Time taken: " + (endTime - startTime) + "ms");
    }
}
package chap55.io.file.copy;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

//복사
//File -> Java, Java -> File
public class FileCopyMainV1 {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream("temp/copy.dat");
        FileOutputStream fos = new FileOutputStream("temp/copy_new.dat");

        byte[] bytes = fis.readAllBytes();
        fos.write(bytes);
        fis.close();
        fos.close();

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken: " + (endTime - startTime) + "ms");
    }
}
  • FileInputStream : readAllBytes를 통해 한번에 모든 데이터를 읽고 write를 통해 한번에 모든 데이터 저장
  • 파일 -> 자바 -> 파일의 과정을 거침
  • copy.dat 파일의 데이터를 자바 프로세스가 사용하는 메모리에 불러오고 -> copy_new.dat에 전달한다.
package chap55.io.file.copy;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopyMainV2 {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream("temp/copy.dat");
        FileOutputStream fos = new FileOutputStream("temp/copy_new.dat");

        //inputStream -> outputStream
        fis.transferTo(fos);
        fis.close();
        fos.close();

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken: " + (endTime - startTime) + "ms");
    }
}
  • transferTo는 성능 최적화 앞의 예제와 비슷 좀더 빠름
    - 상황에 따라 좀더 느릴 수도 있음
    • 디스크는 실행 시간의 편차가 심함
  • 파일(copy.dat) 자바(byte) 파일(copy_new.dat)의 과정을 거진다.
package chap55.io.file.copy;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

//자바에 파일을 불러오는게 아니라 Os에 복사 기능을 사용
//자바를 파일에 불러오는 과정 생략
public class FileCopyMainV3 {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        Path source = Path.of("temp/copy.dat");
        Path target = Path.of("temp/copy_new.dat");
        Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken: " + (endTime - startTime) + "ms");
    }
}
  • Files.copy()
    자바에 파일을 불러오지 않고 운영체제의 파일 복사 기능 사용
    그래서 자바로 가져오는 과정이 사라짐
profile
개발자를 향해 가는 중입니다~! 항상 겸손

0개의 댓글