스마트웹앱콘텐츠전문가/JAVA

[자바7]입출력

9D4U 2018. 5. 29. 18:34
728x90
반응형

★ 자바7은 네트워크 입출력 버전 2 API(NIO.2)를 새로 추가해서

   이제 폴더 모니터링, OS 의존적인 메서드 접근, 확장 가능한 비동기 네트워크 소켓 생성 기능이 가능해짐. <- import java.nio.file.*

★ I/O 스트림은 자바 I/O의 거의 모든 것의 기반이 됨.

   하나의 '스트림'은 데이터의 입출력을 나타냄(흐르는 강물에 비유)

   또, 이 스트림들은 서로 연결 될 수도 있는데 이것을 '데커레이터 패턴'이라 부름(이 데터레이터 패턴 덕분에 매우 다양한 효과를 얻을 수 있음 = 모든 종류의 입력을 취하고, 출력을 생산하는 스트림을 생성할 수 있고, 다른 모든 스트림들이 서로 엮일수 있음)


   입력 스트림 - 파일 입력 스트림   ---> 파일 출력 스트림과 상응

       - 네트워크 소켓 입력 스트림 : 네트워크 소켓 출력 스트림과 상응

   ※ 입/출력 스트림들은 다양하게 엮어 사용 가능(예: 네트워크 입력 스트림[유입 데이터=소스] -> 파일 출력 데이터[유출 데이터=싱크])

   

   이런 스트림 이외에 BufferInputStream이 있음. 이 스트림은 조각(chunk)단위로 데이터를 읽을 수 있음.(바이트 단위로 읽는 것보다 효율적)

   DataOutputStream은 자바 원형 객체를 출력 스트림으로 쓸 수 있음.

   ※ 가장 유용한 스트림 중 하나인 ObjectInputStream과 ObjectOutputStream은 객체를 직렬화/역직렬화할 때 사용.


   cf. 직렬화 : (자바)시스템 내부에서 사용되는 객체 혹은 데이터를 외부(시스템)에서도 사용할 수 있도록 '바이트'형태로 데이터를 변환하는 기술 = 객체를 직렬화하면 전송 가능한 형태로 만드는 것을 의미함.

       역직렬화 : 바이트로 변환된 데이터를 다시 객체로 변환하는 기술 = 직렬화된 데이터 등을 역으로 직렬화하여 다시 '객체'의 형태로 만드는 것

=> 직렬화에서 제공하는 기능은 객체를 얻어 그 객체의 바이트 표현을 생성하는 것임.


1. 자바 객체 직렬화하기

- 내장된 직렬화 메커니즘 사용. ObjectOutputStream 클래스를 사용하여 그 메커니즘에 접근


2. 자바 객체를 더 효율적으로 직렬화하기 : 클래스를 직렬화하고 싶은데, 기본적으로 제공하는 내장 직렬화 메서드의 생성 결과보다 크기가 더 작거나 효율적인 산출물을 원함.

- 'Externalizable 인터페이스'를 구현하는 객체를 한 개 생성하고, 자바 가상 머신(JVM)이 그 객체에서 제공하는 readExternal/writeExternal 메서드를 사용해 사용자 맞춤 직렬화/역직렬화 메커니즘을 수행.

- Serializable 인터페이스 대신 Externalizable 구현이 더 효율적인 이유는 자바의 기본 직렬화가 비효율적이기 때문.

  자바 직렬화 프렝미워크는 모든 객체를 직렬화 대상으로 보기 때문에 null 또는 empty 같은 기본값을 갖는 객체까지도 직렬화하려 함.

  그러나 Externalizable 인터페이스를 구현하면 더 매끄럽게 클래스 직렬화를 제어할 수 있음.

  cf. Externalizable 인터페이스를 구현한 클래스를 작성하려면 그 클래스는 전닭받는 인자가 없는 비어 있는 생성자 필요.

3. 자바 객체를 XML로 직렬화하기

- XMLEncoder 객체를 사용해 프로그램 설정 정보를 저장하고, 설정 정보를 settings.xml 파일에 옮겨 쓰는 Settings 객체를 인코드 함.

  XMLDecider는 settings.xml 파일ㅇ르 스트림으로 읽고 Settings 객체로 디코드함.

예시)

/*자바 객체를 xml로 직렬화*/

ProgramSettings settings = new ProgramSettings( new Point(10, 10), new Dimension(300, 200), Color.blue, "The Title of thee application" );

try{

//인코딩

FileSystem fileSystem = FileSystems.getDefault();

FileOutputStream fos = new FileOutputStream("settings.xml");

XMLEncoder encoder = new XMLEncoder(fos);

encoder.setExceptionListener(new ExceptionListener() {

@Override

public void exceptionThrown(Exception arg0) {

// TODO Auto-generated method stub

System.out.println("exception :" + arg0.toString());

}

});

encoder.writeObject(settings);

encoder.close();

fos.close();

//디코딩

FileInputStream fis = new FileInputStream("settings.xml");

XMLDecoder decoder = new XMLDecoder(fis);

ProgramSettings decodedSettings = (ProgramSettings)decoder.readObject();

System.out.println("is same? :" + settings.equals(decodedSettings));

fis.close();

}catch(IOException e){

e.printStackTrace();

}


4. 네트워크를 통해 직렬화 객체를 전송하는 소켓 연결 생성하기

- NIO 2.0의 논블록킹 소켓 기능 사용.

5. 자바 실행 경로 얻기

- System 클래스의 getProperry 메서드를 수행 : 자바 프로그램이 시작될 떄 JRE는 user.dir 시스템 속성 값을 JRE가 수행된 위치의 레코드로 갱신함.

6. 파일 복사하기 : 폴더에 있는 파일을 다른 폴더로 복사

- 디폴터 FileSystem에서 파일이나 폴더에 대한 from과 to 경로를 생성. Files.copy 정적 메서드를 이용해 앞에서 생성한 경로로 파일을 복사

cf. FileSystem.getDefaults()는 파일 처리가 가능하 추상화된 시스템을 반환

7. 파일 이동하기 

- Files.move() 정적 메서드 실행

cf. import java.nio.file.Files;

Files 객체가 제공하는 다른 메서드들

- Delete(path) : 파일(또는 빈 폴더)을 삭제

- Exists(path) : 파일 또는 폴더가 존재하는지 확인

- isDirectory(path) : 생성된 경로가 디렉터리를 가리키는 확인

- isExecutable(path) : 실행 파일인지 확인

- isHidden(path) : 해당 파일이 그 운영체제에서 숨긴 파일인지 확인

8. 디렉터리 만들기

- Files.createDirectory() 정적 메서드 : 명시한 경로에 디렉터리를 생성. 다른 설정을 하지 않는다면 생성된 디렉토리는 기본허가를 상속함.

- 리눅스 운영체제에서 PosixFilePermission() 메서드를 수행 : 폴더 속성 지정 가능

9. 디레터리 파일을 순회하기

- NIO.2 를 사용해 FileVisitor를 생성하고 폴더를 방문하기

- SimpleFileVisitor 클래스

예시)

        FileVisitor<Path> myFileVisitor = new SimpleFileVisitor<Path>() {

            @Override

            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {

                System.out.println("Visited File: "+file.toString());

                return FileVisitResult.CONTINUE;

            }

        };

        

        FileSystem fileSystem = FileSystems.getDefault();

        Path directory = fileSystem.getPath(".");

        try{

        Files.walkFileTree(directory, myFileVisitor);

        }catch(IOException e){

        e.printStackTrace();

        }

    

10. 파일 메타데이터를 조회하고 설정하기

= 예시)

            System.out.println("File Size:"+Files.size(path));

            System.out.println("Is Directory:"+Files.isDirectory(path));

            System.out.println("Is Regular File:"+Files.isRegularFile(path));

            System.out.println("Is Symbolic Link:"+Files.isSymbolicLink(path));

            System.out.println("Is Hidden:"+Files.isHidden(path));

            System.out.println("Last Modified Time:"+Files.getLastModifiedTime(path));

            System.out.println("Owner:"+Files.getOwner(path));


            // Specific attribute views.

            DosFileAttributeView view = Files.getFileAttributeView(path, DosFileAttributeView.class);

            System.out.println("\nDOS File Attributes\n------------------------------------\n");

            System.out.println("Archive  :"+view.readAttributes().isArchive());

            System.out.println("Hidden   :"+view.readAttributes().isHidden());

            System.out.println("Read-only:"+view.readAttributes().isReadOnly());

            System.out.println("System   :"+view.readAttributes().isSystem());

            

            view.setArchive(false);

11. 디렉터리 변경 감시하기

-WatchService를 사용해 폴더에서 발생하는이벤트 알림을 구독할 수 있음, 폴(poll) 메커니즘이 동작.

예시)

System.out.println("Watch Event, press q<Enter> to exit");

FileSystem fileSystem = FileSystems.getDefault();

WatchService service = fileSystem.newWatchService();

Path path = fileSystem.getPath(".");

System.out.println(path.toAbsolutePath().toString());

path.register(service, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);

boolean shouldContinue = true;

while (shouldContinue) {

WatchKey key = service.poll(250, TimeUnit.MILLISECONDS);

//프로그램을 중지하는 코드

while (System.in.available() > 0) {

int readChar = System.in.read();

if((readChar == 'q') || (readChar == 'Q')){

shouldContinue = false;

break;

}

}

if(key == null) continue;

for(WatchEvent<?> event : key.pollEvents()){

if(event.kind() == StandardWatchEventKinds.OVERFLOW) continue;

WatchEvent<Path> ev = (WatchEvent<Path>)event;

Path filename = ev.context();

System.out.println("Event detected :" + filename.toString() + " " + ev.kind());

}

boolean valid = key.reset();

if(!valid){

break;

}

}


12. 속성 파일 읽기

-Properties 객체를 사용하여 properties.conf파일에 저장된 속성을 읽어옴.

Properties 클래스는 프로그램 속성을 관리함. 이 클래스를 사용하면 누군가 myapp.conf 파일을 편집하는 것과 같은 외부 파일 수정이나 Properties.store()메서드를

호출해 속성을 수정하는 것을 관리할 수 있음.

Properties 객체는 메모리에 올려진 파일을 가지고 초기화가 가능한데, 실제 파일이 없어도 초기화가 가능함.

이 객체는 속성 이름과 값을 [name]=[value] 형식으로 표현하는 파일을 읽을 수 있음

속성 조회할 떄는 getProperties(String, String) 메서드를 호출, 

13. 압축 파일 풀기

- java.util.zip 패키지를 사용하면 .zip파일을 열고, .zip 파일 내부에 있는 항목들을 순회할 수 있음. ZipFile 객체 생성

728x90

'스마트웹앱콘텐츠전문가 > JAVA' 카테고리의 다른 글

[자바7]동시성  (0) 2018.06.05
[java7]이메일  (0) 2018.05.30
[자바7]숫자와 날짜  (0) 2018.05.28
[Java7]문자열  (0) 2018.05.28
자바 날짜(시간) 비교  (0) 2018.05.24