Java NIO-퀵 가이드

Java.nio 패키지는 Java 1.4에서 도입되었습니다. Java NIO의 Java I / O와 달리 I / O 작업을위한 버퍼 및 채널 지향 데이터 흐름이 도입되어 결과적으로 더 빠른 실행과 더 나은 성능을 제공합니다.

또한 NIO API는 비동기식 또는 비 차단 방식으로 IO 이벤트에 대한 여러 채널을 수신하는 기능을 도입하는 선택기를 제공합니다 .NIO에서는 버퍼를 채우고 속도가 증가하는 운영 체제로의 드레인을 포함하여 가장 시간이 많이 걸리는 I / O 활동입니다.

NIO API의 중앙 추상화는 다음과 같습니다.

  • 데이터, 문자 집합 및 관련 디코더 및 인코더를위한 컨테이너 인 버퍼는 바이트와 유니 코드 문자 사이를 변환합니다.

  • I / O 작업을 수행 할 수있는 엔티티에 대한 연결을 나타내는 다양한 유형의 채널

  • 선택 가능한 채널과 함께 다중화 된 비 차단 I / O 기능을 정의하는 선택기 및 선택 키.

이 섹션에서는 컴퓨터에서 Java를 다운로드하고 설정하는 방법에 대해 설명합니다. 환경을 설정하려면 다음 단계를 따르십시오.

Java SE는 Java 다운로드 링크에서 무료로 사용할 수 있습니다 . 따라서 운영 체제에 따라 버전을 다운로드합니다.

지침에 따라 Java를 다운로드하고 .exe컴퓨터에 Java를 설치합니다. 시스템에 Java를 설치 한 후에는 올바른 설치 디렉토리를 가리 키도록 환경 변수를 설정해야합니다.

Windows 2000 / XP 용 경로 설정

c : \ Program Files \ java \ jdk 디렉토리에 Java를 설치했다고 가정합니다 .

  • '내 컴퓨터'를 마우스 오른쪽 버튼으로 클릭하고 '속성'을 선택합니다.

  • '고급'탭에서 '환경 변수'버튼을 클릭합니다.

  • 이제 Java 실행 파일의 경로도 포함하도록 'Path'변수를 변경하십시오. 예를 들어 현재 경로가 'C : \ WINDOWS \ SYSTEM32'로 설정된 경우 경로를 'C : \ WINDOWS \ SYSTEM32; c : \ Program Files \ java \ jdk \ bin'으로 변경합니다.

Windows 95 / 98 / ME의 경로 설정

c : \ Program Files \ java \ jdk 디렉토리에 Java를 설치했다고 가정합니다 .

  • 'C : \ autoexec.bat'파일을 편집하고 끝에 다음 행을 추가하십시오.
    'SET PATH = % PATH %; C : \ Program Files \ java \ jdk \ bin'

Linux, UNIX, Solaris, FreeBSD에 대한 경로 설정

환경 변수 PATH는 Java 바이너리가 설치된 위치를 가리 키도록 설정되어야합니다. 이 작업을 수행하는 데 문제가 있으면 쉘 문서를 참조하십시오.

예를 들어 bash 를 셸로 사용하는 경우 '.bashrc : export PATH = / path / to / java : $ PATH'끝에 다음 줄을 추가합니다.

인기있는 자바 편집자

자바 프로그램을 작성하려면 텍스트 편집기가 필요합니다. 시장에는 훨씬 더 정교한 IDE가 있습니다. 그러나 지금은 다음 중 하나를 고려할 수 있습니다.

  • Notepad − Windows 시스템에서는 메모장 (이 자습서에 권장 됨), TextPad와 같은 간단한 텍스트 편집기를 사용할 수 있습니다.

  • Netbeans − 오픈 소스이며 무료로 제공되는 Java IDE입니다. http://www.netbeans.org/index.html.

  • Eclipse − 또한 Eclipse 오픈 소스 커뮤니티에서 개발 한 Java IDE이며 다음에서 다운로드 할 수 있습니다. https://www.eclipse.org/.

Java NIO는 기존 Java IO API의 발전을 위해 도입 된 것으로 알고 있습니다. NIO를 IO보다 효율적으로 만드는 주요 개선 사항은 NIO에서 사용되는 채널 데이터 흐름 모델과 기존 IO 작업을위한 운영 체제 사용입니다.

Java NIO와 Java IO의 차이점은 다음과 같이 설명 할 수 있습니다.

  • 이전 게시물에서 언급했듯이 I / O 작업을위한 NIO 버퍼 및 채널 지향 데이터 흐름에서 IO에 비해 더 빠른 실행과 더 나은 성능을 제공합니다. 또한 NIO는 기존 I / O 작업에 운영 체제를 사용하여 다시 한 번 더 효율적입니다.

  • NIO와 IO의 차이점의 다른 측면은이 IO가 스트림 라인 데이터 흐름을 사용한다는 것입니다. 즉, 한 번에 하나 이상의 바이트를 사용하고 데이터 개체를 바이트로 또는 그 반대로 변환하는 데 의존하는 반면 NIO는 바이트 청크 인 데이터 블록을 처리합니다.

  • Java에서 IO 스트림 객체는 단방향이며 NIO 채널에서는 양방향으로 채널이 데이터 읽기 및 쓰기 모두에 사용될 수 있습니다.

  • IO의 간소화 된 데이터 흐름은 데이터에서 앞뒤로 이동하는 것을 허용하지 않습니다. 스트림에서 읽은 데이터에서 앞뒤로 이동해야하는 경우 먼저 버퍼에 캐시해야합니다 .NIO의 경우 버퍼 지향을 사용합니다. 캐싱없이 데이터를 앞뒤로 액세스 할 수 있습니다.

  • NIO API는 또한 IO 작업을 수행하는 동안 현재 스레드가 차단되지 않는 방식으로 데이터를 비동기 적으로 읽고 쓸 수 있도록 다중 스레딩을 지원하여 기존 Java IO API보다 더 효율적입니다.

  • 다중 스레딩의 개념은 Selectors 자바 NIO에서 비동기 또는 비 차단 방식으로 IO 이벤트에 대한 여러 채널을 수신 할 수 있습니다.

  • NIO의 멀티 스레딩은 Non- 블로킹으로 데이터를 사용할 수있을 때만 쓰레드를 읽거나 쓰도록 요청하는 것을 의미합니다. 그렇지 않으면 그동안 다른 작업에서 쓰레드를 사용할 수 있지만, 멀티 스레딩이없는 기존 자바 IO의 경우 불가능합니다. 블로킹으로 만드는 것이 지원됩니다.

  • NIO는 하나의 쓰레드만으로 여러 채널을 관리 할 수 ​​있지만, Java IO의 경우 블로킹 스트림에서 데이터를 읽을 때보 다 데이터 파싱이 다소 복잡 할 수 있으므로 매우 높은 대역폭의 연결이 필요한 경우가 적습니다. 한 번에 많은 데이터를 보내면이 경우보다 Java IO API가 가장 적합 할 수 있습니다.

기술

이름에서 알 수 있듯이 채널은 한쪽 끝에서 다른 쪽 끝으로의 데이터 흐름의 수단으로 사용됩니다. 여기서 Java NIO 채널은 버퍼와 다른 쪽 끝의 엔티티간에 동일하게 작동합니다. 즉 채널은 버퍼로 데이터를 읽고 버퍼에서 데이터를 쓰는 데 사용됩니다.

기존의 Java IO 채널에서 사용되는 스트림과 달리 읽기와 쓰기가 모두 가능합니다. Java NIO 채널은 차단 및 비 차단 모드 모두에서 데이터의 비동기 흐름을 지원합니다.

채널 구현

Java NIO 채널은 주로 다음 클래스에서 구현됩니다.

  • FileChannel− 파일에서 데이터를 읽기 위해 파일 채널을 사용합니다. 파일 채널의 객체는 파일 객체를 직접 생성 할 수 없기 때문에 파일 객체에서 getChannel () 메소드를 호출해야만 생성 할 수 있습니다.

  • DatagramChannel − 데이터 그램 채널은 UDP (User Datagram Protocol)를 통해 네트워크를 통해 데이터를 읽고 쓸 수 있으며, DataGramchannel의 Object는 Factory 방식으로 생성 할 수 있습니다.

  • SocketChannel− SocketChannel 채널은 TCP (Transmission Control Protocol)를 통해 네트워크를 통해 데이터를 읽고 쓸 수 있습니다. 또한 새 개체를 만들기 위해 팩토리 메서드를 사용합니다.

  • ServerSocketChannel− ServerSocketChannel은 웹 서버와 마찬가지로 TCP 연결을 통해 데이터를 읽고 씁니다. 들어오는 모든 연결에 대해 SocketChannel이 생성됩니다.

다음 예제는 텍스트 파일에서 읽습니다. C:/Test/temp.txt 콘텐츠를 콘솔에 인쇄합니다.

temp.txt

Hello World!

ChannelDemo.java

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class ChannelDemo {
   public static void main(String args[]) throws IOException {
      RandomAccessFile file = new RandomAccessFile("C:/Test/temp.txt", "r");
      FileChannel fileChannel = file.getChannel();
      ByteBuffer byteBuffer = ByteBuffer.allocate(512);
      while (fileChannel.read(byteBuffer) > 0) {
         // flip the buffer to prepare for get operation
         byteBuffer.flip();
         while (byteBuffer.hasRemaining()) {
            System.out.print((char) byteBuffer.get());
         }
      }
      file.close();
   }
}

산출

Hello World!

기술

이미 언급했듯이 Java NIO 채널의 FileChannel 구현은 생성, 수정, 크기 등을 포함하여 파일의 메타 데이터 속성에 액세스하기 위해 도입되었습니다.이 파일 채널과 함께 다중 스레드가있어 Java NIO가 Java IO보다 더 효율적입니다.

일반적으로 FileChannel은 파일에서 데이터를 읽고 파일에 데이터를 쓸 수있는 파일과 연결되는 채널이라고 할 수 있습니다 .FileChannel의 또 다른 중요한 특징은 non-blocking 모드로 설정할 수 없다는 것입니다. 항상 차단 모드로 실행됩니다.

파일 채널 객체를 직접 얻을 수 없습니다. 파일 채널의 객체는

  • getChannel() − FileInputStream, FileOutputStream 또는 RandomAccessFile의 메소드.

  • open() − 기본적으로 채널을 여는 파일 채널 방법.

File 채널의 객체 유형은 객체 생성에서 호출되는 클래스 유형에 따라 다릅니다. 즉, FileInputStream의 getchannel 메소드를 호출하여 객체가 생성되면 파일 채널이 읽기 위해 열리고 쓰기 시도시 NonWritableChannelException이 발생합니다.

다음 예제는 Java NIO FileChannel에서 데이터를 읽고 쓰는 방법을 보여줍니다.

다음 예제는 텍스트 파일에서 읽습니다. C:/Test/temp.txt 콘텐츠를 콘솔에 인쇄합니다.

temp.txt

Hello World!

FileChannelDemo.java

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashSet;
import java.util.Set;

public class FileChannelDemo {
   public static void main(String args[]) throws IOException {
      //append the content to existing file 
      writeFileChannel(ByteBuffer.wrap("Welcome to TutorialsPoint".getBytes()));
      //read the file
      readFileChannel();
   }
   public static void readFileChannel() throws IOException {
      RandomAccessFile randomAccessFile = new RandomAccessFile("C:/Test/temp.txt",
      "rw");
      FileChannel fileChannel = randomAccessFile.getChannel();
      ByteBuffer byteBuffer = ByteBuffer.allocate(512);
      Charset charset = Charset.forName("US-ASCII");
      while (fileChannel.read(byteBuffer) > 0) {
         byteBuffer.rewind();
         System.out.print(charset.decode(byteBuffer));
         byteBuffer.flip();
      }
      fileChannel.close();
      randomAccessFile.close();
   }
   public static void writeFileChannel(ByteBuffer byteBuffer)throws IOException {
      Set<StandardOpenOption> options = new HashSet<>();
      options.add(StandardOpenOption.CREATE);
      options.add(StandardOpenOption.APPEND);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path, options);
      fileChannel.write(byteBuffer);
      fileChannel.close();
   }
}

산출

Hello World! Welcome to TutorialsPoint

Java NIO Datagram은 비 연결 프로토콜을 통해 UDP 패킷을 송수신 할 수있는 채널로 사용되며, 기본적으로 데이터 그램 채널은 블로킹이지만 넌 블로킹 모드에서 사용할 수 있습니다. 넌 블로킹으로 만들기 위해 configureBlocking ()을 사용할 수 있습니다. false) method.DataGram 채널은 다음과 같은 정적 메서드 중 하나를 호출하여 열 수 있습니다. open() IP 주소를 매개 변수로 사용하여 멀티 캐스팅에 사용할 수도 있습니다.

FileChannel과 같은 데이터 그램 채널은 기본적으로 연결되어 있지 않으므로 연결하기 위해서는 명시 적으로 connect () 메서드를 호출해야합니다.하지만 연결해야하는 동안 송수신 메서드를 사용하기 위해서는 데이터 그램 채널을 연결할 필요가 없습니다. 읽기 및 쓰기 메서드를 사용하려면 해당 메서드는 소켓 주소를 수락하거나 반환하지 않습니다.

데이터 그램 채널의 연결 상태를 확인할 수 있습니다. isConnected() 연결되면 연결이 끊어 지거나 닫힐 때까지 데이터 그램 채널이 연결된 상태로 유지됩니다. 데이터 그램 채널은 스레드로부터 안전하며 멀티 스레딩과 동시성을 동시에 지원합니다.

데이터 그램 채널의 중요한 방법

  • bind(SocketAddress local) −이 방법은 데이터 그램 채널의 소켓을이 방법의 매개 변수로 제공되는 로컬 주소에 바인딩하는 데 사용됩니다.

  • connect(SocketAddress remote) −이 방법은 소켓을 원격 주소에 연결하는 데 사용됩니다.

  • disconnect() −이 방법은 원격 주소에서 소켓을 분리하는 데 사용됩니다.

  • getRemoteAddress() −이 메서드는 채널의 소켓이 연결된 원격 위치의 주소를 반환합니다.

  • isConnected() − 이미 언급했듯이이 메서드는 데이터 그램 채널의 연결 상태, 즉 연결 여부를 반환합니다.

  • open() and open(ProtocolFamily family) − Open 방식은 단일 주소에 대해 데이터 그램 채널을 열고 프로토콜 패밀리로 표현되는 여러 주소에 대해 매개 변수화 된 개방 방식의 개방 채널을 사용합니다.

  • read(ByteBuffer dst) −이 방법은 데이터 그램 채널을 통해 주어진 버퍼에서 데이터를 읽는 방법입니다.

  • receive(ByteBuffer dst) −이 방법은이 채널을 통해 데이터 그램을 수신하는 데 사용됩니다.

  • send(ByteBuffer src, SocketAddress target) −이 방법은이 채널을 통해 데이터 그램을 전송하는 데 사용됩니다.

다음 예제는 Java NIO DataGramChannel에서 데이터를 보내는 방법을 보여줍니다.

서버 : DatagramChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class DatagramChannelServer {
   public static void main(String[] args) throws IOException {
      DatagramChannel server = DatagramChannel.open();
      InetSocketAddress iAdd = new InetSocketAddress("localhost", 8989);
      server.bind(iAdd);
      System.out.println("Server Started: " + iAdd);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      //receive buffer from client.
      SocketAddress remoteAdd = server.receive(buffer);
      //change mode of buffer
      buffer.flip();
      int limits = buffer.limit();
      byte bytes[] = new byte[limits];
      buffer.get(bytes, 0, limits);
      String msg = new String(bytes);
      System.out.println("Client at " + remoteAdd + "  sent: " + msg);
      server.send(buffer,remoteAdd);
      server.close();
   }
}

산출

Server Started: localhost/127.0.0.1:8989

클라이언트 : DatagramChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class DatagramChannelClient {
   public static void main(String[] args) throws IOException {
      DatagramChannel client = null;
      client = DatagramChannel.open();

      client.bind(null);

      String msg = "Hello World!";
      ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
      InetSocketAddress serverAddress = new InetSocketAddress("localhost",
        8989);

      client.send(buffer, serverAddress);
      buffer.clear();
      client.receive(buffer);
      buffer.flip();
    
      client.close();
   }
}

산출

클라이언트를 실행하면 서버에 다음 출력이 인쇄됩니다.

Server Started: localhost/127.0.0.1:8989
Client at /127.0.0.1:64857  sent: Hello World!

Java NIO 소켓 채널은 소켓을 연결하는 스트림 지향 데이터 흐름에 사용되는 선택기를 사용하여 다중화 할 수 있음을 의미하는 선택 가능한 유형 채널입니다. 소켓 채널은 정적을 호출하여 생성 할 수 있습니다. open() 기존 소켓이 존재하지 않는 경우 소켓 채널은 open 메서드를 호출하여 생성되지만 아직 연결되지 않은 소켓 채널을 연결하려면 connect() 여기서 언급해야 할 점은 채널이 연결되지 않은 상태에서 I / O 작업을 시도하면이 채널에서 NotYetConnectedException이 발생하므로 IO를 수행하기 전에 채널이 연결되어 있는지 확인해야합니다. 채널이 연결되면 닫힐 때까지 연결된 상태로 유지됩니다. 소켓 채널의 상태는 해당 채널을 호출하여 확인할 수 있습니다. isConnected 방법.

소켓 채널의 연결은 finishConnect() 연결 작업이 진행 중인지 여부는 isConnectionPending 메서드를 호출하여 확인할 수 있습니다. 기본적으로 소켓 채널은 비 차단 연결을 지원합니다. 또한 Channel 클래스에 지정된 비동기 닫기 작업과 유사한 비동기 종료를 지원합니다 .Also it supports asynchronous shutdown, which is similar to the asynchronous close operation specified in the Channel class.

소켓 채널은 여러 동시 스레드에서 사용하기에 안전합니다. 동시 읽기 및 쓰기를 지원하지만 최대 하나의 스레드가 읽고있을 수 있고 최대 하나의 스레드가 주어진 시간에 쓸 수 있습니다. connect 및 finishConnect 메소드는 서로에 대해 상호 동기화되며 이러한 메소드 중 하나의 호출이 진행중인 동안 읽기 또는 쓰기 작업을 시작하려는 시도는 해당 호출이 완료 될 때까지 차단됩니다.

소켓 채널의 중요한 방법

  • bind(SocketAddress local) −이 메서드는이 메서드에 매개 변수로 제공되는 로컬 주소에 소켓 채널을 바인딩하는 데 사용됩니다.

  • connect(SocketAddress remote) −이 방법은 소켓을 원격 주소에 연결하는 데 사용됩니다.

  • finishConnect() −이 방법은 소켓 채널 연결 과정을 완료하는 데 사용됩니다.

  • getRemoteAddress() −이 메서드는 채널의 소켓이 연결된 원격 위치의 주소를 반환합니다.

  • isConnected() − 이미 언급했듯이이 메서드는 소켓 채널의 연결 상태, 즉 연결 여부를 반환합니다.

  • open() and open((SocketAddress remote) − Open 메서드는 지정된 주소가없는 소켓 채널을 열고, 지정된 원격 주소에 대해 매개 변수화 된 open 메서드 오픈 채널을 사용하여 연결합니다.이 편리한 메서드는 open () 메서드를 호출하여 결과에 대해 connect 메서드를 호출하는 것처럼 작동합니다. 소켓 채널을 원격으로 전달한 다음 해당 채널을 반환합니다.

  • read(ByteBuffer dst) −이 방법은 소켓 채널을 통해 주어진 버퍼에서 데이터를 읽는 데 사용됩니다.

  • isConnectionPending() −이 방법은이 채널에서 연결 작업이 진행 중인지 여부를 알려줍니다.

다음 예제는 Java NIO SocketChannel에서 데이터를 보내는 방법을 보여줍니다.

C : /Test/temp.txt

Hello World!

클라이언트 : SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

산출

클라이언트를 실행하면 서버가 시작될 때까지 아무것도 인쇄되지 않습니다.

서버 : SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);

      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

산출

서버를 실행하면 다음이 인쇄됩니다.

Connection Set:  /127.0.0.1:49558
File Received

Java NIO 서버 소켓 채널은 다시 소켓을 연결하는 스트림 지향 데이터 흐름에 사용되는 선택 가능한 유형 채널입니다. 서버 소켓 채널은 정적을 호출하여 생성 할 수 있습니다. open() 메소드, 기존 소켓 제공이 아직 존재하지 않는 경우 서버 소켓 채널은 open 메소드를 호출하여 생성되지만 아직 바인딩되지 않았습니다. 소켓 채널을 바인딩하기 위해 bind() 메서드가 호출됩니다.

여기서 언급해야 할 점은 채널이 바인딩되지 않고 I / O 작업이 시도되면이 채널에 의해 NotYetBoundException이 throw되므로 IO 작업을 수행하기 전에 채널이 바인딩되었는지 확인해야합니다.

서버 소켓 채널에 대한 수신 연결은 ServerSocketChannel.accept () 메서드를 호출하여 수신합니다. accept () 메서드가 반환되면 들어오는 연결과 함께 SocketChannel을 반환합니다. 따라서 accept () 메서드는 들어오는 연결이 도착할 때까지 차단됩니다. 채널이 비 차단 모드이면 accept 메서드는 보류중인 연결이 없으면 즉시 null을 반환합니다. 그렇지 않으면 새 연결을 사용할 수 있거나 I / O 오류가 발생할 때까지 무기한 차단됩니다.

새 채널의 소켓은 처음에 바인딩 해제됩니다. 연결이 허용되기 전에 소켓의 바인드 메소드 중 하나를 통해 특정 주소에 바인드되어야합니다. 또한 시스템 전체의 기본 SelectorProvider 객체의 openServerSocketChannel 메소드를 호출하여 새 채널을 생성합니다.

소켓 채널처럼 서버 소켓 채널은 다음을 사용하여 데이터를 읽을 수 있습니다. read()먼저 버퍼가 할당됩니다. ServerSocketChannel에서 읽은 데이터는 버퍼에 저장되고, 두 번째로 ServerSocketChannel.read () 메서드를 호출하고 ServerSocketChannel에서 데이터를 버퍼로 읽습니다. read () 메서드의 정수 값은 버퍼에 쓴 바이트 수를 반환합니다.

마찬가지로 데이터는 다음을 사용하여 서버 소켓 채널에 쓸 수 있습니다. write() 버퍼를 매개 변수로 사용하는 메소드. 일반적으로 Buffer에 쓸 수있는 바이트가 더 이상 없을 때까지 write () 메소드를 반복해야하므로 while 루프에서 write 메소드를 사용합니다.

소켓 채널의 중요한 방법

  • bind(SocketAddress local) −이 메서드는이 메서드에 매개 변수로 제공되는 로컬 주소에 소켓 채널을 바인딩하는 데 사용됩니다.

  • accept() −이 방법은이 채널의 소켓에 대한 연결을 수락하는 데 사용됩니다.

  • connect(SocketAddress remote) −이 방법은 소켓을 원격 주소에 연결하는 데 사용됩니다.

  • finishConnect() −이 방법은 소켓 채널 연결 과정을 완료하는 데 사용됩니다.

  • getRemoteAddress() −이 메서드는 채널의 소켓이 연결된 원격 위치의 주소를 반환합니다.

  • isConnected() − 이미 언급했듯이이 메서드는 소켓 채널의 연결 상태, 즉 연결 여부를 반환합니다.

  • open() − Open 메서드는 지정된 주소가없는 소켓 채널을 여는 방식으로, 이는 open () 메서드를 호출하고 결과 서버 소켓 채널에 대해 connect 메서드를 호출하고 원격으로 전달한 다음 해당 채널을 반환하는 것처럼 작동합니다.

  • read(ByteBuffer dst) −이 방법은 소켓 채널을 통해 주어진 버퍼에서 데이터를 읽는 데 사용됩니다.

  • setOption(SocketOption<T> name, T value) −이 방법은 소켓 옵션의 값을 설정합니다.

  • socket() −이 메서드는이 채널과 관련된 서버 소켓을 검색합니다.

  • validOps() −이 메서드는이 채널의 지원되는 작업을 식별하는 작업 집합을 반환합니다. 서버 소켓 채널은 새 연결 허용 만 지원하므로이 메서드는 SelectionKey.OP_ACCEPT를 반환합니다.

다음 예제는 Java NIO ServerSocketChannel에서 데이터를 보내는 방법을 보여줍니다.

C : /Test/temp.txt

Hello World!

클라이언트 : SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

산출

클라이언트를 실행하면 서버가 시작될 때까지 아무것도 인쇄되지 않습니다.

서버 : SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

산출

서버를 실행하면 다음이 인쇄됩니다.

Connection Set:  /127.0.0.1:49558
File Received

Java NIO는 Java의 기존 IO API에 비해 데이터 IO 작업에 더 최적화 된 API라는 것을 알고 있습니다. Java NIO가 제공하는 추가 지원은 여러 버퍼에서 채널로 데이터를 읽고 쓰는 것입니다. 쓰기 지원을 Scatter and Gather라고합니다. 데이터를 읽은 경우 데이터가 단일 채널에서 여러 버퍼로 분산되고 쓰기 데이터의 경우 데이터가 여러 버퍼에서 단일 채널로 수집됩니다.

채널에서 이러한 다중 읽기 및 쓰기를 수행하기 위해 Java NIO가 데이터를 읽고 쓰기 위해 제공하는 ScatteringByteChannel 및 GatheringByteChannel API가 아래 예제와 같이 제공됩니다.

ScatteringByteChannel

Read from multiple channels − 여기에서는 단일 채널의 데이터를 여러 버퍼로 읽어들이도록 만들었습니다.이를 위해 여러 버퍼를 할당하고 버퍼 유형 배열에 추가 한 다음이 배열을 매개 변수로 ScatteringByteChannel read () 메서드에 전달한 다음 데이터를 씁니다. 시퀀스의 채널 버퍼는 배열에서 발생합니다. 버퍼가 가득 차면 채널은 다음 버퍼를 채우기 위해 이동합니다.

다음 예제는 Java NIO에서 데이터 분산이 수행되는 방법을 보여줍니다.

C : /Test/temp.txt

Hello World!
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ScatteringByteChannel;

public class ScatterExample {	
   private static String FILENAME = "C:/Test/temp.txt";
   public static void main(String[] args) {
      ByteBuffer bLen1 = ByteBuffer.allocate(1024);
      ByteBuffer bLen2 = ByteBuffer.allocate(1024);
      FileInputStream in;
      try {
         in = new FileInputStream(FILENAME);
         ScatteringByteChannel scatter = in.getChannel();
         scatter.read(new ByteBuffer[] {bLen1, bLen2});
         bLen1.position(0);
         bLen2.position(0);
         int len1 = bLen1.asIntBuffer().get();
         int len2 = bLen2.asIntBuffer().get();
         System.out.println("Scattering : Len1 = " + len1);
         System.out.println("Scattering : Len2 = " + len2);
      } 
      catch (FileNotFoundException exObj) {
         exObj.printStackTrace();
      }
      catch (IOException ioObj) {
         ioObj.printStackTrace();
      }
   }
}

산출

Scattering : Len1 = 1214606444
Scattering : Len2 = 0

마지막으로 Java NIO의 분산 / 수집 접근 방식은 적절하게 사용할 때 최적화되고 멀티 태스킹 된 것으로 도입되었으며,이를 통해 읽은 데이터를 여러 버킷으로 분리하거나 조립하는 번거로운 작업을 운영 체제에 위임 할 수 있습니다. 이질적인 데이터 청크를 전체로 통합합니다. 이것은 버퍼 복사를 방지하여 시간을 절약하고 운영 체제를보다 효율적으로 사용하며 작성 및 디버그에 필요한 코드 양을 줄입니다.

Java NIO는 Java의 기존 IO API에 비해 데이터 IO 작업에 더 최적화 된 API라는 것을 알고 있습니다. Java NIO가 제공하는 추가 지원은 여러 버퍼에서 채널로 데이터를 읽고 쓰는 것입니다. 쓰기 지원을 Scatter and Gather라고합니다. 데이터를 읽은 경우 데이터가 단일 채널에서 여러 버퍼로 분산되고 쓰기 데이터의 경우 데이터가 여러 버퍼에서 단일 채널로 수집됩니다.

채널에서 이러한 다중 읽기 및 쓰기를 수행하기 위해 Java NIO가 데이터를 읽고 쓰기 위해 제공하는 ScatteringByteChannel 및 GatheringByteChannel API가 아래 예제와 같이 제공됩니다.

GatheringByteChannel

write to multiple channels − 여기에서는 여러 버퍼의 데이터를 단일 채널에 쓰도록 만들었습니다.이를 위해 다시 여러 버퍼를 할당하고 버퍼 유형 배열에 추가 한 다음이 배열을 매개 변수로 GatheringByteChannel write () 메서드에 전달한 다음 데이터를 기록합니다. 시퀀스의 여러 버퍼에서 버퍼는 배열에서 발생합니다. 여기서 기억해야 할 점은 버퍼의 위치와 제한 사이의 데이터 만 기록된다는 것입니다.

다음 예제는 Java NIO에서 데이터 수집이 수행되는 방법을 보여줍니다.

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.GatheringByteChannel;

public class GatherExample {
   private static String FILENAME = "C:/Test/temp.txt";
   public static void main(String[] args) {
      String stream1 = "Gather data stream first";
      String stream2 = "Gather data stream second";
      ByteBuffer bLen1 = ByteBuffer.allocate(1024);
      ByteBuffer bLen2 = ByteBuffer.allocate(1024);
      // Next two buffer hold the data we want to write
      ByteBuffer bstream1 = ByteBuffer.wrap(stream1.getBytes());
      ByteBuffer bstream2 = ByteBuffer.wrap(stream2.getBytes());
      int len1 = stream1.length();
      int len2 = stream2.length();
      // Writing length(data) to the Buffer
      bLen1.asIntBuffer().put(len1);
      bLen2.asIntBuffer().put(len2);
      System.out.println("Gathering : Len1 = " + len1);
      System.out.println("Gathering : Len2 = " + len2);
      // Write data to the file
      try { 
         FileOutputStream out = new FileOutputStream(FILENAME);
         GatheringByteChannel gather = out.getChannel();						
         gather.write(new ByteBuffer[] {bLen1, bLen2, bstream1, bstream2});
         out.close();
         gather.close();
      }
      catch (FileNotFoundException exObj) {
         exObj.printStackTrace();
      }
      catch(IOException ioObj) {
         ioObj.printStackTrace();
      }
   }
}

산출

Gathering : Len1 = 24
Gathering : Len2 = 25

마지막으로 Java NIO의 분산 / 수집 접근 방식은 적절하게 사용할 때 최적화되고 멀티 태스킹 된 것으로 도입되었으며,이를 통해 읽은 데이터를 여러 버킷으로 분리하거나 조립하는 번거로운 작업을 운영 체제에 위임 할 수 있습니다. 이질적인 데이터 청크를 전체로 통합합니다. 이것은 버퍼 복사를 방지하여 시간을 절약하고 운영 체제를보다 효율적으로 사용하며 작성 및 디버그에 필요한 코드 양을 줄입니다.

Java NIO의 버퍼는 버퍼가 채널에 대한 엔드 포인트 역할을하도록 채널에 데이터를 쓰거나 채널에서 데이터를 읽는 데 사용할 수있는 고정 된 크기의 데이터 청크 컨테이너 역할을하는 단순한 객체로 취급 될 수 있습니다.

채널에서 데이터를 읽고 쓰기 위해 메모리 블록을보다 편리하게 처리 할 수있는 일련의 메서드를 제공합니다.

버퍼는 IO 데이터가 데이터의 비동기 및 동시 흐름을 지원하지 않는 스트림 형태로 처리되는 경우 기존 IO에 비해 NIO 패키지를 더 효율적이고 빠르게 만듭니다. 또한 IO는 청크 또는 바이트 그룹의 데이터 실행을 허용하지 않습니다. .

Java NIO 버퍼를 정의하는 기본 매개 변수는 다음과 같이 정의 할 수 있습니다.

  • Capacity − 버퍼에 저장할 수있는 데이터 / 바이트의 최대 양. 버퍼의 용량은 변경할 수 없으며, 버퍼가 가득 차면 쓰기 전에 지워야합니다.

  • Limit − Limit는 Buffer의 모드에 따라 의미가 있습니다. 즉, Buffer Limit의 쓰기 모드에서 버퍼에 쓸 수있는 최대 데이터를 의미하는 용량과 같으며, 읽기 모드에서는 버퍼에 쓸 수있는 데이터의 한계를 의미합니다. 버퍼에서 읽습니다.

  • Position − buffer 내 커서의 현재 위치를 가리키며, 처음에는 buffer 생성시 0으로 설정되거나, 즉 get () 및 put ()에 의해 자동으로 업데이트되는 읽거나 쓸 다음 요소의 인덱스입니다. ) 방법.

  • Mark − 버퍼에 위치의 북마크를 표시하고, mark () 메서드를 호출하면 현재 위치를 기록하고 reset ()을 호출하면 표시된 위치를 복원합니다.

버퍼 유형

Java NIO 버퍼는 버퍼가 다루는 데이터 유형에 따라 다음과 같은 변형으로 분류 할 수 있습니다.

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

버퍼의 중요한 방법

이미 언급했듯이 Buffer는 메모리 블록을보다 편리하게 처리 할 수있는 일련의 메소드를 제공하는 메모리 객체 역할을합니다. 다음은 Buffer의 중요한 메소드입니다.

  • allocate(int capacity) −이 메소드는 용량이있는 새 버퍼를 매개 변수로 할당하는 데 사용되며, Allocate 메소드는 전달 된 용량이 음의 정수인 경우 IllegalArgumentException을 발생시킵니다.

  • read() and put() − 채널 읽기 방식은 채널에서 버퍼로 데이터를 쓰는 방식이고, 넣기 방식은 버퍼에 데이터를 쓰는 방식입니다.

  • flip() − 플립 방식은 Buffer 모드를 쓰기 모드에서 읽기 모드로 전환하며, 위치를 다시 0으로 설정하고 쓰기 시점의 위치로 제한을 설정합니다.

  • write() and get() − 채널의 쓰기 방식은 버퍼에서 채널로 데이터를 쓰는 방식이고, get은 버퍼에서 데이터를 읽는 방식입니다.

  • rewind() − 되감기 방법은 위치를 다시 0으로 설정하고 한계 값을 변경하지 않기 때문에 다시 읽기가 필요할 때 사용됩니다.

  • clear() and compact() − clear 및 compact 두 방법 모두 읽기에서 쓰기 모드로 버퍼를 만드는 데 사용됩니다.clear() 방법은 위치를 0으로 만들고 제한은 용량과 같으며,이 방법에서는 버퍼의 데이터가 지워지지 않고 마커 만 다시 초기화됩니다.

    반면에 compact() 메서드는 읽지 않은 데이터가 남아있을 때 사용되며이 경우에도 버퍼의 쓰기 모드를 사용합니다.이 경우 compact 메서드는 읽지 않은 모든 데이터를 버퍼의 시작 부분에 복사하고 마지막 읽지 않은 요소 바로 뒤에 위치를 설정합니다. 용량으로 설정합니다.

  • mark() and reset() − 이름에서 알 수 있듯이 마크 방법은 버퍼의 특정 위치를 표시하는 데 사용되며 위치를 다시 표시된 위치로 재설정합니다.

다음 예제는 위에 정의 된 메소드의 구현을 보여줍니다.

import java.nio.ByteBuffer;
import java.nio.CharBuffer;

public class BufferDemo {
   public static void main (String [] args) {
      //allocate a character type buffer.
      CharBuffer buffer = CharBuffer.allocate(10);
      String text = "bufferDemo";
      System.out.println("Input text: " + text);
      for (int i = 0; i < text.length(); i++) {
         char c = text.charAt(i);
         //put character in buffer.
		 buffer.put(c);
      }
      int buffPos = buffer.position();
      System.out.println("Position after data is written into buffer: " + buffPos);
      buffer.flip();
      System.out.println("Reading buffer contents:");
      while (buffer.hasRemaining()) {
         System.out.println(buffer.get());                   
      }
      //set the position of buffer to 5.
      buffer.position(5);
      //sets this buffer's mark at its position
      buffer.mark();
      //try to change the position
      buffer.position(6);
      //calling reset method to restore to the position we marked.
      //reset() raise InvalidMarkException if either the new position is less
      //than the position marked or merk has not been setted.
      buffer.reset();
      System.out.println("Restored buffer position : " + buffer.position());
   }
}

산출

Input text: bufferDemo
Position after data is written into buffer: 10
Reading buffer contents:
b
u
f
f
e
r
D
e
m
o
Restored buffer position : 5

Java NIO는 채널과 버퍼에 대한 다중 트랜잭션을 지원한다는 것을 알고 있습니다. 따라서 하나 이상의 NIO 채널을 검사하고 데이터 트랜잭션을 위해 준비된 채널 (예 : Java NIO 읽기 또는 쓰기)을 결정하기 위해 Selector를 제공합니다.

Selector를 사용하면 어떤 채널이 데이터 쓰기 및 읽기 준비가되었는지 알 수있는 스레드를 만들고 해당 특정 채널을 처리 할 수 ​​있습니다.

정적 메서드를 호출하여 선택기 인스턴스를 얻을 수 있습니다. open()오픈 셀렉터 후에 우리는 SelectionKey의 인스턴스를 반환하는 비 차단 모드 채널을 등록해야합니다.

SelectionKey는 기본적으로 채널로 수행 할 수있는 작업 모음이거나 선택 키를 사용하여 채널의 상태를 알 수 있다고 말할 수 있습니다.

선택 키로 표시되는 주요 작업 또는 채널 상태는 다음과 같습니다.

  • SelectionKey.OP_CONNECT − 서버에 연결할 준비가 된 채널.

  • SelectionKey.OP_ACCEPT − 들어오는 연결을 수락 할 준비가 된 채널.

  • SelectionKey.OP_READ − 데이터를 읽을 준비가 된 채널.

  • SelectionKey.OP_WRITE − 데이터 쓰기 준비가 된 채널.

등록 후 얻은 선택 키에는 아래에 언급 된 몇 가지 중요한 방법이 있습니다.

  • attach() − 키로 오브젝트를 붙이는 방법으로, 오브젝트를 채널에 붙이는 주된 목적은 같은 채널을 인식하는 것입니다.

  • attachment() −이 방법은 채널에서 부착 된 개체를 유지하는 데 사용됩니다.

  • channel() −이 방법은 특정 키가 생성 된 채널을 가져 오는 데 사용됩니다.

  • selector() −이 방법은 특정 키가 생성 된 선택자를 가져 오는 데 사용됩니다.

  • isValid() −이 메서드는 키가 유효한지 날씨를 반환합니다.

  • isReadable() −이 방법은 날씨 키의 채널을 읽을 준비가되었는지 여부를 나타냅니다.

  • isWritable() −이 방법은 날씨 키의 채널이 쓰기 준비가되었는지 여부를 나타냅니다.

  • isAcceptable() −이 방법은 날씨 키의 채널이 수신 연결을 수락 할 준비가되었는지 여부를 나타냅니다.

  • isConnectable() −이 메서드는이 키의 채널이 소켓 연결 작업을 완료했는지 또는 완료하지 못했는지 테스트합니다.

  • isAcceptable() −이 메서드는이 키의 채널이 새 소켓 연결을 수락 할 준비가되었는지 여부를 테스트합니다.

  • interestOps() −이 방법은이 키의 관심 세트를 검색합니다.

  • readyOps() −이 메소드는 채널이 준비된 작업 세트 인 준비 세트를 검색합니다.

선택기에서 정적 메서드를 호출하여 채널을 선택할 수 있습니다. select(). 선택기의 선택 방법은 다음과 같이 과부하됩니다.

  • select() −이 메서드는 등록 된 이벤트에 대해 하나 이상의 채널이 준비 될 때까지 현재 스레드를 차단합니다.

  • select(long timeout) −이 메서드는 최대 타임 아웃 밀리 초 (파라미터) 동안 스레드를 차단한다는 점을 제외하면 select ()와 동일합니다.

  • selectNow() −이 메서드는 전혀 차단하지 않으며 준비된 채널이 있으면 즉시 반환합니다.

또한 select 메서드를 호출하는 차단 된 스레드를 떠나기 위해wakeup() 메서드는 selector 인스턴스에서 호출 될 수 있으며 그 후 select () 내부에서 대기중인 스레드가 즉시 반환됩니다.

마지막으로 다음을 호출하여 선택기를 닫을 수 있습니다. close() 선택기를 닫고이 선택기에 등록 된 모든 SelectionKey 인스턴스를 무효화하는 메서드입니다.

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SelectorDemo {
   public static void main(String[] args) throws IOException {
      String demo_text = "This is a demo String";	
      Selector selector = Selector.open();
      ServerSocketChannel serverSocket = ServerSocketChannel.open();
      serverSocket.bind(new InetSocketAddress("localhost", 5454));
      serverSocket.configureBlocking(false);
      serverSocket.register(selector, SelectionKey.OP_ACCEPT);
      ByteBuffer buffer = ByteBuffer.allocate(256);
      while (true) {
         selector.select();
         Set<SelectionKey> selectedKeys = selector.selectedKeys();
         Iterator<SelectionKey> iter = selectedKeys.iterator();
         while (iter.hasNext()) {
            SelectionKey key = iter.next();
            int interestOps = key.interestOps();
            System.out.println(interestOps);
            if (key.isAcceptable()) {
               SocketChannel client = serverSocket.accept();
               client.configureBlocking(false);
               client.register(selector, SelectionKey.OP_READ);
            }
            if (key.isReadable()) {
               SocketChannel client = (SocketChannel) key.channel();
               client.read(buffer);
               if (new String(buffer.array()).trim().equals(demo_text)) {
                  client.close();
                  System.out.println("Not accepting client messages anymore");
               }
               buffer.flip();
               client.write(buffer);
               buffer.clear();
            }
            iter.remove();
         }
      }
   }
}

Java에서 NIO 파이프는 두 스레드간에 데이터를 쓰고 읽는 데 사용되는 구성 요소로, 파이프는 주로 데이터 전파를 담당하는 두 채널로 구성됩니다.

두 개의 구성 채널 중 하나는 주로 데이터 쓰기를위한 Sink 채널이라고하고 다른 하나는 Sink 채널에서 데이터를 읽는 것이 주 목적인 Source 채널입니다.

데이터 동기화는 데이터가 파이프에 기록되는 순서와 동일한 순서로 읽혀 져야하므로 데이터 쓰기 및 읽기 동안 순서대로 유지됩니다.

파이프에서 데이터의 단방향 흐름이라는 점에 유의해야합니다. 즉, 데이터는 싱크 채널에만 기록되고 소스 채널에서만 읽을 수 있습니다.

Java에서 NIO 파이프는 주로 세 가지 메서드가있는 추상 클래스로 정의되며 그 중 두 가지는 추상입니다.

파이프 클래스의 방법

  • open() −이 메서드는 Pipe의 인스턴스를 가져 오거나이 메서드를 호출하여 파이프가 생성되었다고 말할 수 있습니다.

  • sink() −이 메서드는 write 메서드를 호출하여 데이터를 쓰는 데 사용되는 Pipe의 싱크 채널을 반환합니다.

  • source() −이 메서드는 read 메서드를 호출하여 데이터를 읽는 데 사용되는 Pipe의 소스 채널을 반환합니다.

다음 예제는 Java NIO 파이프의 구현을 보여줍니다.

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;

public class PipeDemo {
   public static void main(String[] args) throws IOException {
      //An instance of Pipe is created
      Pipe pipe = Pipe.open();
      // gets the pipe's sink channel
      Pipe.SinkChannel skChannel = pipe.sink();
      String testData = "Test Data to Check java NIO Channels Pipe.";
      ByteBuffer buffer = ByteBuffer.allocate(512);
      buffer.clear();
      buffer.put(testData.getBytes());
      buffer.flip();
      //write data into sink channel.
      while(buffer.hasRemaining()) {
         skChannel.write(buffer);
      }
      //gets  pipe's source channel
      Pipe.SourceChannel sourceChannel = pipe.source();
      buffer = ByteBuffer.allocate(512);
      //write data into console     
      while(sourceChannel.read(buffer) > 0){
         //limit is set to current position and position is set to zero
         buffer.flip();
         while(buffer.hasRemaining()){
            char ch = (char) buffer.get();
            System.out.print(ch);
         }
         //position is set to zero and limit is set to capacity to clear the buffer.
         buffer.clear();
      }
   }
}

산출

Test Data to Check java NIO Channels Pipe.

텍스트 파일이 있다고 가정합니다. c:/test.txt, 다음과 같은 내용이 있습니다. 이 파일은 예제 프로그램의 입력으로 사용됩니다.

이름에서 알 수 있듯이 Path는 특정 위치에서 검색하고 액세스 할 수 있도록 파일 또는 파일 시스템의 디렉토리와 같은 엔티티의 특정 위치입니다.

기술적으로 Java 측면에서 Path는 Java 버전 7에서 Java NIO 파일 패키지에 도입 된 인터페이스이며 특정 파일 시스템의 위치를 ​​나타내는 인터페이스입니다. 경로 인터페이스가 Java NIO 패키지에 있으므로 정규화 된 이름을 java로 가져옵니다. .nio.file.Path.

일반적으로 엔티티의 경로는 두 가지 유형이 될 수 있습니다 하나는 절대 경로이고 다른 하나는 상대 경로입니다. 두 경로의 이름은 절대 경로가 루트에서 엔티티까지의 위치 주소이고 상대 경로는 위치 주소임을 나타냅니다. 다른 경로에 상대적입니다 .Path는 정의에서 구분 기호를 Windows의 경우 "\"로, 유닉스 운영 체제의 경우 "/"로 사용합니다.

Path의 인스턴스를 얻기 위해 java.nio.file.Paths 클래스의 정적 메소드를 사용할 수 있습니다. get()이 메서드는 경로 문자열 또는 경로 문자열을 구성 할 때 결합 된 문자열 시퀀스를 Path 인스턴스로 변환합니다 .This method converts a path string, or a sequence of strings that when join form a path string, to a Path instance. 전달 된 인수에 잘못된 문자가 포함 된 경우이 메서드는 런타임 InvalidPathException도 throw합니다.

위에서 언급했듯이 절대 경로는 루트 요소와 파일을 찾는 데 필요한 전체 디렉토리 목록을 전달하여 검색합니다. 상대 경로는 기본 경로와 상대 경로를 결합하여 검색 할 수 있습니다. 두 경로의 검색은 다음 예제에서 설명합니다.

package com.java.nio;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathDemo {
   public static void main(String[] args) throws IOException {
      Path relative = Paths.get("file2.txt");
      System.out.println("Relative path: " + relative);
      Path absolute = relative.toAbsolutePath();
      System.out.println("Absolute path: " + absolute);
   }
}

지금까지 우리는 경로 인터페이스가 왜 필요한지, 어떻게 액세스 할 수 있는지 알고 있었으며 이제 경로 인터페이스가 제공하는 중요한 메서드가 무엇인지 알게되었습니다.

경로 인터페이스의 중요한 방법

  • getFileName() −이 객체를 생성 한 파일 시스템을 반환합니다.

  • getName() −이 경로의 이름 요소를 경로 객체로 반환합니다.

  • getNameCount() − 경로에있는 이름 요소의 수를 반환합니다.

  • subpath() −이 경로의 이름 요소의 하위 시퀀스 인 상대 경로를 반환합니다.

  • getParent() − 부모 경로를 반환하거나이 경로에 부모가 없으면 null을 반환합니다.

  • getRoot() −이 경로의 루트 구성 요소를 Path 객체로 반환하거나이 경로에 루트 구성 요소가 없으면 null을 반환합니다.

  • toAbsolutePath() −이 경로의 절대 경로를 나타내는 Path 객체를 반환합니다.

  • toRealPath() − 기존 파일의 실제 경로를 반환합니다.

  • toFile() −이 경로를 나타내는 File 객체를 반환합니다.

  • normalize() − 중복 된 이름 요소가 제거 된 경로 인 경로를 반환합니다.

  • compareTo(Path other) − 두 개의 추상 경로를 사전 식으로 비교합니다.이 메소드는 인수가이 경로와 같으면 0을 반환하고,이 경로가 사전 식으로 인수보다 작 으면 0보다 작은 값을 반환하고,이 경로가 사 전적으로 인수보다 크면 0보다 큰 값을 반환합니다. .

  • endsWith(Path other) −이 경로가 주어진 경로로 끝나는 지 테스트합니다. 주어진 경로에 N 개의 요소가 있고 루트 구성 요소가없고이 경로에 N 개 이상의 요소가있는 경우이 경로는 각 경로의 마지막 N 개 요소 인 경우 지정된 경로로 끝납니다. 루트에서 가장 먼 요소에서 시작하여 동일합니다.

  • endsWith(String other) −이 경로가 endsWith (Path) 메서드에 지정된 방식으로 정확히 지정된 경로 문자열을 변환하여 생성 된 경로로 끝나는 지 테스트합니다.

다음 예제는 위에서 언급 한 다양한 경로 인터페이스 방법을 설명합니다.

package com.java.nio;
import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathDemo {
   public static void main(String[] args) throws IOException {
      Path path = Paths.get("D:/workspace/ContentW/Saurav_CV.docx");
      FileSystem fs =  path.getFileSystem();
      System.out.println(fs.toString());
      System.out.println(path.isAbsolute());
      System.out.println(path.getFileName());
      System.out.println(path.toAbsolutePath().toString());
      System.out.println(path.getRoot());
      System.out.println(path.getParent());
      System.out.println(path.getNameCount());
      System.out.println(path.getName(0));
      System.out.println(path.subpath(0, 2));
      System.out.println(path.toString());
      System.out.println(path.getNameCount());
      Path realPath = path.toRealPath(LinkOption.NOFOLLOW_LINKS);
      System.out.println(realPath.toString());
      String originalPath = "d:\\data\\projects\\a-project\\..\\another-project";
      Path path1 = Paths.get(originalPath);
      Path path2 = path1.normalize();
      System.out.println("path2 = " + path2);
   }
}

Java NIO 패키지는 주로 Path 객체에서 작동하는 정적 메소드를 사용하여 파일 및 디렉토리를 조작하는 데 기본적으로 사용되는 파일이라는 유틸리티 API를 하나 더 제공합니다.

Path tutorial에서 언급했듯이 파일 패키지의 Java 7 버전 동안 Java NIO 패키지에 Path 인터페이스가 도입되었으므로이 자습서는 동일한 File 패키지에 대한 것입니다.

이 클래스는 파일, 디렉터리 또는 다른 유형의 파일에서 작동하는 정적 메서드로만 구성됩니다. 대부분의 경우 여기에 정의 된 메서드는 파일 작업을 수행하기 위해 연결된 파일 시스템 공급자에게 위임됩니다.

파일 클래스에는 Java 문서에서도 읽을 수있는 많은 메소드가 정의되어 있습니다.이 튜토리얼에서는 Java NIO Files 클래스의 모든 메소드 중에서 중요한 메소드 중 일부를 다루려고했습니다.

Files 클래스의 중요한 메서드.

다음은 Java NIO 파일 클래스에 정의 된 중요한 메소드입니다.

  • createFile(Path filePath, FileAttribute attrs) − Files 클래스는 지정된 Path를 사용하여 파일을 생성하는 방법을 제공합니다.

package com.java.nio;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class CreateFile {
   public static void main(String[] args) {
      //initialize Path object
      Path path = Paths.get("D:file.txt");
      //create file
      try {
         Path createdFilePath = Files.createFile(path);
         System.out.println("Created a file at : "+createdFilePath);
      } 
      catch (IOException e) {
         e.printStackTrace();
      }
   }
}

산출

Created a file at : D:\data\file.txt
  • copy(InputStream in, Path target, CopyOption… options) −이 메서드는 지정된 입력 스트림에서 지정된 대상 파일로 모든 바이트를 복사하고 다음 값을 가진이 매개 변수에 대해 long value.LinkOption으로 읽거나 쓴 바이트 수를 반환하는 데 사용됩니다.

    • COPY_ATTRIBUTES − 속성을 새 파일에 복사합니다 (예 : 마지막 수정 시간 속성).

    • REPLACE_EXISTING − 기존 파일이 있으면 교체합니다.

    • NOFOLLOW_LINKS − 파일이 심볼릭 링크 인 경우 링크 대상이 아닌 링크 자체가 복사됩니다.

package com.java.nio;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
public class WriteFile {
   public static void main(String[] args) {
      Path sourceFile = Paths.get("D:file.txt");
      Path targetFile = Paths.get("D:fileCopy.txt");
      try {
         Files.copy(sourceFile, targetFile,
         StandardCopyOption.REPLACE_EXISTING);
      }
      catch (IOException ex) {
         System.err.format("I/O Error when copying file");
      }
      Path wiki_path = Paths.get("D:fileCopy.txt");
      Charset charset = Charset.forName("ISO-8859-1");
      try {
         List<String> lines = Files.readAllLines(wiki_path, charset);
         for (String line : lines) {
            System.out.println(line);
         }
      } 
      catch (IOException e) {
         System.out.println(e);
      }
   }	
}

산출

To be or not to be?
  • createDirectories(Path dir, FileAttribute<?>...attrs) −이 방법은 존재하지 않는 모든 상위 디렉토리를 생성하여 주어진 경로를 사용하여 디렉토리를 생성하는 데 사용됩니다.

  • delete(Path path) −이 메소드는 지정된 경로에서 파일을 삭제하는 데 사용되며, 지정된 경로에 파일이 존재하지 않거나 파일이 디렉토리이고 비어 있지 않아 삭제할 수없는 경우 NoSuchFileException을 발생시킵니다.

  • exists(Path path) −이 방법은 지정된 경로에 파일이 있는지 확인하고 파일이 존재하면 true를 반환하고 그렇지 않으면 false를 반환합니다.

  • readAllBytes(Path path) −이 메소드는 주어진 경로에있는 파일의 모든 바이트를 읽고 파일에서 읽은 바이트를 포함하는 바이트 배열을 반환하는 데 사용됩니다.

package com.java.nio;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class ReadFile {
   public static void main(String[] args) {
      Path wiki_path = Paths.get("D:file.txt");
      Charset charset = Charset.forName("ISO-8859-1");
      try {
         List<String> lines = Files.readAllLines(wiki_path, charset);
         for (String line : lines) {
            System.out.println(line);
         }
      } 
      catch (IOException e) {
         System.out.println(e);
      }
   }	
}

산출

Welcome to file.
  • size(Path path) −이 방법은 지정된 경로에있는 파일의 크기를 바이트 단위로 가져 오는 데 사용됩니다.

  • write(Path path, byte[] bytes, OpenOption… options) −이 방법은 지정된 경로에있는 파일에 바이트를 쓰는 데 사용됩니다.

package com.java.nio;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
public class WriteFile {
   public static void main(String[] args) {
      Path path = Paths.get("D:file.txt");
      String question = "To be or not to be?";
      Charset charset = Charset.forName("ISO-8859-1");
      try {
         Files.write(path, question.getBytes());
         List<String> lines = Files.readAllLines(path, charset);
         for (String line : lines) {
            System.out.println(line);
         }
      } 
      catch (IOException e) {
         System.out.println(e);
      }
   }
}

산출

To be or not to be?

Java NIO는 동시성과 멀티 스레딩을 지원하여 동시에 서로 다른 채널을 동시에 처리 할 수 ​​있다는 것을 알고 있으므로 Java NIO 패키지에서이를 담당하는 API는 NIO channels 패키지에 정의 된 AsynchronousFileChannel입니다. AsynchronousFileChannel의 경우 java.nio.channels.AsynchronousFileChannel.

AsynchronousFileChannel은 스레드가 작업에 들어가서 요청이 완료 될 때까지 대기하는 동기 I / O 작업과 달리이 채널을 사용하면 파일 작업을 비동기 적으로 실행할 수 있다는 점을 제외하면 NIO의 FileChannel과 유사합니다. 여러 동시 스레드에 의해.

비동기식에서 요청은 스레드가 운영 체제의 커널로 전달하여 스레드가 다른 작업을 계속 처리하는 동안 완료됩니다. 커널 작업이 완료되면 스레드에 신호를 보내고 스레드는 신호를 확인하고 현재 작업을 중단하고 필요에 따라 I / O 작업.

동시성을 달성하기 위해이 채널은 하나를 반환하는 두 가지 접근 방식을 제공합니다. java.util.concurrent.Future object 다른 하나는 유형의 객체를 작업에 전달하는 것입니다. java.nio.channels.CompletionHandler.

우리는 예제를 통해 하나씩 두 가지 접근 방식을 이해할 것입니다.

  • Future Object −이 경우 Future Interface의 인스턴스가 채널에서 반환됩니다. Future 인터페이스에는 get() 다른 작업의 추가 실행을 결정할 수있는 기준으로 비동기 적으로 처리되는 작업의 상태를 반환하는 메서드입니다. 또한 작업이 완료되었는지 여부를 확인할 수 있습니다. isDone 방법.

다음 예제는 Future 객체를 사용하고 비동기 적으로 작업하는 방법을 보여줍니다.

package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class FutureObject {
   public static void main(String[] args) throws Exception {
      readFile();
   }
   private static void readFile() throws IOException, InterruptedException, ExecutionException {
      String filePath = "D:fileCopy.txt";
      printFileContents(filePath);
      Path path = Paths.get(filePath);		
      AsynchronousFileChannel channel =AsynchronousFileChannel.open(path, StandardOpenOption.READ);
      ByteBuffer buffer = ByteBuffer.allocate(400);
      Future<Integer> result = channel.read(buffer, 0); // position = 0
      while (! result.isDone()) {
         System.out.println("Task of reading file is in progress asynchronously.");
      }
      System.out.println("Reading done: " + result.isDone());
      System.out.println("Bytes read from file: " + result.get()); 
      buffer.flip();
      System.out.print("Buffer contents: ");
      while (buffer.hasRemaining()) {
         System.out.print((char) buffer.get());                
      }
      System.out.println(" ");
      buffer.clear();
      channel.close();
   }
   private static void printFileContents(String path) throws IOException {
      FileReader fr = new FileReader(path);
      BufferedReader br = new BufferedReader(fr);
      String textRead = br.readLine();
      System.out.println("File contents: ");
      while (textRead != null) {
         System.out.println("     " + textRead);
         textRead = br.readLine();
      }
   fr.close();
   br.close();
   }
}

산출

File contents: 
   To be or not to be?
   Task of reading file is in progress asynchronously.
   Task of reading file is in progress asynchronously.
   Reading done: true
   Bytes read from file: 19
   Buffer contents: To be or not to be?
  • Completion Handler

    이 접근 방식은 CompletionHandler 인터페이스를 사용하고 두 메서드를 재정의하는 것처럼 매우 간단합니다. completed() I / O 작업이 성공적으로 완료되고 다른 작업이 완료 될 때 호출되는 메소드 failed() I / O 작업이 실패 할 경우 호출되는 메서드 여기에서 작업이 완료되면 처리기 만 실행되는 함수를 가지므로 비동기 I / O 작업의 결과를 소비하기위한 핸들러가 생성됩니다.

다음 예제는 CompletionHandler를 사용하여 비동기 적으로 작업하는 방법을 보여줍니다.

package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class CompletionHandlerDemo {
   public static void main (String [] args) throws Exception {
      writeFile();
   }
   private static void writeFile() throws IOException {
      String input = "Content to be written to the file.";
      System.out.println("Input string: " + input);
      byte [] byteArray = input.getBytes();
      ByteBuffer buffer = ByteBuffer.wrap(byteArray);
      Path path = Paths.get("D:fileCopy.txt");
      AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
      CompletionHandler handler = new CompletionHandler() {
         @Override
         public void completed(Object result, Object attachment) {
            System.out.println(attachment + " completed and " + result + " bytes are written.");
         }
         @Override
         public void failed(Throwable exc, Object attachment) {
            System.out.println(attachment + " failed with exception:");
            exc.printStackTrace();
         }
      };
      channel.write(buffer, 0, "Async Task", handler);
      channel.close();
      printFileContents(path.toString());
   }
   private static void printFileContents(String path) throws IOException {
      FileReader fr = new FileReader(path);
      BufferedReader br = new BufferedReader(fr);
      String textRead = br.readLine();
      System.out.println("File contents: ");
      while (textRead != null) {
         System.out.println("     " + textRead);
         textRead = br.readLine();
      }
      fr.close();
      br.close();
   }
}

산출

Input string: Content to be written to the file.
Async Task completed and 34 bytes are written.
File contents: 
Content to be written to the file.

Java에는 모든 문자에 대해 JVM이 내부적으로 처리하는 잘 정의 된 유니 코드 코드 단위가 있으므로 Java NIO 패키지는 주로 charset 및 UNICODE의 인코딩 및 디코딩에 사용되는 Charset이라는 추상 클래스를 정의합니다.

표준 문자 세트

Java에서 지원되는 Charset은 다음과 같습니다.

  • US-ASCII − 7 비트 ASCII 문자.

  • ISO-8859-1 − ISO 라틴 알파벳.

  • UTF-8 − 8 비트 UCS 변환 형식입니다.

  • UTF-16BE − 빅 엔디안 바이트 순서를 사용하는 16 비트 UCS 변환 형식입니다.

  • UTF-16LE − 이것은 리틀 엔디안 바이트 순서의 16 비트 UCS 변환입니다.

  • UTF-16 − 16 비트 UCS 변환 형식.

Charset 클래스의 중요한 메서드

  • forName() −이 메서드는 주어진 문자셋 이름에 대한 문자셋 객체를 생성합니다. 이름은 정식 또는 별칭 일 수 있습니다.

  • displayName() −이 메서드는 주어진 문자 집합의 정식 이름을 반환합니다.

  • canEncode() −이 방법은 주어진 문자셋이 인코딩을 지원하는지 여부를 확인합니다.

  • decode() −이 방법은 주어진 문자셋의 문자열을 유니 코드 문자셋의 문자 버퍼로 디코딩합니다.

  • encode() −이 방법은 유니 코드 문자셋의 문자 버퍼를 주어진 문자셋의 바이트 버퍼로 인코딩합니다.

다음 예제는 Charset 클래스의 중요한 메서드를 보여줍니다.

package com.java.nio;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
public class CharsetExample {
   public static void main(String[] args) {
      Charset charset = Charset.forName("US-ASCII");
      System.out.println(charset.displayName());
      System.out.println(charset.canEncode());
      String str = "Demo text for conversion.";
      //convert byte buffer in given charset to char buffer in unicode
      ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());
      CharBuffer charBuffer = charset.decode(byteBuffer);
      //convert char buffer in unicode to byte buffer in given charset
      ByteBuffer newByteBuffer = charset.encode(charBuffer);
      while(newbb.hasRemaining()){
         char ch = (char) newByteBuffer.get();
         System.out.print(ch);
      }
      newByteBuffer.clear();
   }
}

산출

US-ASCII
Demo text for conversion.

Java NIO는 동시에 여러 파일에서 작동하는 여러 스레드를 처리 할 수있는 동시성 및 다중 스레딩을 지원하지만 경우에 따라 파일이 어떤 스레드에서도 공유되지 않고 액세스 할 수 없도록해야합니다.

이러한 요구 사항에 대해 NIO는 전체 파일 또는 파일 일부에 대한 잠금을 제공하는 데 사용되는 FileLock이라는 API를 다시 제공하므로 파일 또는 그 일부가 공유되거나 액세스되지 않습니다.

이러한 잠금을 제공하거나 적용하려면 두 가지 방법을 제공하는 FileChannel 또는 AsynchronousFileChannel을 사용해야합니다. lock()tryLock()제공되는 잠금 장치는 두 가지 유형이 있습니다.

  • Exclusive Lock − 배타적 잠금은 다른 프로그램이 두 유형의 중복 잠금을 획득하는 것을 방지합니다.

  • Shared Lock − 공유 잠금은 동시에 실행되는 다른 프로그램이 겹치는 배타적 잠금을 획득하는 것을 방지하지만 겹치는 공유 잠금을 획득 할 수 있습니다.

파일에 대한 잠금 획득에 사용되는 방법-

  • lock() − FileChannel 또는 AsynchronousFileChannel의이 메소드는 주어진 채널과 관련된 파일에 대한 배타적 잠금을 획득합니다.이 메소드의 반환 유형은 획득 된 잠금을 모니터링하는 데 더 사용되는 FileLock입니다.

  • lock(long position, long size, boolean shared) −이 방식 역시 잠금 방식의 오버로드 방식이며 파일의 특정 부분을 잠그는 데 사용됩니다.

  • tryLock() −이 메서드는 잠금을 획득 할 수없고이 채널의 파일에 대해 명시 적으로 배타적 인 잠금을 획득하려고 시도하는 경우 FileLock 또는 null을 반환합니다.

  • tryLock(long position, long size, boolean shared) −이 방법은 배타적이거나 공유 유형일 수있는이 채널 파일의 주어진 영역에 대한 잠금을 획득하려고 시도합니다.

FileLock 클래스의 방법

  • acquiredBy() −이 메서드는 파일 잠금을 획득 한 채널을 반환합니다.

  • position() −이 메서드는 잠긴 영역의 첫 번째 바이트의 파일 내 위치를 반환합니다. 잠긴 영역은 실제 기본 파일 내에 포함되거나 겹칠 필요가 없으므로이 메서드에서 반환 된 값이 파일의 현재 크기를 초과 할 수 있습니다.

  • size() −이 메서드는 잠긴 영역의 크기를 바이트 단위로 반환합니다. 잠긴 영역은 실제 기본 파일 내에 포함되거나 겹칠 필요가 없으므로이 메서드에서 반환 된 값이 파일의 현재 크기를 초과 할 수 있습니다.

  • isShared() −이 방법은 잠금 공유 여부를 결정하는 데 사용됩니다.

  • overlaps(long position,long size) −이 방법은이 잠금이 주어진 잠금 범위와 겹치는 지 여부를 알려줍니다.

  • isValid() −이 메서드는 획득 한 잠금이 유효한지 여부를 알려줍니다. 잠금 객체는 해제되거나 관련 파일 채널이 닫힐 때까지 유효한 상태를 유지합니다.

  • release()− 획득 한 잠금을 해제합니다. 잠금 개체가 유효하면이 메서드를 호출하면 잠금이 해제되고 개체가 유효하지 않게됩니다. 이 잠금 개체가 유효하지 않은 경우이 메서드를 호출해도 효과가 없습니다.

  • close()−이 메서드는 release () 메서드를 호출합니다. 자동 자원 관리 블록 구성과 함께 사용할 수 있도록 클래스에 추가되었습니다.

파일 잠금을 보여주는 예제입니다.

다음 예제는 파일에 대한 잠금을 만들고 내용을 작성합니다.

package com.java.nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class FileLockExample {
   public static void main(String[] args) throws IOException {
      String input = "Demo text to be written in locked mode.";  
      System.out.println("Input string to the test file is: " + input);  
      ByteBuffer buf = ByteBuffer.wrap(input.getBytes());  
      String fp = "D:file.txt";  
      Path pt = Paths.get(fp);  
      FileChannel channel = FileChannel.open(pt, StandardOpenOption.WRITE,StandardOpenOption.APPEND);  
      channel.position(channel.size() - 1); // position of a cursor at the end of file       
      FileLock lock = channel.lock();   
      System.out.println("The Lock is shared: " + lock.isShared());  
      channel.write(buf);  
      channel.close(); // Releases the Lock  
      System.out.println("Content Writing is complete. Therefore close the channel and release the lock.");  
      PrintFileCreated.print(fp);  
   }  
}
package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class PrintFileCreated {
   public static void print(String path) throws IOException {  
      FileReader filereader = new FileReader(path);  
      BufferedReader bufferedreader = new BufferedReader(filereader);  
      String tr = bufferedreader.readLine();    
      System.out.println("The Content of testout.txt file is: ");  
      while (tr != null) {      
         System.out.println("    " + tr);  
         tr = bufferedreader.readLine();  
      }  
   filereader.close();  
   bufferedreader.close();  
   }  
}

산출

Input string to the test file is: Demo text to be written in locked mode.
The Lock is shared: false
Content Writing is complete. Therefore close the channel and release the lock.
The Content of testout.txt file is: 
To be or not to be?Demo text to be written in locked mode.