java.nio
NIO New Input Ouput 의 약자
기존 java.io 패키지를 개선한 새로운 입출력 패키지
JDK 7부터는 파일 I/O를 개선한 NIO2도 등장
java.nio와 그것의 서브패키지 형태
- java.nio.file, java.nio.channels, java.nio.charset 등
File클래스보다 다양한 기능을 제공하는 Path
- Files의 static 메소드를 통한 파일/디렉터리의 조작, 파일의 읽기/쓰기
파일입력과 파일출력이 모두가능한 FileChannel클래스
- 버퍼링기능, 멀티스레드에안전
비동기식 파일입출력을 위한 AsynchronousFileChannel클래스
- non-blocking방식 파일입출력
Path인터페이스
java.nio.file 패키지에 존재하며 java.io.File 클래스를 대신함
파일시스템에 존재하는 파일이나 디렉터리에 해당하는 경로를 표현
절대 경로 또는 상대 경로로 표현됨
경로의 생성, 경로의비교, 경로 정보추출, 경로 요소조작기능 등을 제공
java.nio.file.Files 클래스의 static 메소드를 이용해 Path 객체에 대한 다양한 실제 조작 (생성, 읽기,쓰기, 복사, 이동 등)이 가능함
Path 객체의 생성방법
- Path p = Paths.get("C:\\tmp\\foo");
파일이나 디렉터리의 절대 또는 상대 경로를 명시해야함
Path인터페이스의 메소드
메소드 | 설명 |
int compareTo(Path other) | 두경로를 비교하여 같으면 0을 반 |
Path getFileName() | 디렉터리 또는 파일의 이름을 Path 객체로 리턴 |
FileSystem getFileSystem() | Path객체를 만들어준 FileSystem 객체를 리턴 |
Path getName(int index) | 경로에서 index에 해당하는 이름을 Path객체로 리턴 |
int getNameCount() | 경로에 포함된 원소의 개수를 리턴 |
Path getParent() | 부모 경로를 Path객체로 리턴 |
Path getRoot() | 루트디렉터리를 Path객체로리턴 |
Iterator<Path>iterator() | 경로에 존재하는 모든 디렉터리 또는 파일의 이름을 Iterator객체로 리턴 |
File toFile() | Path객체를 File객체로 변환하여 리턴 |
String toString() | Path객체를 문자열로 변환하여 리턴 |
Path인터페이스 사용예제
import java.util.*
import java.nio.file.*;
public class Main{
public static void main(String args[]){
try{
Path path = Paths.get("C:\\windows\\system32\\driver\\etc\\host");
System.out.println("파일 이름 : " + path.getFileName());
System.out.println("상위 폴더 : " + path.getParent().getFileName());
System.out.println("경로 길이 : " + path.getNameCount());
System.out.println("현재 경로 : ");
for(int i = 0; i < path.getNameCount(); i++)
System.out.println(path.getName(i) + "\\");
Iterator<Path> it = path.iterator();
System.out.println("\n현재 경로 : ");
while(it.hasNext())
System.out.print(it.next().getFileName() + "\\");
}catch (Exception e){
System.out.print(e);
}
}
}
//아래는 결과 예시
파일 이름 : hosts
상위 폴더 : etc
경로 길이 : 5
현재 경로 :
C:\windows\system32\driver\etc\host
현재 경로 :
C:\windows\system32\driver\etc\host
FileSystem클래스와 FileStore클래스
FileSystem 클래스의 메소드
FileSystem은 파일시스템에 대한 인터페이스를 제공
- FileSystem.getDefault()은 기본파일시스템을 리턴함
Iterable <FileStore> getFileStores()
- 하나이상의 파일스토어로 구성됨
WatchService newWatchService()
FileStore클래스의 메소드
FileStore는 저장소(파티션 또는 볼륨)을 표현함
- String name(), String type()
- long getTotalSpace(),
- long getUnallocatedSpace(), long getUsableSpace()
FileSystem 객체로 디스크 정보 출력하기
package testjava;
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException {
FileSystem fs = FileSystems.getDefault();
for(FileStore store : fs.getFileStores()) {
System.out.println("드라이브 이름 : " + store.name());
System.out.println("파일시스템 : " + store.type());
long total = store.getTotalSpace();
long free = store.getUnallocatedSpace();
System.out.println("전체공간 : " + total + "bytes");
System.out.println("사용중인 공간 : " + (total - free) + "bytes");
System.out.println("사용가능한 공간 : " + free + "bytes");
System.out.println();
}
}
}
//아래는 결과 예시
드라이브 이름 : C드라이브
파일시스템 : NTFS
전체공간 : 499321040896bytes
사용중인 공간 : 125864742912bytes
사용가능한 공간 : 373456297984bytes
Files 클래스
파일 조작 기능을 제공하는 static 메소드를 제공함
- 메소드는 Path 객체를 인자로 가지고 작업함
파일의 읽기와 쓰기 메소드
- byte[] readAllBytes(Path), Path write(Path, byte[])
파일이나 디렉터리의 검사/생성/삭제/복사/이동/속성관리 메소드
- boolean isDirectory(Path), boolean isRegularFile(Path)
- Path createFile(Path), Path createDirectory(Path), void delete(Path)
- Path copy(Path, Path), Path move(Path, Path)
- long size(Path), UserPrincipal getOwner(Path)
Files클래스로 디렉터리 확인하기
package testjava;
import java.io.IOException;
import java.nio.file.*;
public class Main {
public static void main(String[] args) throws IOException{
Path path = Paths.get("C:\\Java");
DirectoryStream<Path> ds = Files.newDirectoryStream(path);
for(Path p : ds) {
if(Files.isDirectory(p)) {
System.out.println("[디렉터리]" + p.getFileName());
}else {
System.out.println("[파일]" + p.getFileName());
System.out.println("(" + Files.size(p) + ")");
}
}
}
}
//아래는 결과 예시
[디렉터리] example
[파일] FileInputSteamTest.java (434)
[파일] FileTest1.java (800)
[디렉터리] temp
[파일] winhlp.exe (9728)
[파일] winhlp32.exe (9728)
Buffer클래스
데이터 생산자로부터 프로그램으로 데이터가 입력될때 이력속도와 처리속도의 차이로 인해 지연이 발생할수도있음
프로그램으로부터 데이터 소비자로 데이터가 출력될때도 마찬가지
버퍼를 사용하면 지연 현상을 방지할수있음
- 프로그램은 버퍼로부터 데이터를 읽음(입력)
- 프로그램은 버퍼로 데이터를 출력함 (출력)
- 버퍼는 기본형 값을 저장하는 데이터 보관소
- 채널 입출력에 사용되며 버퍼 단위로 입출력할수있음
Buffer는 추상클래스로 java.nio패키지에 존재
- 자식클래스에서 구현해야할 공통의 메소드를 선언
실제 사용을 위해 boolean을 제외한 모든 기본형에 대해 Buffer의 서브클래스가존재함
- ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer
버퍼의 생성방법
ByteBuffer buffer = ByteBuffer.allocate(1024*1024);
byte[] barray = new byte[100];
Buffer bbuffer = ByteBuffer.wrap(barray);
버퍼의 속성
0 <= mark <= position <= limit <= capacity
- capacity: 버퍼의 크기(데이터의 개수)로, 생성될때 정해짐
- position: 읽기나 쓰기가 적용되는 위치 ( position <= limit)
- limit: 읽거나 쓸수없는 최초 위치 (limit <= capacity)
- mark: reset() 되었을 때 position이 가리킬 위치
Buffer 클래스의 메소드
Buffer mark() | mark를 position의 값으로 설정 |
Buffer reset() | position을 mark의 값으로 설정 |
Buffer rewind() | position을 0으로 바꾸고 mark를 삭제함. 처음부터 다시 읽기를 준비하는 것 |
Buffer flip() | limit를 position값으로 설정하고, position은 0으로 변경함. 버퍼에 쓰기를 끝내고, 버퍼 읽기를 준비하는 것 |
Buffer clear() | 버퍼를 초기 상태로 돌림. 새로운 쓰기를 준비하는 것. |
int capacity() | 현재 capacity값을 리턴 |
int position() | 현재 position값을 리턴 |
int limit() | 현재 limit값을 리턴 |
버퍼 읽기와 쓰기
Buffer의 서브클래스에서 제공
- ByteBuffer, CharBuffer, DoubleBuffer ...
상대적 읽기/쓰기 메소드 (예: ByteBuffer에서)
- 현재 position의 위치에서 읽기 또는 쓰기를 수행하며, 읽거나 쓴 요소만큼 position값이 증가함
- byte get(), ByteBuffer get(byte[])
- ByteBuffer put(byte), ByteBuffer put(byte[])
절대적 읽기/쓰기 메소드
- 읽거나 쓸 위치를 매개변수 index로 지정
- position값에 영향을 주지않음
- byte get(int index)
- ByteBuffer put(int index, byte b)
FileChannel 클래스
java.io 패키지의 파일관련 입출력 스트림을 대체
- java.nio.channels 패키지에 존재
- 파일에 대한 읽기와 쓰기를 모두 제공
- 멀티 스레드 환경에서도 안전하게 사용할수 있음
읽기와 쓰기 메소드
- int read(ByteBuffer dst), int write(ByteBuffer src)
객체 생성 방법
- FileChannel.open(Path path, OpenOption ... options)
- 옵션은 StandardOpenOption.READ. 그외 CREATE, WRITE, APPEND 등
- FileInputStream, FileOutputStream 또는 RandomAccessFile 객체에서 getChannel()
FileChannel클래스로 파일만들기
public class Main {
public static void main(String[] args) throws IOException {
String[] data = {"안녕하세요, 여러분" ,
"자바프로그래밍언어의 세계로 오신것을 환영합니다." ,
"jdk설치하는 방법부터 프로그램을 컴파일하고 실행시키는" ,
"모든 방법에 대해 공부해봅시다."};
Path path = Paths.get("c:\\java\\temp\\file.txt");
Files.createDirectories(path.getParent());
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE);
Charset charset = Charset.defaultcharset();
ByteBuffer buffer;
int byteCount = 0;
for(int i = 0; i < data.length; i++){
buffer = charset.encode(data[i]);
byteCount = fileChannel.write(buffer);
}
System.out.println(byteCount);
fileChannel.close();
}
}
FileChannel클래스로 파일읽기
public class Main {
public static void main(String[] args) throws IOException {
Path path = Paths.get("c:\\java\\temp\\file.txt");
FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allcate(1024 * 1024);
Charset charset = Charset.defaultCharset();
StringBuffer sb = newStringBuffer();
int byteCount;
while((byteCount = fileChannel.read(buffer)) >= 0){
buffer.flip();
sb.append(charset.decode(buffer));
buffer.clear();
}
System.out.println(sb);
fileChannel.close();
}
}
//아래는 결과 예시
안녕하세요, 여러분,자바프로그래밍언어의 세계로 오신것을 환영합니다.jdk설치하는 방법부터 프로그램을 컴파일하고 실행시키는모든 방법에 대해 공부해봅시다.
WatchService 인터페이스
WatchService
어떤 대상을 정한 후 변화나 이벤트가 생기는 것을 감시(watch)
감시대상은 Watchable 객체로, register()메소드를 사용하여 WatchService 객체에 감시대상으로 등록됨
디렉터리를 표현하는 Path 객체의 변화를 감지
- 디렉터리 내의 파일 또는 서브디렉터리의 생성, 삭제, 수정
java.nio.file 패키지에 존재
감시자의 생성
먼저 WatchService 객체를 생성함
- WatchService ws = FileSystems.getDefault().newWatchService();
감시 대상 디렉터리를 WatchService에 등록
- Path path = Paths.get("C:\\java\\temp");
- 등록 시 알림을 받고자하는 이벤트를 명시
- path.register(ws, StandardWatchEventKinds.ENSTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchService는 take()메소드를 호출하여 감시함
- 무한루프안에서 이벤트가 발생할때까지 기다림
- While(true){ WatchKey = ws.take(); }
- 이벤트가 발생하면 take()가 리턴하는 WatchKey 객체를 이용하여 이벤트를 처리
- WatchKey는 감시상태, 감시대상디렉터리, 이벤트정보를 가짐
- pollEvents()를 호출하여 WatchEvent 객체를 얻고 어떤 변화가 생겼는지 알수있음
for(WatchEvent<?> event : key.pollEvents()){
WatchEvent.Kind k = event.kind();
Path p = (Path) event.context():
... ...
}
boolean valid = key.reset();
if(!valid)
break;
WatchService 예제
try{
WatchService ws;
ws = FileSystems.getDefault().newWatchService();
Path path = Paths.get("c:\\java\\temp");
path.register(ws, StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
while(true){
WatchKey key = ws.take();
for(WatchEvent<?> event : key.pollEvents()){
WatchEvent.Kind k = event.kind();
Path p = (Path) evet.context();
if(k == StandardWatchEventDinds.ENTRY_CREATE){
System.out.println("File " + p.getFileName() + " is created.");
}else if(k == StandardWatchEventDinds.ENTRY_DELETE){
System.out.println("File " + p.getFileName() + " is deleted.");
}
... ...
boolean valid = key.reset();
if(!valid) break;
}
}
}
'STUDY > JAVA' 카테고리의 다른 글
[JAVA] MySQL과 JAVA 데이터 타입표 (0) | 2025.01.16 |
---|---|
[JAVA] Date Calender SimpleDateFormat 과 java.time 패키지 (0) | 2025.01.16 |
[Java] 파일 읽고 쓸 때 UTF-8 인코딩 처리 방법 정리 (1) | 2024.11.08 |
[Java] Javadoc 활용한 자바 주석 처리 (0) | 2024.10.30 |
[Java] 바이트 크기를 사람이 읽기 편한 형식으로 변환 (kb, mb, gb ...) (0) | 2024.10.14 |