IO vs. NIO

IO Decorator PatternとAdapter Patternに基づく

bytes

Stream ⇔ Stream Streamは単方向

NIO Reactor Patternに基づく

buffer

Channel ⇔ Channel Channelは双方向

・Reactor Pattern イベント発生源が複数

・Observer Pattern イベント発生源が単一

★ビッグファイルの書き込み・読み込みの比較

・Stream Write

try (DataOutputStream dos = new DataOutputStream(

new BufferedOutputStream(

new FileOutputStream(FILE_PATH))) ) {

for (int i = 0; i < INT_SIZE; i++) {

dos.writeInt(i);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

・Memory-mapped File Write 性能アップ

try (FileChannel fc = new RandomAccessFile(FILE_PATH, "rw").getChannel()) {

//fc = new FileOutputStream(FILE_PATH).getChannel();

↑NonReadableChannelExceptionが発生。

IntBuffer ib =

fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();

for(int i = 0; i < INT_SIZE; i++) {

ib.put(i);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

・Stream Read

try (DataInputStream dis = new DataInputStream(

new BufferedInputStream(

new FileInputStream(FILE_PATH))) ) {

//書き方1

for (int i = 0; i < INT_SIZE; i++) {

dis.readInt();

}

//書き方2

int bytes;

while( (bytes = dis.read()) != -1 ){

System.out.println(bytes);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

・Memory-mapped File Read 性能アップ

try (FileChannel fc = new RandomAccessFile(FILE_PATH, "rw").getChannel()) {

//fc = new FileInputStream(FILE_PATH).getChannel(); //別の書き方

IntBuffer ib =

fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).asIntBuffer();

while(ib.hasRemaining()) {

int num = ib.get();

System.out.println(num);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

★ファイルシステムの比較

public boolean writeFile(String filePath, byte[] bytes){

File file = new File(filePath);

try(OutputStream outputStream = new FileOutputStream(file)) {

outputStream.write(bytes);

} catch (FileNotFoundException ex){

...

} catch(IOException ex){

...

}

return true;

}

public boolean writeFile(String filePath, byte[] bytes){

FileSystem fs = FileSystems.getDefault();

Path path = fs.getPath(filePath);

try {

Files.write(path, bytes, StandardOpenOption.CREATE_NEW);

} catch (IOException ex) {

...

}

return true;

}

public byte[] readFile(String filePath){

File file = new File(filePath);

if(!file.exists()){

return null;

}

int length = (int)file.length();

byte[] bytes = new byte[length];

try(InputStream is = new FileInputStream(file)) {

is.read(bytes);

} catch (FileNotFoundException ex) {

...

} catch(IOException ex){

...

}

return bytes;

}

public byte[] readFile(String filePath){

FileSystem fs = FileSystems.getDefault();

Path path = fs.getPath(filePath);

if(!Files.exists(path)){

return null;

}

byte[] bytes = null;

try {

bytes = Files.readAllBytes(path);

} catch (IOException ex) {

...

}

return bytes;

}

★ファイルコピーの比較

読み込み専用のFileChannel

FileInputStream inStream = new FileInputStream(FILE_PATH);

FIleChannel inChannel = inStream.getChannel();

書き込み専用のFileChannel

FileOutputStream outStream = new FileOutputStream(FILE_PATH);

FIleChannel outChannel = outStream.getChannel();

読み書き可能なFileChannel

RandomAccessFile rwFile = new RandomAccessFile(FILE_PATH, "rw");

FIleChannel rwChannel = rwFile.getChannel();

IOの場合

try (

Reader reader = new BufferedReader(new FileReader("D:\\in.txt"));

Writer writer = new BufferedWriter(new FileWriter("D:\\out.txt"))

) {

while (true) {

char[] buf = new char[4 * 1024];

int r = reader.read(buf);

if (r == -1) {

break;

}

writer.write(buf);

}

writer.flush();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

NIOの場合 性能アップ

try (

FileChannel inChannel = new FileInputStream("D:\\in.txt").getChannel();

FileChannel outChannel = new FileOutputStream("D:\\out.txt").getChannel()

) {

// 書き方1

ByteBuffer buf = ByteBuffer.allocate( 4 * 1024 ); //Heap Buffer

//ByteBuffer buf = ByteBuffer.allocateDirect( 4 * 1024 ); //Direct Buffer

while (true) {

buf.clear();

int r = inChannel.read(buf);

if (r == -1) {

break;

}

buf.flip();

outChannel.write(buf);

}

// 書き方2

inChannel.transferTo(0, inChannel.size(), outChannel); // Bigサイズに向かない

// 書き方3

int maxCount = 4 * 1024;

long size = inChannel.size();

long position = 0;

while ( position < size ){

position += inChannel.transferTo( position, maxCount, outChannel );

}

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

32MB 32 * 1024 * 1024

32KB 32 * 1024