Java nio (ii) basic memory management File Locking Socket server client communication, niosocket
NIO Introduction
There are four nio packages:
1. Buffer package: java. nio version: Java SE1.4
2. Channel package: java. nio. channels version: Java SE1.4
3. Character Set package: java. nio. charset version: Java SE1.4
4. file Processing Package: java nio. file version: Java SE1.7
A) inbound and outbound channel data must go through the buffer zone.
B) the channel is a new concept of native I/O abstraction. It is like connecting the data pipelines at both ends for data interaction.
C) Character Set package: a collection of most character sets that process conversion between byte characters
D) file package: Process directories and files. Include the File class function in io, which is more powerful than above and has the meaning of name equivalence.
1. Buffer
All basic data types have corresponding buffers (excluding Boolean), but bytes are the basic data types used by the operating system and its I/O devices, therefore, the only buffer that interacts with the channel is ByteBuffer. CharBuffer will be used for character set conversion later
Buffer Basics
There are several flag bits used to operate the Buffer Zone
Capacity: The buffer size (byte). Read and Write values remain unchanged.
Position: the location where the next byte is read and written. Note: position is always less than limit.
Limit: when writing (limit = capacity), when reading (position of the last write)
Mark: the initial value is-1. You can call reset () to return to the mark position.
Public static void main (String [] args) {// Initialization Method 1: directly use the encapsulated array as the buffer, and no space is allocated. ByteBuffer temp = ByteBuffer. wrap ("byte array ". getBytes (); // initialize a buffer with a capacity of 10. Note: during initialization, the write status is ByteBuffer bb = ByteBuffer. allocate (10); bb. capacity (); // capacity: 10bb. position (); // position: 0bb. limit (); // limit: 10 // write byte bb. put ("345 ". getBytes (); // position = 3 // reverse execution position = 0; mark =-1bb. rewind (); // write byte bb. put ("012 ". getBytes (); // position = 3 // mark (mark) bb. mark (); // mark = position = 3; // continue to write bb. put ("678 ". getBytes (); // position = 6 // Reset: Return to the mark bb. reset (); // position = mark = 3 // continue to write bb. Put ("345 ". getBytes (); // position = 6 // switch to the write status and call the following method: bb. flip (); // run: limit = position = 6; position = 0; mark =-1; // position = 0 to read data from the beginning. Because bb contains only 6 bytes, the read limit is set to 6 // the remaining number of bytes that can be read. bb. remaining (); while (bb. hasRemaining () {// is there any unread byte? // read 1 byte bb. get ();} // position = 6 // continue to read from the beginning. rewind (); // position = 0 // set position = 3bb. position (3); System. out. println (char) bb. get (); // output 3 // get () containing the index. The position value is not changed. out. println (char) bb. get (1); // output 1 // position = 4 // create a read-only buffer. The two buffers share the data element ByteBuffer readOnly = bb. asReadOnlyBuffer (); // copy a buffer, Two buffer shared data elements, with their respective locations and tags. // If the original buffer is read-only or direct, the new buffer will inherit these attributes ByteBuffer duplicate = bb. duplicate (); // create a new buffer starting from the current position of the original buffer // its capacity is the number of remaining elements of the original buffer (limit-position) ByteBuffer slice = bb. slice (); // checks whether the buffer is read-only. isReadOnly (); // true // switch to the write status bb. clear (); // position = 0; limit = 10}
Indirect Buffer:
ByteBuffer bb = ByteBuffer. allocate (1024); CharBuffer cb = CharBuffer. allocate (1024); // The modification to the buffer will affect the array ByteBuffer bbw = ByteBuffer. wrap ("wrap ". getBytes (); CharBuffer cbw = CharBuffer. wrap ("aaa"); // you can create other basic types that are not boolean.
Direct Buffer:
// Create a direct buffer, only the byte buffer has this factory method ByteBuffer bb = ByteBuffer. allocateDirect (1024); // construct a channel FileChannel fc = new FileInputStream (new File ("File path ")). getChannel (); // read data from the disk to the direct buffer zone fc. read (bb );
Memory ing file:
Test the usage of three buffer memories.
Channel
FileChannel
Public static void main (String [] args) throws IOException {File file = new File ("D: \ TEXT.txt "); // only the read channel FileChannel readCh = new FileInputStream (file ). getChannel (); // can only be used to write FileChannel writCh = new FileOutputStream (file ). getChannel (); // The FileChannel rwCh = new RandomAccessFile (file, "rw") that can be read or written "). getChannel (); // a new initialization method is provided in Java SE1.7. // Path = Paths will be introduced later. get ("D:", "TEXT.txt"); // The FileChannel nReadCh = FileChannel that can only be used for reading. open (path, StandardOpenOption. READ); // it can only be used to write the channel FileChannel nWriteCh = FileChannel. open (path, StandardOpenOption. WRITE); // a channel that can be read or written. The second parameter can be an array of FileChannel nReadWrite = FileChannel. open (path, StandardOpenOption. WRITE, StandardOpenOption. READ );}
5. Basic Methods
Public static void main (String [] args) throws IOException {File file = new File ("D: \ t2.txt"); // if the File is not saved, an empty file FileChannel rw = new RandomAccessFile (file, "rw") will be created directly "). getChannel (); // initialize a buffer ByteBuffer bb = ByteBuffer. wrap ("temp ". getBytes (); // note that the channel also has a read/write location, it is obtained from the underlying file descriptor //, which means that an object's update to this position can be seen by another object rw. position (); // write data to the channel while (bb. hasRemaining () {// position at the end. write will automatically resize the file rw. write ( Bb);} // clear the buffer bb first. clear (); // The read/Write File Location of the channel is at the end and is set to 0 rw. position (0); // read data to the buffer rw. read (bb); // The size (in bytes) of the channel associated file rw. size (); // truncate the file. Only the first three bytes are retained. truncate (3); // all modern file systems cache data and delay disk file updates to improve performance. Calling the force () method requires that all the pending changes to the file be synchronized to the disk immediately. The/boolean parameter sets whether the metadata should be written to the disk. // metadata: indicates the information such as the file owner, access permission, and last modification time. // metadata synchronization requires the operating system to perform at least one I/O operation. To improve performance, metadata can be not synchronized, at the same time, it will not sacrifice data integrity rw. force (false); // close the channel if (rw. isOpen () rw. close ();}
6. Channel-to-Channel Transmission
Public abstract class FileChannel extends actchannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel {// only some APIs are listed here. public abstract long transferTo (long position, long count, WritableByteChannel target) public abstract long transferFrom (ReadableByteChannel src, long position, long count )}
The transferTo () and transferFrom () methods allow one channel to be connected to another, instead of passing data through an intermediate buffer. Only the FileChannel class has these two methods, so one of the channels in Channel-to-Channel transmission must be FileChannel. Data cannot be directly transmitted between socket channels, but the socket channel implements the WritableByteChannel and ReadableByteChannel interfaces. Therefore, the file content can be transmitted to a socket channel using the transferTo () method, alternatively, you can use the transferFrom () method to directly read data from a socket channel to a file.
Public static void main (String [] args) throws IOException {// connect two channels for data transmission. File inFile = new File ("D:" + File. separator + "temp.png"); File outFile = new File ("E:" + File. separator + "temp.png"); FileChannel in = new FileInputStream (inFile ). getChannel (); FileChannel out = new FileOutputStream (outFile ). getChannel (); // copy the inFile data to outFileout. transferFrom (in, 0, in. size (); in. transferTo (0, in. size (), out );}
7. The channel can write data to the buffer array and fill each buffer in sequence until all the buffers are full or no data is readable. Clustered write is also completed in a similar way. The data is obtained from each buffer in the list and sent to the channel in sequence, just as the data is written in sequence.
File lock
Socket Channel
Both SocketChannel and mongoramchannel implement interfaces for reading and writing, while ServerSocketChannel does not. ServerSocketChannel is only responsible for listening for incoming connections and creating SocketChannel objects.
The operating system must be used to select readiness. One of the most important functions of the operating system is to process I/O requests and notify each thread that their data is ready. The selector class provides this abstraction. Using Java code, you can request the underlying operating system to provide the ready selection service in a portable manner.
You can use only one thread to monitor the readiness of the channel and use a coordinated working thread pool to process the received data. According to the deployment conditions, the thread pool size can be adjusted (or dynamically adjusted by itself ).
Package I. io. socket; import java. io. IOException; import java.net. inetSocketAddress; import java. nio. byteBuffer; import java. nio. charBuffer; import java. nio. channels. closedChannelException; import java. nio. channels. selectionKey; import java. nio. channels. selector; import java. nio. channels. serverSocketChannel; import java. nio. channels. socketChannel; import java. nio. charset. charset; import java. util. iterator; public class SelectSockets {/*** server side */public static class ServerSocketListen implements Runnable {@ Overridepublic void run () {try {server (1234 );} catch (Exception e) {e. printStackTrace () ;}} public void server (int... port) throws Exception {// initialize a Selector selector = Selector. open (); // listen to multiple ports for (int pt: port) {System. out. println ("Listening on port" + pt); // initialize a server socket channel ServerSocketChannel serverChannel = ServerSocketChannel. open (); // set the serverChannel listening port of the port server channel. bind (new InetSocketAddress (pt); // sets the non-blocking mode serverChannel of the listener socket. configureBlocking (false); // register the ServerSocketChannel selector serverChannel. register (selector, SelectionKey. OP_ACCEPT);} while (true) {// This may be blocked for a long time. After returning it, select the set containing the prepared channel key if (selector. select () = 0) continue; // process the prepared channel handleChannel (selector );}} /*** register the business to Selector that is of interest to the channel and channel */protected void handleChannel (selector Selector) throws Exception {// Iterator <SelectionKey> it = selector. selectedKeys (). iterator (); while (it. hasNext () {SelectionKey key = it. next (); // new connection if (key. isAcceptable () {// obtain the server channel ServerSocketChannel server = (ServerSocketChannel) key. channel (); SocketChannel channel = server. accept (); // set the channel to be non-blocking channel. configureBlocking (false); channel. register (selector, SelectionKey. OP_READ);} // if (key. isReadable () {readDataFromSocket (key);} it. remove () ;}/ *** read Channel Data */protected void readDataFromSocket (SelectionKey key) throws Exception {SocketChannel socketChannel = (SocketChannel) key. channel (); // initialize the buffer ByteBuffer buffer = ByteBuffer. allocate (1024); // read data to the buffer while (socketChannel. read (buffer)> 0) {// switch to buffer in read mode. flip (); // open the buffer CharBuffer cb = buffer in the character view. asCharBuffer (); StringBuilder messClient = new StringBuilder (); while (cb. hasRemaining () {messClient. append (cb. get ();} System. err. println ("2-the server receives client data:" + messClient. toString (); buffer. clear ();} // write back System. err. println ("3-feedback data to the client: go"); Charset charset = Charset. forName ("gbk"); socketChannel. write (charset. encode ("OK");}/*** client class */public static class ClientSocketListen {public void client () throws IOException {Selector selector = Selector. open (); SocketChannel SC = SocketChannel. open (); SC. configureBlocking (false); SC. register (selector, SelectionKey. OP_CONNECT); SC. connect (new InetSocketAddress (1234); while (true) {if (selector. select () = 0) continue; handleChannel (selector) ;}} protected void handleChannel (Selector selector) throws ClosedChannelException, IOException {Iterator <SelectionKey> it = selector. selectedKeys (). iterator (); while (it. hasNext () {SelectionKey key = it. next (); int op = key. readyOps (); SocketChannel channel = (SocketChannel) key. channel (); // listen to this channel, used to receive feedback from the server if (op & SelectionKey. OP_CONNECT) = SelectionKey. OP_CONNECT) {if (channel. finishConnect () {// a selector can only have one instance of the current channel, // channel. register (selector, SelectionKey. OP_READ); key. interestOps (SelectionKey. OP_READ); System. out. println ("1-the client sends data to the server: go"); ByteBuffer bb = ByteBuffer. allocate (8); bb. asCharBuffer (). put ("4 characters"); channel. write (bb); bb. clear () ;}// receives the server-side feedback if (op & SelectionKey. OP_READ) = SelectionKey. OP_READ) {ByteBuffer bb = ByteBuffer. allocate (1, 1024); while (channel. read (bb)> 0) {bb. flip (); Charset charset = Charset. forName ("gbk"); System. out. println ("4-client receives server feedback data:" + charset. decode (bb);} it. remove () ;}} public static void main (String [] argv) throws Exception {// use a Thread to start the server side new Thread (new SelectSockets. serverSocketListen ()). start (); // The client calls new SelectSockets. clientSocketListen (). client ();}}
The ingress ramchannel is UDP-oriented. The ingress ramchannel object can act as either a server (listener) or a client (sender). It is different from the SocketChannel (which is useful only when a connection is required and can only be connected once ), the initramchannel object can be connected or disconnected at any number of times. Each connection can be connected to a different remote address. You can call the disconnect () method to configure a channel so that it can receive data from any remote address allowed by the security manager (if installed) or send data to these addresses again.
Lists data packets used.
Programs can withstand data loss or disorder.
You do not need to know whether or not the package you sent has been received.
Data throughput is more important than reliability.
You must send data to multiple recipients (multicast or broadcast) at the same time ).
Package metaphor is more suitable for Handy tasks than stream metaphor.