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