티스토리 뷰
Author: 니용
FileOutputStream만 사용하다가 Files가 있다는 것을 알게 되었습니다. 자바 1.7버전부터 지원을 하고 있었습니다.
위 클래스가 있는 패키지는 NIO(New Input/Output)라고 하여 새로운 입출력을 의미합니다. 기존의 IO 클래스에서의 일관성을 바로 잡고 비동기 채널과 네트워크 지원등을 강화한 API라고 합니다.
방식 | IO | NIO |
I/O | Stream | Channel |
Buffer | Non-buffer | Buffer |
Asynchornous | Sync | Async |
Blocking / Non-blocking | Blocking | Both |
기존의 Stream에서는 입출력이 Input/Ouput으로 나누어져 있어 따로 생성해야 했습니다. 이를 개선한 것이 채널이고, 양방향성을 가지고 있어 입출력이 동시에 가능합니다.
버퍼를 사용하면 채널간 통신을 하는 것과 같아 성능이 좋아집니다. 버퍼를 사용하지 않았을 때는 데이터의 위치를 이동할 수 없어 불편한 점이 개선되었습니다.
블로킹은 데이터가 읽고 쓰이는 동안 쓰레드(Thread)가 대기 상태가 됩니다. 그래서 FileInputStream이나 FileOutputStream을 쓰면 항상 .close()를 호출해주어 스트림을 닫았어야 했습니다. 넌블로킹은 쓰레드가 인터럽트가 가능해서 작업 도중 빠져나올 수 있게 해줍니다. 핵심 객체는 멀티플렉서라고 하는 선택자(Selector)이며 이는 복수 개 채널 중 준비 완료된 채널을 선택하도록 지원해줍니다. 멀티플렉서는 대개 영상 편집에서 많이 사용됩니다.
이제 Files를 사용하기 위한 준비물을 알아보겠습니다.
Path
가장 먼저 경로를 지정해야 합니다. java.nio.file.Path에 있는 인터페이스로 구현 객체를 얻기 위해 get() 메소드로 호출 가능합니다.
파일의 경로는 절대 경로와 상대 경로 모두를 사용할 수 있고, 아래 메소드 외에도 제공하는 메소드가 많습니다.
import org.apache.commons.lang3.exception.ExceptionUtils;
import javax.validation.constraints.NotNull;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileUtil {
public static void write(@NotNull String filePath) {
String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
try {
Path path = Paths.get(filePath + ".txt");
String fileName = path.getFileName(); // 파일명 리턴
String parentFileName = path.getParent().getFileName(); // 부모 객체의 이름
}
catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
}
}
FileSystem
파일 시스템 정보를 읽어올 수 있는 인터페이스입니다. 구현 객체는 getDefault()로 호출 가능합니다.
아래 메소드 외에도 많은 것들이 있어 필요에 따라 사용가능합니다.
import javax.validation.constraints.NotNull;
import java.nio.file.*;
import java.text.SimpleDateFormat;
public class FileUtil {
public static void fileSystem(@NotNull String filePath, @NotNull PointLog pointLog) {
try {
FileSystem fileSystem = FileSystems.getDefault();
Iterable<FileStore> fileStores = fileSystem.getFileStores(); // 드라이버 정보
Iterable<Path> rootDirectories = fileSystem.getRootDirectories(); // 루트 디렉터리 정보
String separator = fileSystem.getSeparator(); // 디렉토리 구분자
}
catch (Exception e) {
}
}
}
InputStream / OutputStream
위에 Path를 알고 있으면 바로 파일 입출력이 가능합니다.
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import javax.validation.constraints.NotNull;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
public class FileUtil {
public static void writeToFile(@NotNull String filePath, @NotNull Map<String, Object> param) {
String fileName = new SimpleDateFormat("yyyyMMdd").format(new Date()) + ".txt";
try {
StringBuilder sb = new StringBuilder();
for(Map.Entry<String, Object> row : param.entrySet()) {
sb.append("key:").append(row.getKey()).append("/val:").append(row.getValue()).append("\n");
}
Path path = Paths.get(filePath + fileName);
// StandardOpenOption
Files.newOutputStream(path, StandardOpenOption.CREATE, StandardOpenOption.APPEND)
.write(sb.toString().getBytes());
}
catch (Exception e) {
log.error(ExceptionUtils.getStackTrace(e));
}
}
}
여기에서는 파일이 없으면 생성하고 생성된 파일안에서 뒤에 계속 붙여쓰는 것을 구현해보았습니다.
옵션에 대한 설명입니다.
StandardOpenOption
파일에 읽고 쓰기 위한 옵션을 정해줄 수 있습니다. Enum Class로 지정되어 있고 순서 상관없이 Path 입력 후 사용하면 됩니다.
Enum Name | 용도 | Example |
APPEND | 파일 쓰기에서 맨 뒤에 붙임 | StandardOpenOption.APPEND |
CREATE | 파일이 없으면 생성 | StandardOpenOption.CREATE |
CREATE_NEW | 이미 파일이 존재해도 생성 | StandardOpenOption.CREATE_NEW |
DELETE_ON_CLOSE | Files 사용하다가 close() 호출되면 파일 삭제 | StandardOpenOption.DELETE_ON_CLOSE |
READ | 읽기 권한을 얻음 | StandardOpenOption.READ |
WRITE | 쓰기 권한을 얻음 | StandardOpenOption.WRITE |
'Server' 카테고리의 다른 글
[Spring] RestTemplate 알아보기 (0) | 2020.07.14 |
---|---|
[Spring] Spring Framework 5와 WebFlux (0) | 2020.07.06 |
Kotlin의 상속성과 다형성 (0) | 2020.07.03 |
Kotlin의 Pair와 Triple (0) | 2020.07.02 |
Kotlin의 Type과 Nullable (3) (0) | 2020.07.01 |
[Kotlin] MongoDB JPA 사용하기 (2) | 2020.06.30 |