Java NIO - คู่มือฉบับย่อ

แพ็คเกจ Java.nio ถูกนำมาใช้ใน java 1.4 ในทางตรงกันข้ามกับ java I / O ใน java NIO จะมีการนำเสนอบัฟเฟอร์และช่องทางข้อมูลสำหรับการดำเนินการ I / O ซึ่งส่งผลให้การดำเนินการเร็วขึ้นและประสิทธิภาพที่ดี

นอกจากนี้ NIO API ยังมีตัวเลือกที่แนะนำฟังก์ชันการฟังหลายช่องสัญญาณสำหรับเหตุการณ์ IO ในแบบอะซิงโครนัสหรือไม่ปิดกั้นใน NIO กิจกรรม I / O ที่ใช้เวลามากที่สุดรวมถึงการเติมและระบายบัฟเฟอร์ไปยังระบบปฏิบัติการซึ่งจะเพิ่มความเร็ว

นามธรรมกลางของ NIO API มีดังต่อไปนี้ -

  • บัฟเฟอร์ซึ่งเป็นที่เก็บข้อมูลชุดอักขระและตัวถอดรหัสและตัวเข้ารหัสที่เกี่ยวข้องซึ่งแปลระหว่างอักขระไบต์และอักขระ Unicode

  • แชนเนลประเภทต่างๆซึ่งแสดงถึงการเชื่อมต่อกับเอนทิตีที่สามารถดำเนินการ I / O ได้

  • ตัวเลือกและปุ่มการเลือกซึ่งร่วมกับแชนเนลที่เลือกได้จะกำหนดสิ่งอำนวยความสะดวก I / O แบบมัลติเพล็กซ์และไม่ปิดกั้น

ส่วนนี้จะแนะนำคุณเกี่ยวกับวิธีดาวน์โหลดและตั้งค่า Java บนเครื่องของคุณ โปรดทำตามขั้นตอนต่อไปนี้เพื่อตั้งค่าสภาพแวดล้อม

Java SE เป็นอิสระที่มีอยู่จากการเชื่อมโยงดาวน์โหลด Java คุณจึงดาวน์โหลดเวอร์ชันที่อิงตามระบบปฏิบัติการของคุณ

ทำตามคำแนะนำเพื่อดาวน์โหลด java และเรียกใช้ไฟล์ .exeเพื่อติดตั้ง Java บนเครื่องของคุณ เมื่อคุณติดตั้ง Java บนเครื่องของคุณคุณจะต้องตั้งค่าตัวแปรสภาพแวดล้อมเพื่อชี้ไปที่ไดเร็กทอรีการติดตั้งที่ถูกต้อง -

การตั้งค่าเส้นทางสำหรับ windows 2000 / XP

สมมติว่าคุณติดตั้ง Java ในไดเร็กทอรีc: \ Program Files \ java \ jdk -

  • คลิกขวาที่ 'My Computer' และเลือก 'Properties'

  • คลิกที่ปุ่ม "ตัวแปรสภาพแวดล้อม" ใต้แท็บ "ขั้นสูง"

  • ตอนนี้เปลี่ยนตัวแปร 'Path' เพื่อให้มีพา ธ ไปยังไฟล์ปฏิบัติการ Java ตัวอย่างหากเส้นทางถูกตั้งค่าเป็น 'C: \ WINDOWS \ SYSTEM32' ให้เปลี่ยนเส้นทางของคุณเป็นอ่าน 'C: \ WINDOWS \ SYSTEM32; c: \ Program Files \ java \ jdk \ bin'

การตั้งค่าเส้นทางสำหรับ windows 95/98 / ME

สมมติว่าคุณติดตั้ง Java ในไดเร็กทอรีc: \ Program Files \ java \ jdk -

  • แก้ไขไฟล์ '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'

บรรณาธิการ Java ยอดนิยม

ในการเขียนโปรแกรม Java ของคุณคุณจะต้องมีโปรแกรมแก้ไขข้อความ มี IDE ที่ซับซ้อนมากขึ้นในตลาด แต่ในตอนนี้คุณสามารถพิจารณาข้อใดข้อหนึ่งต่อไปนี้ -

  • Notepad - บนเครื่อง Windows คุณสามารถใช้โปรแกรมแก้ไขข้อความง่ายๆเช่น Notepad (แนะนำสำหรับบทช่วยสอนนี้), TextPad

  • Netbeans - เป็น Java IDE ที่เป็นโอเพ่นซอร์สและฟรีซึ่งสามารถดาวน์โหลดได้จาก http://www.netbeans.org/index.html.

  • Eclipse - ยังเป็น java IDE ที่พัฒนาโดยชุมชนโอเพนซอร์ส eclipse และสามารถดาวน์โหลดได้จาก https://www.eclipse.org/.

ดังที่เราทราบว่า java NIO ได้รับการแนะนำเพื่อความก้าวหน้าของ java IO API แบบเดิมการปรับปรุงหลักที่ทำให้ NIO มีประสิทธิภาพมากกว่า IO คือรูปแบบการไหลของข้อมูลช่องทางที่ใช้ใน NIO และการใช้ระบบปฏิบัติการสำหรับงาน IO ทั่วไป

ความแตกต่างระหว่าง Java NIO และ Java IO สามารถอธิบายได้ดังต่อไปนี้ -

  • ตามที่กล่าวไว้ในโพสต์ก่อนหน้าในบัฟเฟอร์ NIO และการไหลของข้อมูลที่มุ่งเน้นช่องสัญญาณสำหรับการดำเนินการ I / O ซึ่งให้การดำเนินการที่รวดเร็วขึ้นและประสิทธิภาพที่ดีขึ้นเมื่อเทียบกับ IO นอกจากนี้ NIO ยังใช้ระบบปฏิบัติการสำหรับงาน I / O ทั่วไปซึ่งทำให้มีประสิทธิภาพมากขึ้นอีกครั้ง

  • ความแตกต่างอื่น ๆ ระหว่าง NIO และ IO คือ IO นี้ใช้การไหลของข้อมูลสตรีมไลน์เช่นครั้งละหนึ่งไบต์และอาศัยการแปลงอ็อบเจ็กต์ข้อมูลเป็นไบต์และในทางกลับกันในขณะที่ NIO เกี่ยวข้องกับบล็อกข้อมูลซึ่งเป็นกลุ่มไบต์

  • ในอ็อบเจ็กต์สตรีม java IO เป็นแบบทิศทางเดียวในขณะที่ช่อง NIO เป็นแบบสองทิศทางหมายความว่าช่องสัญญาณสามารถใช้สำหรับทั้งการอ่านและการเขียนข้อมูล

  • การไหลของข้อมูลที่คล่องตัวใน IO ไม่อนุญาตให้ย้ายไปมาและย้อนกลับในข้อมูลหากกรณีจำเป็นต้องย้ายไปมาและย้อนกลับในข้อมูลที่อ่านจากสตรีมจำเป็นต้องแคชข้อมูลในบัฟเฟอร์ก่อนในขณะที่ NIO เราใช้บัฟเฟอร์เชิง ซึ่งช่วยให้สามารถเข้าถึงข้อมูลไปมาได้โดยไม่ต้องใช้แคช

  • NIO API ยังรองรับ multi threading เพื่อให้สามารถอ่านและเขียนข้อมูลแบบอะซิงโครนัสได้เช่นในขณะที่ดำเนินการ IO เธรดปัจจุบันจะไม่ถูกบล็อกสิ่งนี้ทำให้มีประสิทธิภาพมากกว่า java IO API ทั่วไปอีกครั้ง

  • มีการนำแนวคิดของเธรดหลายแบบมาใช้ด้วยการแนะนำ Selectors ใน java NIO ซึ่งอนุญาตให้ฟังหลายช่องสัญญาณสำหรับเหตุการณ์ IO ในแบบอะซิงโครนัสหรือไม่ปิดกั้น

  • เธรดหลายเธรดใน NIO ทำให้ไม่ใช่การปิดกั้นซึ่งหมายความว่าเธรดถูกร้องขอให้อ่านหรือเขียนเฉพาะเมื่อมีข้อมูลเท่านั้นมิฉะนั้นเธรดจะสามารถใช้ในงานอื่นได้ในเวลาเฉลี่ย แต่จะเป็นไปไม่ได้ในกรณีของ java IO แบบเดิมเนื่องจากไม่มีเธรดแบบมัลติ ได้รับการสนับสนุนซึ่งทำให้เป็นการปิดกั้น

  • NIO อนุญาตให้จัดการหลายช่องทางโดยใช้เธรดเดียวเท่านั้น แต่ค่าใช้จ่ายคือการแยกวิเคราะห์ข้อมูลอาจค่อนข้างซับซ้อนกว่าเมื่ออ่านข้อมูลจากสตรีมการบล็อกในกรณีของ java IO ดังนั้นในกรณีที่ต้องการการเชื่อมต่อน้อยลงด้วยแบนด์วิดท์ที่สูงมาก ด้วยการส่งข้อมูลครั้งละมาก ๆ มากกว่าในกรณีนี้ java IO API อาจเหมาะสมที่สุด

คำอธิบาย

ตามชื่อแนะนำช่องถูกใช้เป็นค่าเฉลี่ยของการไหลของข้อมูลจากปลายด้านหนึ่งไปยังอีกด้านหนึ่งที่นี่ในช่อง java NIO จะทำหน้าที่เหมือนกันระหว่างบัฟเฟอร์และเอนทิตีที่ปลายอีกด้านหนึ่งในคำอื่น ๆ ช่องใช้เพื่ออ่านข้อมูลไปยังบัฟเฟอร์และเขียนข้อมูลจากบัฟเฟอร์

แตกต่างจากสตรีมที่ใช้ในแชนเนล Java IO ทั่วไปคือสองทางคือสามารถอ่านและเขียนได้ Java NIO channel รองรับการไหลของข้อมูลแบบอะซิงโครนัสทั้งในโหมดบล็อกและไม่บล็อก

การใช้งานช่อง

ช่อง Java NIO ถูกนำไปใช้ในคลาสต่อไปนี้เป็นหลัก -

  • FileChannel- ในการอ่านข้อมูลจากไฟล์เราใช้ช่องไฟล์ ออบเจ็กต์ของช่องไฟล์สามารถสร้างได้โดยการเรียกเมธอด getChannel () บนอ็อบเจ็กต์ไฟล์เท่านั้นเนื่องจากเราไม่สามารถสร้างอ็อบเจ็กต์ไฟล์ได้โดยตรง

  • DatagramChannel - ช่องดาต้าแกรมสามารถอ่านและเขียนข้อมูลผ่านเครือข่ายผ่าน UDP (User Datagram Protocol) วัตถุของ DataGramchannel สามารถสร้างได้โดยใช้วิธีการของโรงงาน

  • 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!

คำอธิบาย

ดังที่ได้กล่าวไปแล้วการใช้งาน FileChannel ของ Java NIO channel ถูกนำมาใช้เพื่อเข้าถึงคุณสมบัติข้อมูลเมตาของไฟล์รวมถึงการสร้างการปรับเปลี่ยนขนาดและอื่น ๆ นอกจากนี้ File Channels ยังมีมัลติเธรดซึ่งทำให้ Java NIO มีประสิทธิภาพมากกว่า Java IO อีกครั้ง

โดยทั่วไปเราสามารถพูดได้ว่า FileChannel เป็นช่องทางที่เชื่อมต่อกับไฟล์ที่คุณสามารถอ่านข้อมูลจากไฟล์และเขียนข้อมูลลงในไฟล์ได้ลักษณะสำคัญอื่น ๆ ของ FileChannel คือไม่สามารถตั้งค่าเป็นโหมดไม่ปิดกั้นได้ และทำงานในโหมดบล็อกเสมอ

เราไม่สามารถรับออบเจ็กต์ช่องไฟล์โดยตรงได้วัตถุของช่องไฟล์จะได้รับโดย -

  • getChannel() - วิธีการใด ๆ ใน FileInputStream, FileOutputStream หรือ RandomAccessFile

  • open() - วิธีการของ File channel ซึ่งโดยค่าเริ่มต้นจะเปิดช่อง

ประเภทอ็อบเจ็กต์ของ File channel ขึ้นอยู่กับประเภทของคลาสที่เรียกจากการสร้างอ็อบเจ็กต์เช่นถ้าอ็อบเจ็กต์ถูกสร้างโดยเรียกเมธอด getchannel ของ FileInputStream จากนั้น File channel จะเปิดขึ้นสำหรับการอ่านและจะโยน 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 ผ่านโปรโตคอลที่เชื่อมต่อน้อยลงโดยค่าเริ่มต้นช่องดาตาแกรมจะบล็อกในขณะที่สามารถใช้ในโหมดที่ไม่ปิดกั้นเพื่อที่จะทำให้มันไม่ปิดกั้นเราสามารถใช้การกำหนดค่าบล็อก ( false) ช่องทาง DataGram สามารถเปิดได้โดยเรียกหนึ่งในวิธีการแบบคงที่ที่มีชื่อว่า open() ซึ่งสามารถใช้ที่อยู่ IP เป็นพารามิเตอร์เพื่อให้สามารถใช้สำหรับการหล่อหลายตัว

ช่องดาต้าแกรมเหมือนกันของ FileChannel ไม่ได้เชื่อมต่อตามค่าเริ่มต้นเพื่อให้เชื่อมต่อได้เราต้องเรียกวิธีการเชื่อมต่อ () อย่างชัดเจนอย่างไรก็ตามไม่จำเป็นต้องเชื่อมต่อช่องดาตาแกรมเพื่อให้ใช้วิธีการส่งและรับในขณะที่ต้องเชื่อมต่อ ในการใช้วิธีการอ่านและเขียนเนื่องจากวิธีการเหล่านั้นไม่ยอมรับหรือส่งคืนที่อยู่ของซ็อกเก็ต

เราสามารถตรวจสอบสถานะการเชื่อมต่อของช่องดาตาแกรมได้โดยเรียกมัน isConnected() เมธอดเมื่อเชื่อมต่อแล้วช่องดาตาแกรมจะยังคงเชื่อมต่อจนกว่าจะถูกตัดการเชื่อมต่อหรือปิดช่องดาต้าแกรมเป็นเธรดที่ปลอดภัยและรองรับมัลติเธรดและการทำงานพร้อมกันพร้อมกัน

วิธีการที่สำคัญของช่องดาต้าแกรม

  • bind(SocketAddress local) - วิธีนี้ใช้เพื่อผูกซ็อกเก็ตของช่องดาตาแกรมเข้ากับโลคัลแอดเดรสซึ่งระบุไว้เป็นพารามิเตอร์ของเมธอดนี้

  • connect(SocketAddress remote) - วิธีนี้ใช้เพื่อเชื่อมต่อซ็อกเก็ตกับที่อยู่ระยะไกล

  • disconnect() - วิธีนี้ใช้เพื่อถอดซ็อกเก็ตไปยังที่อยู่ระยะไกล

  • getRemoteAddress() - วิธีนี้จะส่งกลับที่อยู่ของตำแหน่งระยะไกลที่เชื่อมต่อซ็อกเก็ตของช่อง

  • isConnected() - ดังที่กล่าวไปแล้ววิธีนี้จะคืนสถานะการเชื่อมต่อของช่องดาตาแกรมเช่นว่าเชื่อมต่อหรือไม่

  • open() and open(ProtocolFamily family) - ใช้วิธีการเปิดเพื่อเปิดช่องดาต้าแกรมสำหรับที่อยู่เดียวในขณะที่วิธีการเปิดแบบพารามิเตอร์เปิดช่องสำหรับที่อยู่หลายรายการที่แสดงเป็นตระกูลโปรโตคอล

  • 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() วิธีการจัดเตรียมซ็อกเก็ตที่มีอยู่แล้วใด ๆ ไม่ปรากฏอยู่แล้วช่องซ็อกเก็ตถูกสร้างขึ้นโดยการเรียกใช้วิธีการเปิด แต่ยังไม่ได้เชื่อมต่อเพื่อเชื่อมต่อช่องซ็อกเก็ต connect() จะเรียกวิธีการจุดหนึ่งที่จะกล่าวถึงในที่นี้คือหากไม่ได้เชื่อมต่อช่องสัญญาณและพยายามดำเนินการ I / O ใด ๆ แล้ว NotYetConnectedException จะถูกโยนทิ้งโดยช่องนี้ดังนั้นต้องตรวจสอบให้แน่ใจว่ามีการเชื่อมต่อช่องสัญญาณก่อนดำเนินการ IO ใด ๆ เมื่อเชื่อมต่อช่องแล้วจะยังคงเชื่อมต่ออยู่จนกว่าจะปิดสถานะของช่องซ็อกเก็ตอาจถูกกำหนดโดยการเรียกใช้ isConnected วิธี.

การเชื่อมต่อของช่องซ็อกเก็ตสามารถทำได้โดยการเรียกใช้ finishConnect() วิธีการไม่ว่าการดำเนินการเชื่อมต่อจะอยู่ระหว่างดำเนินการหรือไม่อาจถูกกำหนดโดยการเรียกใช้เมธอด isConnectionPending โดยค่าเริ่มต้นของช่องซ็อกเก็ตรองรับการเชื่อมต่อแบบไม่ปิดกั้นนอกจากนี้ยังรองรับการปิดระบบแบบอะซิงโครนัสซึ่งคล้ายกับการปิดแบบอะซิงโครนัสที่ระบุในคลาส Channel

ช่องซ็อกเก็ตปลอดภัยสำหรับการใช้งานโดยเธรดหลายเธรดพร้อมกัน สนับสนุนการอ่านและการเขียนพร้อมกันแม้ว่าเธรดส่วนใหญ่อาจกำลังอ่านอยู่และเธรดส่วนใหญ่อาจกำลังเขียนในช่วงเวลาใดเวลาหนึ่ง เมธอด connect และ finishConnect จะซิงโครไนซ์ซึ่งกันและกันและความพยายามที่จะเริ่มต้นการดำเนินการอ่านหรือเขียนในขณะที่กำลังดำเนินการเรียกใช้วิธีใดวิธีหนึ่งเหล่านี้จะบล็อกจนกว่าการเรียกใช้จะเสร็จสมบูรณ์

วิธีการสำคัญของ Socket channel

  • bind(SocketAddress local) - วิธีนี้ใช้เพื่อผูกช่องซ็อกเก็ตกับโลคัลแอดเดรสซึ่งจัดเตรียมไว้เป็นพารามิเตอร์ของเมธอดนี้

  • connect(SocketAddress remote) - วิธีนี้ใช้เพื่อเชื่อมต่อซ็อกเก็ตกับที่อยู่ระยะไกล

  • finishConnect() - วิธีนี้ใช้เพื่อเสร็จสิ้นขั้นตอนการเชื่อมต่อช่องซ็อกเก็ต

  • getRemoteAddress() - วิธีนี้จะส่งกลับที่อยู่ของตำแหน่งระยะไกลที่เชื่อมต่อซ็อกเก็ตของช่อง

  • isConnected() - ดังที่ได้กล่าวไปแล้ววิธีนี้จะคืนสถานะการเชื่อมต่อของช่องซ็อกเก็ตเช่นเชื่อมต่อหรือไม่

  • open() and open((SocketAddress remote) - ใช้วิธีการเปิดเพื่อเปิดช่องซ็อกเก็ตโดยไม่มีที่อยู่ที่ระบุในขณะที่วิธีการเปิดที่กำหนดพารามิเตอร์จะเปิดช่องทางสำหรับที่อยู่ระยะไกลที่ระบุและเชื่อมต่อด้วยวิธีการอำนวยความสะดวกนี้ทำงานเหมือนกับการเรียกใช้เมธอด open () โดยเรียกใช้วิธีการเชื่อมต่อเมื่อผลลัพธ์ ซ็อกเก็ตช่องส่งผ่านระยะไกลแล้วส่งคืนช่องนั้น

  • 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() วิธีการจัดเตรียมซ็อกเก็ตที่มีอยู่แล้วใด ๆ ไม่มีอยู่แล้วช่องเสียบเซิร์ฟเวอร์ถูกสร้างขึ้นโดยการเรียกใช้วิธีการเปิด แต่ยังไม่ถูกผูกไว้เพื่อผูกช่องซ็อกเก็ต bind() จะเรียกวิธีการ

จุดหนึ่งที่จะกล่าวถึงในที่นี้คือหากช่องสัญญาณไม่ถูกผูกไว้และพยายามดำเนินการ I / O ใด ๆ แล้ว NotYetBoundException จะถูกโยนทิ้งโดยแชนเนลนี้ดังนั้นเราต้องแน่ใจว่าช่องถูกล้อมรอบก่อนที่จะดำเนินการ IO ใด ๆ

การเชื่อมต่อขาเข้าสำหรับช่องซ็อกเก็ตเซิร์ฟเวอร์จะรับฟังโดยการเรียกใช้เมธอด ServerSocketChannel.accept () เมื่อวิธีการยอมรับ () ส่งคืนจะส่งคืน SocketChannel พร้อมการเชื่อมต่อขาเข้า ดังนั้นวิธีการยอมรับ () จะบล็อกจนกว่าจะมีการเชื่อมต่อขาเข้าหากช่องสัญญาณอยู่ในโหมดไม่ปิดกั้นวิธีการยอมรับจะส่งคืนค่าว่างทันทีหากไม่มีการเชื่อมต่อที่รอดำเนินการ มิฉะนั้นจะบล็อกโดยไม่มีกำหนดจนกว่าจะมีการเชื่อมต่อใหม่หรือเกิดข้อผิดพลาด I / O

ซ็อกเก็ตของช่องใหม่ในตอนแรกไม่ถูกผูกไว้ ต้องถูกผูกไว้กับแอดเดรสที่ระบุผ่านวิธีการผูกของซ็อกเก็ตก่อนจึงจะยอมรับการเชื่อมต่อได้นอกจากนี้ยังสร้างช่องสัญญาณใหม่โดยเรียกใช้เมธอด openServerSocketChannel ของอ็อบเจ็กต์ SelectorProvider ดีฟอลต์ทั้งระบบ

เช่นเดียวกับช่องซ็อกเก็ตเซิร์ฟเวอร์ซ็อกเก็ตช่องสัญญาณสามารถอ่านข้อมูลโดยใช้ read()วิธีการประการแรกบัฟเฟอร์ถูกจัดสรร ข้อมูลที่อ่านจาก ServerSocketChannel จะถูกเก็บไว้ในบัฟเฟอร์ประการที่สองเราเรียกว่าเมธอด ServerSocketChannel.read () และอ่านข้อมูลจาก ServerSocketChannel ลงในบัฟเฟอร์ ค่าจำนวนเต็มของเมธอด read () จะส่งกลับจำนวนไบต์ที่เขียนลงในบัฟเฟอร์

ข้อมูลในทำนองเดียวกันสามารถเขียนไปยังช่องซ็อกเก็ตเซิร์ฟเวอร์โดยใช้ write() วิธีการใช้บัฟเฟอร์เป็นพารามิเตอร์โดยทั่วไปจะใช้วิธีการเขียนใน while loop เนื่องจากจำเป็นต้องทำซ้ำเมธอด write () จนกว่าบัฟเฟอร์จะไม่มีไบต์เพิ่มเติมให้เขียน

วิธีการสำคัญของ Socket channel

  • bind(SocketAddress local) - วิธีนี้ใช้เพื่อผูกช่องซ็อกเก็ตกับโลคัลแอดเดรสซึ่งจัดเตรียมไว้เป็นพารามิเตอร์ของเมธอดนี้

  • accept() - วิธีนี้ใช้เพื่อยอมรับการเชื่อมต่อกับซ็อกเก็ตของช่องนี้

  • connect(SocketAddress remote) - วิธีนี้ใช้เพื่อเชื่อมต่อซ็อกเก็ตกับที่อยู่ระยะไกล

  • finishConnect() - วิธีนี้ใช้เพื่อเสร็จสิ้นขั้นตอนการเชื่อมต่อช่องซ็อกเก็ต

  • getRemoteAddress() - วิธีนี้จะส่งกลับที่อยู่ของตำแหน่งระยะไกลที่เชื่อมต่อซ็อกเก็ตของช่อง

  • isConnected() - ดังที่ได้กล่าวไปแล้ววิธีนี้จะคืนสถานะการเชื่อมต่อของช่องซ็อกเก็ตเช่นเชื่อมต่อหรือไม่

  • open() - ใช้วิธีการเปิดเพื่อเปิดช่องซ็อกเก็ตโดยไม่มีที่อยู่ที่ระบุวิธีการอำนวยความสะดวกนี้ทำงานเหมือนกับการเรียกใช้เมธอด open () เรียกใช้วิธีการเชื่อมต่อกับช่องสัญญาณซ็อกเก็ตเซิร์ฟเวอร์ที่เป็นผลลัพธ์ส่งผ่านระยะไกลแล้วส่งคืนช่องนั้น

  • 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 เป็น API ที่ได้รับการปรับให้เหมาะสมกว่าสำหรับการดำเนินการ IO ข้อมูลเมื่อเทียบกับ IO API แบบเดิมของ Java การสนับสนุนเพิ่มเติมอีกอย่างหนึ่งที่ Java NIO มีให้คือการอ่าน / เขียนข้อมูลจาก / ไปยังบัฟเฟอร์หลายตัวไปยังแชนเนล และการสนับสนุนการเขียนเรียกว่า Scatter and Gather ซึ่งข้อมูลจะกระจัดกระจายไปยังบัฟเฟอร์หลายรายการจากช่องทางเดียวในกรณีที่อ่านข้อมูลในขณะที่รวบรวมข้อมูลจากหลายบัฟเฟอร์ไปยังช่องเดียวในกรณีที่เขียนข้อมูล

เพื่อให้บรรลุการอ่านและเขียนหลายรายการจากแชนเนลมี ScatteringByteChannel และ GatheringByteChannel API ซึ่ง Java NIO จัดเตรียมไว้สำหรับอ่านและเขียนข้อมูลดังที่แสดงในตัวอย่างด้านล่าง

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 เป็น API ที่ได้รับการปรับให้เหมาะสมกว่าสำหรับการดำเนินการ IO ข้อมูลเมื่อเทียบกับ IO API แบบเดิมของ Java การสนับสนุนเพิ่มเติมอีกอย่างหนึ่งที่ Java NIO มีให้คือการอ่าน / เขียนข้อมูลจาก / ไปยังบัฟเฟอร์หลายตัวไปยังแชนเนล และการสนับสนุนการเขียนเรียกว่า Scatter and Gather ซึ่งข้อมูลจะกระจัดกระจายไปยังบัฟเฟอร์หลายรายการจากช่องทางเดียวในกรณีที่อ่านข้อมูลในขณะที่รวบรวมข้อมูลจากหลายบัฟเฟอร์ไปยังช่องเดียวในกรณีที่เขียนข้อมูล

เพื่อให้บรรลุการอ่านและเขียนหลายรายการจากแชนเนลมี ScatteringByteChannel และ GatheringByteChannel API ซึ่ง Java NIO จัดเตรียมไว้สำหรับอ่านและเขียนข้อมูลดังที่แสดงในตัวอย่างด้านล่าง

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 สามารถถือว่าเป็นอ็อบเจ็กต์ธรรมดาซึ่งทำหน้าที่เป็นคอนเทนเนอร์ขนาดคงที่ของชิ้นข้อมูลที่สามารถใช้ในการเขียนข้อมูลไปยังแชนเนลหรืออ่านข้อมูลจากแชนเนลเพื่อให้บัฟเฟอร์ทำหน้าที่เป็นจุดสิ้นสุดของแชนเนล

มีชุดวิธีการที่ทำให้สะดวกในการจัดการกับบล็อกหน่วยความจำเพื่ออ่านและเขียนข้อมูลเข้าและออกจากช่องสัญญาณ

บัฟเฟอร์ทำให้แพ็กเกจ NIO มีประสิทธิภาพมากขึ้นและเร็วขึ้นเมื่อเทียบกับ IO แบบคลาสสิกเนื่องจากในกรณีของข้อมูล IO ถูกจัดการในรูปแบบของสตรีมที่ไม่รองรับการไหลของข้อมูลแบบอะซิงโครนัสและพร้อมกันนอกจากนี้ IO ยังไม่อนุญาตให้เรียกใช้ข้อมูลเป็นกลุ่มหรือกลุ่มไบต์ .

พารามิเตอร์หลักที่กำหนดบัฟเฟอร์ Java NIO สามารถกำหนดเป็น -

  • Capacity - จำนวนข้อมูล / ไบต์สูงสุดที่สามารถจัดเก็บในบัฟเฟอร์ได้ไม่สามารถเปลี่ยนแปลงความจุของบัฟเฟอร์ได้เมื่อบัฟเฟอร์เต็มแล้วควรล้างข้อมูลก่อนที่จะเขียนลงไป

  • Limit - Limit มีความหมายตามโหมดของ Buffer เช่นในโหมดการเขียนของ Buffer Limit เท่ากับความจุซึ่งหมายความว่าข้อมูลสูงสุดที่สามารถเขียนในบัฟเฟอร์ได้ในขณะที่อยู่ในโหมดอ่านของขีด จำกัด บัฟเฟอร์หมายถึงขีด จำกัด ของข้อมูลที่สามารถมีได้ อ่านจากบัฟเฟอร์

  • Position - ชี้ไปยังตำแหน่งปัจจุบันของเคอร์เซอร์ในบัฟเฟอร์ตั้งค่าเริ่มต้นเป็น 0 ในขณะที่สร้างบัฟเฟอร์หรือกล่าวอีกนัยหนึ่งคือดัชนีขององค์ประกอบถัดไปที่จะอ่านหรือเขียนซึ่งได้รับการอัปเดตโดยอัตโนมัติโดย get () และใส่ ( ) วิธีการ

  • Mark - ทำเครื่องหมายบุ๊กมาร์กของตำแหน่งในบัฟเฟอร์เมื่อเมธอด mark () เรียกว่าตำแหน่งปัจจุบันจะถูกบันทึกและเมื่อรีเซ็ต () เรียกว่าตำแหน่งที่ทำเครื่องหมายไว้จะถูกเรียกคืน

ประเภทบัฟเฟอร์

Java NIO บัฟเฟอร์สามารถจำแนกได้ตามรูปแบบต่อไปนี้บนพื้นฐานของประเภทข้อมูลที่บัฟเฟอร์เกี่ยวข้องกับ -

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

วิธีการสำคัญของ Buffer

ดังที่ได้กล่าวไปแล้วว่า Buffer ทำหน้าที่เป็นหน่วยความจำซึ่งจัดเตรียมชุดวิธีการที่ช่วยให้จัดการกับบล็อกหน่วยความจำได้สะดวกยิ่งขึ้นต่อไปนี้เป็นวิธีการสำคัญของ Buffer -

  • allocate(int capacity) - วิธีนี้ใช้เพื่อจัดสรรบัฟเฟอร์ใหม่ที่มีความจุเป็นพารามิเตอร์เมธอด Allocate พ่น IllegalArgumentException ในกรณีที่ความจุที่ส่งผ่านเป็นจำนวนเต็มลบ

  • read() and put() - วิธีการอ่านของช่องใช้ในการเขียนข้อมูลจากช่องสัญญาณไปยังบัฟเฟอร์ในขณะที่ put เป็นวิธีการของบัฟเฟอร์ที่ใช้ในการเขียนข้อมูลในบัฟเฟอร์

  • flip() - วิธีการพลิกจะเปลี่ยนโหมดของ Buffer จากการเขียนเป็นโหมดการอ่านนอกจากนี้ยังตั้งค่าตำแหน่งกลับเป็น 0 และกำหนดขีด จำกัด ว่าตำแหน่งอยู่ที่ใดในขณะที่เขียน

  • write() and get() - วิธีการเขียนของช่องใช้ในการเขียนข้อมูลจากบัฟเฟอร์ไปยังช่องสัญญาณในขณะที่ get เป็นวิธีการของบัฟเฟอร์ที่ใช้ในการอ่านข้อมูลจากบัฟเฟอร์

  • rewind() - ใช้วิธีการกรอกลับเมื่อต้องอ่านซ้ำเนื่องจากตั้งค่าตำแหน่งกลับเป็นศูนย์และไม่เปลี่ยนค่าขีด จำกัด

  • clear() and compact() - ใช้ทั้งสองวิธีที่ชัดเจนและกะทัดรัดเพื่อสร้างบัฟเฟอร์จากโหมดอ่านเป็นเขียนclear() วิธีการทำให้ตำแหน่งเป็นศูนย์และขีด จำกัด เท่ากับความจุในวิธีนี้ข้อมูลในบัฟเฟอร์จะไม่ถูกล้างเฉพาะเครื่องหมายที่ได้รับการเริ่มต้นใหม่

    ในทางกลับกัน 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 Channel หนึ่งช่องหรือมากกว่าและพิจารณาว่าช่องทางใดที่พร้อมสำหรับการทำธุรกรรมข้อมูลเช่นการอ่านหรือการเขียน 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() - วิธีนี้ไม่ได้ปิดกั้นเลย แต่จะส่งคืนทันทีเมื่อมีช่องใดก็ตามที่พร้อม

นอกจากนี้เพื่อที่จะออกจากเธรดที่ถูกบล็อกซึ่งเรียกใช้วิธีการเลือกwakeup() สามารถเรียกใช้วิธีการจากอินสแตนซ์ตัวเลือกหลังจากนั้นเธรดที่รออยู่ภายใน select () จะกลับมาทันที

ในที่สุดเราสามารถปิดตัวเลือกโดยการโทร close() ซึ่งยังทำให้อินสแตนซ์ SelectionKey ทั้งหมดที่ลงทะเบียนกับ Selector นี้ไม่ถูกต้องพร้อมกับการปิดตัวเลือก

ตัวอย่าง

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

การซิงโครไนซ์ข้อมูลจะถูกเก็บไว้ตามลำดับในระหว่างการเขียนและการอ่านข้อมูลเนื่องจากต้องมั่นใจว่าข้อมูลจะต้องอ่านในลำดับเดียวกันกับที่เขียนไปยัง Pipe

ต้องแจ้งให้ทราบว่าเป็นการไหลแบบทิศทางเดียวของข้อมูลใน Pipe กล่าวคือข้อมูลที่เขียนในช่อง Sink เท่านั้นและสามารถอ่านได้จากช่องต้นทางเท่านั้น

ในท่อ Java NIO ถูกกำหนดให้เป็นคลาสนามธรรมโดยมีสามวิธีเป็นหลักซึ่งสองวิธีเป็นนามธรรม

วิธีการของคลาส Pipe

  • open() - วิธีนี้ใช้เพื่อรับอินสแตนซ์ของ Pipe หรือเราสามารถพูดได้ว่าไพพ์ถูกสร้างขึ้นโดยเรียกใช้เมธอดนี้

  • sink() - วิธีนี้จะคืนค่าช่องอ่างของท่อซึ่งใช้ในการเขียนข้อมูลโดยเรียกวิธีการเขียน

  • source() - วิธีนี้จะส่งคืนช่องต้นทางของ 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 NIO ระหว่าง Java เวอร์ชัน 7 และเป็นการแสดงตำแหน่งในระบบไฟล์เฉพาะเนื่องจากพา ธ อินเตอร์เฟสอยู่ในแพ็คเกจ Java NIO ดังนั้นจึงได้รับชื่อที่ถูกต้องเป็น java .nio.file.Path.

โดยทั่วไปเส้นทางของเอนทิตีอาจมีสองประเภทประเภทหนึ่งคือพา ธ สัมบูรณ์และอีกประเภทหนึ่งเป็นพา ธ สัมพัทธ์เนื่องจากชื่อของทั้งสองพา ธ แสดงให้เห็นว่าพา ธ สัมบูรณ์คือที่อยู่ที่ตั้งจากรูทไปยังเอนทิตีที่ระบุตำแหน่งในขณะที่พา ธ สัมพัทธ์เป็นที่อยู่ที่ตั้ง ซึ่งสัมพันธ์กับเส้นทางอื่น ๆ Path ใช้ตัวคั่นในคำจำกัดความเป็น "\" สำหรับ Windows และ "/" สำหรับระบบปฏิบัติการ unix

ในการรับอินสแตนซ์ของ Path เราสามารถใช้วิธีการคงที่ของคลาส java.nio.file.Paths get()เมธอดนี้จะแปลงสตริงพา ธ หรือลำดับของสตริงที่เมื่อรวมเป็นสตริงพา ธ ไปยังอินสแตนซ์พา ธ วิธีนี้ยังแสดงรันไทม์ InvalidPathException หากอาร์กิวเมนต์ที่ส่งผ่านมีอักขระที่ไม่ถูกต้อง

ดังที่ได้กล่าวไว้ข้างต้นพา ธ สัมบูรณ์ถูกดึงโดยการส่งผ่านอิลิเมนต์รูทและรายการไดเร็กทอรีทั้งหมดที่จำเป็นในการค้นหาไฟล์ในขณะที่พา ธ สัมพัทธ์สามารถดึงข้อมูลได้โดยการรวมพา ธ ฐานกับพา ธ สัมพัทธ์การดึงข้อมูลทั้งสองพา ธ จะแสดงในตัวอย่างต่อไปนี้

ตัวอย่าง

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);
   }
}

จนถึงตอนนี้เรารู้แล้วว่าอินเทอร์เฟซพา ธ คืออะไรทำไมเราถึงต้องการสิ่งนั้นและเราจะเข้าถึงมันได้อย่างไรตอนนี้เราจะรู้แล้วว่าอะไรคือวิธีการสำคัญที่อินเทอร์เฟซ Path ให้เรา

วิธีการสำคัญของ Path Interface

  • getFileName() - ส่งคืนระบบไฟล์ที่สร้างอ็อบเจ็กต์นี้

  • getName() - ส่งคืนองค์ประกอบชื่อของเส้นทางนี้เป็นวัตถุ Path

  • getNameCount() - ส่งคืนจำนวนองค์ประกอบชื่อในเส้นทาง

  • subpath() - ส่งคืนเส้นทางสัมพัทธ์ที่เป็นลำดับต่อมาขององค์ประกอบชื่อของเส้นทางนี้

  • getParent() - ส่งคืนพา ธ พาเรนต์หรือค่าว่างหากพา ธ นี้ไม่มีพาเรนต์

  • getRoot() - ส่งคืนองค์ประกอบรากของเส้นทางนี้เป็นวัตถุเส้นทางหรือค่าว่างหากเส้นทางนี้ไม่มีองค์ประกอบราก

  • toAbsolutePath() - ส่งคืนอ็อบเจ็กต์ Path ที่แสดงถึงพา ธ สัมบูรณ์ของพา ธ นี้

  • toRealPath() - ส่งคืนเส้นทางจริงของไฟล์ที่มีอยู่

  • toFile() - ส่งคืนอ็อบเจ็กต์ไฟล์ที่แสดงเส้นทางนี้

  • normalize() - ส่งคืนเส้นทางที่เป็นเส้นทางนี้โดยตัดองค์ประกอบชื่อที่ซ้ำซ้อนออกไป

  • compareTo(Path other) - เปรียบเทียบเส้นทางนามธรรมสองทางตามศัพท์วิธีนี้จะคืนค่าเป็นศูนย์หากอาร์กิวเมนต์เท่ากับเส้นทางนี้ค่าน้อยกว่าศูนย์หากเส้นทางนี้มีศัพท์น้อยกว่าอาร์กิวเมนต์หรือค่าที่มากกว่าศูนย์หากเส้นทางนี้มีค่ามากกว่าอาร์กิวเมนต์ในเชิงศัพท์ .

  • endsWith(Path other) - ทดสอบว่าเส้นทางนี้ลงท้ายด้วยเส้นทางที่กำหนดหรือไม่หากเส้นทางที่กำหนดมีองค์ประกอบ N และไม่มีองค์ประกอบรูทและเส้นทางนี้มีองค์ประกอบ N หรือมากกว่าเส้นทางนี้จะสิ้นสุดด้วยเส้นทางที่กำหนดหากองค์ประกอบ N สุดท้ายของแต่ละเส้นทาง เริ่มต้นที่องค์ประกอบที่ไกลที่สุดจากรากมีค่าเท่ากัน

  • endsWith(String other) - ทดสอบว่าเส้นทางนี้ลงท้ายด้วย Path หรือไม่ซึ่งสร้างขึ้นโดยการแปลงสตริงพา ธ ที่กำหนดในลักษณะที่ระบุโดยเมธอด endWith (Path)

ตัวอย่าง

ตัวอย่างต่อไปนี้แสดงให้เห็นถึงวิธีการต่างๆของอินเทอร์เฟซ 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 มี API ยูทิลิตี้อีกหนึ่งตัวที่มีชื่อว่าไฟล์ซึ่งโดยทั่วไปจะใช้สำหรับการจัดการไฟล์และไดเร็กทอรีโดยใช้วิธีการแบบคงที่ซึ่งส่วนใหญ่ทำงานบนออบเจ็กต์ Path

ดังที่กล่าวไว้ในบทช่วยสอน Path ว่าอินเทอร์เฟซ Path ถูกนำมาใช้ในแพ็คเกจ Java NIO ระหว่างเวอร์ชัน Java 7 ในแพ็คเกจไฟล์ดังนั้นบทช่วยสอนนี้จึงใช้สำหรับแพ็คเกจไฟล์เดียวกัน

คลาสนี้ประกอบด้วยเมธอดแบบคงที่ที่ดำเนินการกับไฟล์ไดเร็กทอรีหรือไฟล์ประเภทอื่น ๆ เท่านั้นในกรณีส่วนใหญ่เมธอดที่กำหนดไว้ที่นี่จะมอบสิทธิ์ให้กับผู้ให้บริการระบบไฟล์ที่เกี่ยวข้องเพื่อดำเนินการกับไฟล์

มีวิธีการมากมายที่กำหนดไว้ในคลาสไฟล์ซึ่งสามารถอ่านได้จากเอกสาร Java ในบทช่วยสอนนี้เราพยายามที่จะครอบคลุมวิธีการที่สำคัญบางอย่างจากวิธีการทั้งหมดของคลาส Java NIO Files

วิธีการที่สำคัญของคลาสไฟล์

ต่อไปนี้เป็นวิธีการสำคัญที่กำหนดไว้ในคลาส Java NIO Files

  • createFile(Path filePath, FileAttribute attrs) - คลาสไฟล์จัดเตรียมวิธีการนี้เพื่อสร้างไฟล์โดยใช้ 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) - วิธีนี้ใช้เพื่อคัดลอกไบต์ทั้งหมดจากอินพุตสตรีมที่ระบุไปยังไฟล์เป้าหมายที่ระบุและส่งคืนจำนวนไบต์ที่อ่านหรือเขียนเป็นค่ายาว 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) - วิธีนี้ใช้เพื่อตรวจสอบว่าไฟล์มีอยู่ในพา ธ ที่ระบุหรือไม่และหากมีไฟล์อยู่ไฟล์นั้นจะส่งคืนจริงหรือมิฉะนั้นจะส่งคืนเท็จ

  • 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 รองรับการทำงานพร้อมกันและมัลติเธรดซึ่งช่วยให้เราจัดการกับแชนเนลต่างๆพร้อมกันได้ในเวลาเดียวกันดังนั้น API ที่รับผิดชอบในสิ่งนี้ในแพ็คเกจ Java NIO คือ AsynchronousFileChannel ซึ่งกำหนดไว้ภายใต้แพ็คเกจช่อง NIO ดังนั้นชื่อที่ถูกต้อง สำหรับ AsynchronousFileChannel คือ java.nio.channels.AsynchronousFileChannel.

AsynchronousFileChannel คล้ายกับ FileChannel ของ NIO ยกเว้นว่าแชนเนลนี้เปิดใช้งานไฟล์เพื่อดำเนินการแบบอะซิงโครนัสซึ่งแตกต่างจากการดำเนินการ I / O แบบซิงโครนัสที่เธรดเข้าสู่การดำเนินการและรอจนกว่าการร้องขอจะเสร็จสมบูรณ์ดังนั้นแชนเนลแบบอะซิงโครนัสจึงปลอดภัยสำหรับการใช้งาน โดยหลายเธรดพร้อมกัน

ในแบบอะซิงโครนัสคำร้องขอจะถูกส่งผ่านเธรดไปยังเคอร์เนลของระบบปฏิบัติการเพื่อให้มันเสร็จสิ้นในขณะที่เธรดยังคงประมวลผลงานอื่นเมื่องานของเคอร์เนลเสร็จสิ้นมันจะส่งสัญญาณไปยังเธรดจากนั้นเธรดจะรับสัญญาณและขัดจังหวะงานปัจจุบันและประมวลผล งาน I / O ตามต้องการ

เพื่อให้บรรลุการทำงานพร้อมกันช่องทางนี้มีสองแนวทางซึ่งรวมถึงวิธีหนึ่งที่ส่งกลับ a java.util.concurrent.Future object และอื่น ๆ คือการส่งผ่านไปยังการดำเนินการวัตถุประเภท java.nio.channels.CompletionHandler.

เราจะเข้าใจทั้งสองแนวทางด้วยความช่วยเหลือของตัวอย่างทีละตัวอย่าง

  • Future Object - ในอินสแตนซ์ของอินเทอร์เฟซในอนาคตจะถูกส่งคืนจากช่องสัญญาณในอินเทอร์เฟซในอนาคตมี get() วิธีการที่ส่งคืนสถานะของการดำเนินการที่ได้รับการจัดการแบบอะซิงโครนัสบนพื้นฐานของการตัดสินใจดำเนินการงานอื่น ๆ ต่อไปนอกจากนี้เรายังสามารถตรวจสอบว่างานเสร็จสมบูรณ์หรือไม่โดยเรียก isDone วิธี.

ตัวอย่าง

ตัวอย่างต่อไปนี้แสดงวิธีการใช้วัตถุในอนาคตและงานแบบอะซิงโครนัส

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 สำหรับทุกอักขระจะมีหน่วยรหัส Unicode ที่กำหนดไว้อย่างดีซึ่ง JVM จัดการภายในดังนั้นแพ็คเกจ Java NIO จึงกำหนดคลาสนามธรรมที่มีชื่อว่า Charset ซึ่งส่วนใหญ่จะใช้สำหรับการเข้ารหัสและถอดรหัสชุดอักขระและ UNICODE

ชุดอักขระมาตรฐาน

Charset ที่รองรับใน java มีให้ด้านล่าง

  • US-ASCII - อักขระ ASCII เจ็ดบิต

  • ISO-8859-1 - อักษรละติน ISO

  • UTF-8 - นี่คือรูปแบบการแปลง UCS 8 บิต

  • UTF-16BE - นี่คือรูปแบบการแปลง UCS 16 บิตพร้อมคำสั่ง endian byte ขนาดใหญ่

  • UTF-16LE - นี่คือการแปลง UCS 16 บิตพร้อมคำสั่ง endian byte เล็กน้อย

  • UTF-16 - รูปแบบการแปลง UCS 16 บิต

วิธีการที่สำคัญของคลาส Charset

  • forName() - วิธีนี้สร้างออบเจ็กต์ชุดอักขระสำหรับชื่อชุดอักขระที่กำหนดชื่อสามารถเป็นนามแฝงหรือนามแฝง

  • displayName() - วิธีนี้ส่งคืนชื่อมาตรฐานของชุดอักขระที่กำหนด

  • canEncode() - วิธีนี้จะตรวจสอบว่าชุดอักขระที่ระบุรองรับการเข้ารหัสหรือไม่

  • decode() - วิธีนี้จะถอดรหัสสตริงของชุดอักขระที่กำหนดให้เป็น charbuffer ของ Unicode charset

  • encode() - วิธีนี้เข้ารหัส charbuffer ของ unicode charset ลงในไบต์บัฟเฟอร์ของชุดอักขระที่กำหนด

ตัวอย่าง

ตัวอย่างต่อไปนี้แสดงให้เห็นถึงวิธีการที่สำคัญของคลาส 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 จัดเตรียม API ที่เรียกว่า FileLock อีกครั้งซึ่งใช้เพื่อล็อกไฟล์ทั้งหมดหรือบางส่วนของไฟล์ดังนั้นไฟล์หรือส่วนนั้นจะไม่ถูกแชร์หรือเข้าถึงได้

ในการจัดหาหรือใช้การล็อกดังกล่าวเราต้องใช้ 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 Class

  • 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.