referee:Java Programming Tutorial Advanced Input & Output (I/O)

JDK 1.4+ introduced the so-called New I/O int java.nio package and its auxiliary packages to support high performance and intensive I/O operations. NIO is meant to complement the existing stanard java.io, not as a replacement.

Direct vs Indirect Buffers: 

A buffer can be direct or indirect. For a direct buffer, "the JVM will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer's content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system's native I/O operations." In other words, direct buffer is more efficient.

For byte buffer, you can allocate a direct ByteBuffer via the allocateDirect(int capacity) method. For other buffers (char, short, int, long, float, double), you need to first allocate a ByteBuffer, and then create a view via methods such as asFloatBuffer(). As these primitive types have unit of multiple bytes (e.g., an int is 4 bytes), you need to specify the byte order of either big-endian (big byte first) or little-endian (little byte first) via order(ByteOrder order) method. The order could be ByteOrder.BIG_ENDIANByteOrder.LITTLE_ENDIAN, or ByteOrder.nativeOrder() which returns the native byte order of the underlying platform for you to write portable program.

ByteBuffer: ByteBuffer is special. To summarize:

  1. It is used in channel I/O (see channel I/O below).
  2. You can allocate ByteBuffer as direct. In this case, the JVM will make a best effort to perform native I/O directly for better performance.
  3. You can create a view as other buffer, such as FloatBuffer via asFloatBuffer().
  4. You can get/put as other primitive types via getXxx() and putXxx().
  5. MapByteBuffer for mapped I/O

Here is example about direct buffer:

     static void directIndirectBuf() {
float[] vertices = {
0.0f, 1.0f, 0.0f, // top (x, y, z)
-1.0f, -1.0f, 0.0f, // left-bottom (x, y, z)
1.0f, -1.0f, 0.0f // right-bottom (x, y, z)
};
FloatBuffer vertexBuffer;
//set up vertex-array buffer. Vertices in float.
//Allocate a direct ByteBuffer for the vertices. A float has 4 bytes.
ByteBuffer vbb = ByteBuffer.allocate(vertices.length * 4); //set the byte order (big-endian or little endian) to the native
//byte order of the underlying platform for portable program.
vbb.order(ByteOrder.nativeOrder());
// Create a direct FloatBuffer as a view of this ByteBuffer.
// Position is 0.
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
// Rewind by setting position to 0
vertexBuffer.position(0);
for (int i = 0; i < vertexBuffer.capacity(); i++) {
System.out.print(vertexBuffer.get(i) + " ");
}
}

1.2  java.nio.MappedByteBuffer

A direct byte buffer whose content is a memory-mapped region of a file.Mapped byte buffers are created via the FileChannel.map method. This class extends the ByteBuffer class with operations that are specific to memory-mapped file regions.A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.

The content of a mapped byte buffer can change at any time, for example if the content of the corresponding region of the mapped file is changed by this program or another. Whether or not such changes occur, and when they occur, is operating-system dependent and therefore unspecified.

All or part of a mapped byte buffer may become inaccessible at any time, for example if the mapped file is truncated. An attempt to access an inaccessible region of a mapped byte buffer will not change the buffer's content and will cause an unspecified exception to be thrown either at the time of the access or at some later time. It is therefore strongly recommended that appropriate precautions be taken to avoid the manipulation of a mapped file by this program, or by a concurrently running program, except to read or write the file's content.Mapped byte buffers otherwise behave no differently than ordinary direct byte buffers.

1.3 Channel (java.nio.channels.Channel) 

A channel represents a connection to a physical I/O device (such as file, network socket, or even another program). It si similar to standard I/O's stream, but a more platform-dependent version of stream. Becase channels hava a closer ties to the underlying platform, they can achieve better I/O thoughtput.

Types of channels are FileChannel, SocketChannel, DatagramChannel.A Channel object can be obtained by calling the getChannel() methods of classes such as java.io.FileInputStreamjava.io.FileOutputStreamjava.io.RandomAccessFile,java.net.Socketjava.net.ServerSocketjava.net.DatagramSocket, and java.net.MulticastSocket.

For example:

        File file = new File("/users/wsy/Documents/job/wok.tar");
FileInputStream in = new FileInputStream(file);
FileChannel channel = in.getChannel();

A FileChannel obtained from a FileInputStream is read-only; while a FileChannel obtained from a FileOutputStream is write-only. While stream I/O processes one byte at at a time; Channel I/O processes a buffer once.

/**
* Reads a sequence of bytes from this channel into the given buffer.
*
* <p> Bytes are read starting at this channel's current file position, and
* then the file position is updated with the number of bytes actually
* read. Otherwise this method behaves exactly as specified in the {@link
* ReadableByteChannel} interface. </p>
*/
public abstract int read(ByteBuffer dst) throws IOException; /**
* Writes a sequence of bytes to this channel from the given buffer.
*
* <p> Bytes are written starting at this channel's current file position
* unless the channel is in append mode, in which case the position is
* first advanced to the end of the file. The file is grown, if necessary,
* to accommodate the written bytes, and then the file position is updated
* with the number of bytes actually written. Otherwise this method
* behaves exactly as specified by the {@link WritableByteChannel}
* interface. </p>
*/
public abstract int write(ByteBuffer src) throws IOException;

We can also transfer data between an input channel and an touput channel directly via:

public abstract long transferFrom(ReadableByteChannel src,
long position, long count)
throws IOException; public abstract long transferTo(long position, long count,
WritableByteChannel target)
throws IOException;

Here is an example copying file using different methods:

1 Using FileChannel with indirect ByteBuffer

static void copyFileFileChannelIndirectMem()  throws IOException{
String inFileStr = "/users/wsy/Documents/job/kimchi_v2.pdf";
String outFileStr = "./kimchi_v2.pdf";
long startTime, elapsedTime; // for speed benchmarking
int bufferSizeKB = 4;
int bufferSize = bufferSizeKB * 1024; // Check file length
File fileIn = new File(inFileStr);
System.out.println("File size is " + fileIn.length() + " bytes");
System.out.println("Buffer size is " + bufferSizeKB + " KB"); // Using FileChannel with indirect ByteBuffer
System.out.println("Using FileChannel with indirect ByteBuffer of " + bufferSizeKB + " KB");
try (FileChannel in = new FileInputStream(inFileStr).getChannel();
FileChannel out = new FileOutputStream(outFileStr).getChannel();) {
// Allocate an indirect ByteBuffer
ByteBuffer bytebuf = ByteBuffer.allocate(bufferSize); startTime = System.nanoTime();
boolean bytesCount;
while((bytesCount = in.read(bytebuf) > 0)){
// flip the buffer which set the limit to current position, and position to 0.
bytebuf.flip();
out.write(bytebuf);
bytebuf.clear();
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed Time is "
+ (elapsedTime / 1000000.0) + " msec");
} catch (IOException ex){
ex.printStackTrace();
}
}

2 Using FileChannel with direct memory

    static void copyFileFileChannelDirectMem()  throws IOException{
String inFileStr = "/users/wsy/Documents/job/kimchi_v2.pdf";
String outFileStr = "./kimchi_v2.pdf";
long startTime, elapsedTime; // for speed benchmarking
int bufferSizeKB = 4;
int bufferSize = bufferSizeKB * 1024; // Check file length
File fileIn = new File(inFileStr);
System.out.println("File size is " + fileIn.length() + " bytes");
System.out.println("Buffer size is " + bufferSizeKB + " KB"); // Using FileChannel with indirect ByteBuffer
System.out.println("Using FileChannel with direct ByteBuffer of " + bufferSizeKB + " KB");
try (FileChannel in = new FileInputStream(inFileStr).getChannel();
FileChannel out = new FileOutputStream(outFileStr).getChannel();) {
// Allocate an indirect ByteBuffer
ByteBuffer bytebuf = ByteBuffer.allocateDirect(bufferSize); startTime = System.nanoTime();
boolean bytesCount;
while((bytesCount = in.read(bytebuf) > 0)){
// flip the buffer which set the limit to current position, and position to 0.
bytebuf.flip();
out.write(bytebuf);
bytebuf.clear();
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed Time is "
+ (elapsedTime / 1000000.0) + " msec");
} catch (IOException ex){
ex.printStackTrace();
}
}

3 Using Buffered Stream I/O

static void CpFileStreamIO () throws IOException {
String inFileStr = "/users/wsy/Documents/job/kimchi_v2.pdf";
String outFileStr = "./kimchi_v2.pdf";
long startTime, elapsedTime; // for speed benchmarking
int bufferSizeKB = 4;
int bufferSize = bufferSizeKB * 1024; System.out.println("Using Buffered Stream");
try( BufferedInputStream in = new BufferedInputStream(new FileInputStream(inFileStr));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outFileStr))) {
startTime = System.nanoTime();
int bytesCount;
while ((bytesCount = in.read()) != -1){
out.write(bytesCount);
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed time is " + (elapsedTime / 1000000.0) + " msec");
} catch (IOException ex){
ex.printStackTrace();
}
}

4 Using FileChannel with transferTo()

private static void CpFileChannel() {
String inFileStr = "/users/wsy/Documents/job/kimchi_v2.pdf";
String outFileStr = "./kimchi_v2.pdf";
long startTime, elapsedTime; // for speed benchmarking
int bufferSizeKB = 4;
int bufferSize = bufferSizeKB * 1024; System.out.println("Using Buffered Stream");
try( FileChannel in = new FileInputStream(inFileStr).getChannel();
FileChannel out = new FileOutputStream(outFileStr).getChannel()) {
startTime = System.nanoTime();
in.transferTo(0, in.size(), out);
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed time is " + (elapsedTime / 1000000.0) + " msec");
} catch (IOException ex){
ex.printStackTrace();
}
}

5 Using a programmer-managed 4K byte-array for Disk I/O

static void CpFileDiskIO () throws IOException {
String inFileStr = "/users/wsy/Documents/job/kimchi_v2.pdf";
String outFileStr = "./kimchi_v2.pdf";
long startTime, elapsedTime; // for speed benchmarking
int bufferSizeKB = 4;
int bufferSize = bufferSizeKB * 1024; System.out.println("Using a programmer-managed byte-array of " + bufferSizeKB + " KB");
try(FileInputStream in = new FileInputStream(inFileStr);
FileOutputStream out = new FileOutputStream(outFileStr)) {
startTime = System.nanoTime();
// Create byte array
byte[] byteArray = new byte[bufferSize];
int bytesCount;
while ((bytesCount = in.read(byteArray)) != -1){
out.write(byteArray, 0, bytesCount);
}
elapsedTime = System.nanoTime() - startTime;
System.out.println("Elapsed time is " + (elapsedTime / 1000000.0) + " msec");
} catch (IOException ex){
ex.printStackTrace();
}
}

FileChannel with a 4K direct Bytebuffer is faster than indirect ByteBuffer. Buffered Stream I/O is much slower than FileChannel. While user-managed byte-array is faster than some channels.

The following table compare the run-time for various buffer size with (a) Using FileChannel with an indirect ByteBuffer, (b) Using FileChannel with a direct ByteBuffer, (c) Using FileChannel withtransferTo(), (d) Using Buffered Stream, (e) Using a programmer-managed byte-array.

BufSize (a) (b) (c) (d) (e)

   4KB  16.67   9.73   3.33 124.21   7.72
16KB 6.92 3.39 1.86 110.85 4.06
32KB 3.95 2.75 1.76 109.60 2.90
64KB 3.26 2.15 1.88 109.77 2.96
128KB 2.77 2.11 2.02 109.64 2.59
256KB 2.49 1.66 1.80 109.10 2.55
1024KB 3.57 1.86 1.97 109.08 5.88

1.4 Selector

A number of channels can be registered with a selector (java.nio.channels.Selector). A selector provides a mechanism for waiting on channels until one ore more become available for data transfer. It can be used to block the program until at least one channel is available for use. Examples are server applications that involves simultaneously waiting for responses on a number of session.

1.5 Character Set(CharSet) 

waiting for complement

Analysis about different methods for reading and writing file in Java language的更多相关文章

  1. Reading and writing RData files

    前面添加个lapply()或者dplyr::llply()就能读取,储存多个文件了.http://bluemountaincapital.github.io/FSharpRProvider/readi ...

  2. Reading and writing

    A text file is a sequence of characters stored on a permanent medium like a hard drive, flash memory ...

  3. Reading and Writing CSV Files in C#

    Introduction A common requirement is to have applications share data with other programs. Although t ...

  4. Apache POI – Reading and Writing Excel file in Java

    来源于:https://www.mkyong.com/java/apache-poi-reading-and-writing-excel-file-in-java/ In this article, ...

  5. Error writing file‘frm‘(Errcode: 28)

    Error writing file‘frm‘(Errcode: 28)   mysql出现这个错误,表示磁盘已经满了,该增加容量了.

  6. Reading Lines from File in C++

    Reading Lines from File in C++ In C++, istringstream has been used to read lines from a file. code: ...

  7. mysql执行SQL语句时报错:[Err] 3 - Error writing file '/tmp/MYP0G1B8' (Errcode: 28 - No space left on device)

    问题描述: 今天一同事在mysql中执行SQL语句的时候,报了/tmp空间不足的问题,报错如下: [SQL] SELECT f.prov as 字段1, MAX( CASE f.flag_name W ...

  8. Java – Reading a Large File Efficiently--转

    原文地址:http://www.baeldung.com/java-read-lines-large-file 1. Overview This tutorial will show how to r ...

  9. Reading or Writing to Another Processes Memory in C# z

    http://www.jarloo.com/reading-and-writing-to-memory/ Declarations [Flags] public enum ProcessAccessF ...

随机推荐

  1. Zoom属性的使用介绍(IE私有属性)

      其实Zoom属性是IE浏览器的专有属性,Firefox等浏览器不支持.它可以设置或检索对象的缩放比例.除此之外,它还有其他一些小作用,比如触发ie的hasLayout属性,清除浮动.清除margi ...

  2. App.config和Web.config配置文件的自定义配置节点

    前言 昨天修改代码发现了一个问题,由于自己要在WCF服务接口中添加了一个方法,那么在相应调用的地方进行更新服务就可以了,不料意外发生了,竟然无法更新.左查右查终于发现了问题.App.config配置文 ...

  3. 第9课_3_db库安装

    四 安装listener监听 使用oracle用户,在rac1和rac2上都可以起netca 1.打开网络配置界面,选择"Cluster configuration"集群配置方案, ...

  4. 混淆篇之原生DOM操作方法小结

    1.0   DOM结构 1.1先来看结构图: 父节点        兄弟节点        当前节点            属性节点            子节点        兄弟节点一般任意一个节 ...

  5. Java SE基础部分——常用类库之NumberFormat(数字格式化)

    数字格式化常用方法:DecimalFormat和NuberFormat. //2016060524 数字格式化学习 //数字格式化 两种方法 一种直接使用NumberFormat,另一种Decimal ...

  6. 关于MySQL MyISAM 表并发

    MyISAM的锁调度 MyISAM存储引擎的读锁和写锁是互斥的,读写操作是串行的.那么,一个进程请求某个MyISAM表的读锁,同时另一个进程也请求同一表的写锁,MySQL如何处理呢?答案是写进程先获得 ...

  7. 关于html标签元素的data-*属性

    关于这个主题的文章和博客其实已经非常多了,这里并非要重复造轮子,只是看到一些例子稍微有点麻烦,其实也很简单,但是对于一个刚刚入门的人,w3c的例子甚至可能看不懂,这里列出一个最简单不过的小案例以供参考 ...

  8. 编译SASS

    编译SASS sass编译有很多种方式,如命令行编译模式.sublime插件SASS-Build.编译软件koala.前端自动化软件codekit.Grunt打造前端自动化工作流grunt-sass. ...

  9. 'gbk' codec can't encode character

    做爬虫抓取网页,print(html)进行调试,遇到UnicodeEncodeError: 'gbk' codec can't encode character XX in position XX问题 ...

  10. android ViewHolder 使用

    android中使用ListView   ExpandableListView  数据适配器adapter很多都是自己定义,自己定义数据适配器时,要重写getView.重写getView为了不让每次调 ...