NIO/NIO2
★Event
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
Path path = Paths.get("/home/work");
System.out.println("Watching ...");
try {
WatchService watcher = path.getFileSystem().newWatchService();
path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
WatchKey watckKey = watcher.take();
List<WatchEvent<?>> events = watckKey.pollEvents();
for (WatchEvent<?> event : events) {
System.out.println("File created:" + event.context().toString());
}
} catch (Exception e) {
...
}
★Charset
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
String str = "...";
Charset charset = Charset.forName("ISO-8859-1");
CharsetEncoder encoder = charset.newEncoder();
ByteBuffer buf = encoder.encode(CharBuffer.wrap(str));
byte[] byteArray = new byte[100];
int bytesRead = fileInputStream.read(byteArray);
↓
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
int bytesRead = fileChannel.read(byteBuffer);
ByteBuffer header = ByteBuffer.allocate (50);
ByteBuffer footer = ByteBuffer.allocate (50);
ByteBuffer[] buffers = { header, footer };
fileChannel.read(buffers);
★Memory mapping
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
static int MEM_MAP_SIZE = 20 * 1024 * 1024;
static String FILE_PATH = "...";
try (RandomAccessFile memoryMappedFile
= new RandomAccessFile(FILE_PATH, "rw")) {
MappedByteBuffer out = memoryMappedFile.getChannel().map(
FileChannel.MapMode.READ_WRITE, 0, MEM_MAP_SIZE);
// Write
for (int i = 0; i < MEM_MAP_SIZE; i++) {
out.put((byte) 'A');
}
// Read
for (int i = 0; i < 50; i++) {
System.out.print((char) out.get(i));
}
}
★SelectorとChannel
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class MultiPortEcho {
private int ports[];
private ByteBuffer echoBuffer = ByteBuffer.allocate(1024);
public MultiPortEcho(int ports[]) throws IOException {
this.ports = ports;
init();
}
private void init() throws IOException {
Selector selector = Selector.open();
for (int i = 0; i < ports.length; i++) {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ServerSocket ss = ssc.socket();
InetSocketAddress address = new InetSocketAddress(ports[i]);
ss.bind(address);
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Listening on " + ports[i]);
}
while (true) {
selector.select();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectedKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey) it.next();
if ((key.readyOps() & SelectionKey.OP_ACCEPT)
== SelectionKey.OP_ACCEPT) {
ServerSocketChannel ssc
= (ServerSocketChannel) key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
it.remove();
System.out.println("Connection from " + sc);
} else if ((key.readyOps() & SelectionKey.OP_READ)
== SelectionKey.OP_READ) {
SocketChannel sc = (SocketChannel) key.channel();
int readBytes = 0;
while (true) {
echoBuffer.clear();
int numberOfBytes = sc.read(echoBuffer);
if (numberOfBytes <= 0) {
break;
}
echoBuffer.flip();
sc.write(echoBuffer);
readBytes += numberOfBytes;
}
System.out.println("Read " + readBytes + " from " + sc);
it.remove();
}
}
}
}
public static void main(String args[]) throws Exception {
if (args.length <= 0) {
System.err.println("Usage: java MultiPortEcho port [port ...]");
System.exit(1);
}
int ports[] = new int[args.length];
for (int i = 0; i < args.length; i++) {
ports[i] = Integer.parseInt(args[i]);
}
new MultiPortEcho(ports);
}
}
★Direct Buffer vs Heap Buffer
・Direct Buffer
処理流れ:
ネットワーク・ファイルシステム ⇒ 自作Direct Buffer ⇒ ネットワーク・ファイルシステム
メリット:
データコピー処理を減らすため、性能アップ
デメリット:
new・destroyのコストが高い
利用場面:
ビッグファイルを読み込む・ダウンロードする
重複データの再利用
・Heap Buffer
処理流れ:
ネットワーク・ファイルシステム ⇒ 一時Direct Buffer ⇒ 自作Heap Buffer ⇒ 一時Direct Buffer ⇒ ネットワーク・ファイルシステム
★bufferの状態
0 <= position <= limit <= capacity
flipメソッド(write処理前に呼ぶべき)
limit = position;
position = 0;
clearメソッド(read処理前に呼ぶべき)
limit = capacity
position = 0;