⬛ File, Path
file은 옛날에 쓰던 방식이다. (레거시코드볼때..just참고)
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 exists: " + file.exists());
// 2. createNewFile(): 새 파일을 생성
boolean created = file.createNewFile();
System.out.println("File created = " + created);
// 3. mkdir(): 새 디렉토리를 생성
boolean dirCreated = directory.mkdir();
System.out.println("Directory created: " + dirCreated);
// 4. delete(): 파일이나 디렉토리를 삭제
//boolean deleted = file.delete();
//System.out.println("File deleted: " + deleted);
// 5. isFile(): 파일인지 확인
System.out.println("Is file: " + file.isFile());
// 6. isDirectory(): 디렉토리인지 확인
System.out.println("Is directory: " + directory.isDirectory());
// 7. getName(): 파일이나 디렉토리의 이름을 반환
System.out.println("File name: " + file.getName());
// 8. length(): 파일의 크기를 바이트 단위로 반환
System.out.println("File size: " + file.length() + " bytes");
// 9. renameTo(File dest): 파일의 이름을 변경하거나 이동
File newFile = new File("temp/newExample.txt");
boolean renamed = file.renameTo(newFile);
System.out.println("File renamed: " + renamed);
// 10. lastModified(): 마지막으로 수정된 시간을 반환
long lastModified = newFile.lastModified();
System.out.println("Last modified: " + new Date(lastModified));
}
}
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());
}
}
}
path = temp/..
Absolute path = /Users/yh/study/inflearn/java/java-adv2/temp/..
Canonical path = /Users/yh/study/inflearn/java/java-adv2
절대 경로는 구체적인 길을 모두 표시하고, 정규 경로는 계산된 최종 목적지만 표현한다. 절대 경로가 여러 개 있을 수 있지만, 계산된 정규 경로는 하나로 고정된다.
⬛ Files
오늘날(자바1.7~) 파일관련은 Files를 쓴다. files는 성능과 편의성이 모두 개선되었다.
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 exists: " + 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. isRegularFile(): 일반 파일인지 확인
System.out.println("Is regular file: " + Files.isRegularFile(file));
// 6. isDirectory(): 디렉토리인지 확인
System.out.println("Is directory: " + Files.isDirectory(directory));
// 7. getFileName(): 파일이나 디렉토리의 이름을 반환
System.out.println("File name: " + file.getFileName());
// 8. size(): 파일의 크기를 바이트 단위로 반환
System.out.println("File size: " + 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());
System.out.println("Is symbolic link: " + attrs.isSymbolicLink());
System.out.println("Size: " + attrs.size());
}
}
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.writeString(): 파일 읽기
Files.readString(): 파일에서 모든 문자읽기
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, UTF_8);
// 파일에서 읽기
String readString = Files.readString(path, UTF_8);
System.out.println("== Read String ==");
System.out.println(readString);
}
}
Files.readAllLines(path): 전체 내용 한번에 읽기.라인 단위로 리스트에 저장한다.
public class ReadTextFileV2 {
public 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, UTF_8);
// 파일에서 읽기
System.out.println("== Read String ==");
List<String> lines = Files.readAllLines(path, UTF_8);
for (int i = 0; i < lines.size(); i++) {
System.out.println((i + 1) + ": " + lines.get(i));
}
/*
try(Stream<String> lineStream = Files.lines(path, UTF_8)){
lineStream.forEach(line -> System.out.println(line));
}
* */
}
}
파일을 한 줄 단위로 나누어 읽고, 메모리 사용량을 줄이고 싶다면 이 기능을 사용하면 된다.
try(Stream<String> lineStream = Files.lines(path, UTF_8)){
lineStream.forEach(line -> System.out.println(line));
}
⬛ 파일 복사 최적화
🟢 기본 복사 방식
FileInputStream과 FileOutputStream을 사용해 readAllBytes()로 파일을 읽고 write()로 저장할 수 있다.
이는 큰 파일을 복사할 때 메모리 사용량이 커서 비효율적일 수 있다.
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");
}
}
🟢 최적화된 복사 방식 transferTo()
자바 9부터 InputStream에 추가된 transferTo() 메서드를 사용해 입력 스트림의 데이터를 바로 출력 스트림으로 전달한다.
이 메서드는 성능최적화가 되어있기에, 메모리를 효율적으로 사용하여 복사 속도가 빠르다.
파일(copy.dat) -> 자바(byte) -> 파일(copy_new.dat)의 과정을 거친다.
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");
fis.transferTo(fos);
fis.close();
fos.close();
long endTime = System.currentTimeMillis();
System.out.println("Time taken: " + (endTime - startTime) + "ms");
}
}
🟢 최고의 복사 방식 - Files.copy()
Files.copy() 메서드를 사용하면 운영체제의 파일 복사 기능을 이용해 직접 복사한다.
파일을 메모리에 올리지 않고 바로 복사하므로 가장 빠르고 효율적이다. 대용량 파일을 복사할 때 최적의 방식이다.
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");
}
}
'Java' 카테고리의 다른 글
[Java] 김영한의 실전 자바 - 고급 2편 섹션6 네트워크,자원 정리 (0) | 2024.11.04 |
---|---|
[Java] 김영한의 실전 자바 - 고급 2편 섹션5 네트워크 기본이론 / HTTP (2) | 2024.10.31 |
[Java] 김영한의 실전 자바 - 고급 2편 섹션2 I/O 기본1,2 (0) | 2024.10.28 |
[Java] 김영한의 실전 자바 - 고급 1편 섹션12 스레드 풀과 Executor 프레임워크2 (1) | 2024.09.30 |
[Java] 김영한의 실전 자바 - 고급 1편 섹션12 스레드 풀과 Executor 프레임워크 (0) | 2024.09.29 |