<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="http://itecfun.com/extern.php?action=feed&amp;tid=3158&amp;type=rss" rel="self" type="application/rss+xml" />
		<title><![CDATA[个人知识管理站 / Java I/O 操作及优化建议[转载]]]></title>
		<link>http://www.itecfun.com/viewtopic.php?id=3158</link>
		<description><![CDATA[Java I/O 操作及优化建议[转载] 最近发表的帖子。]]></description>
		<lastBuildDate>Wed, 10 Jun 2015 01:54:57 +0000</lastBuildDate>
		<generator>FluxBB</generator>
		<item>
			<title><![CDATA[Java I/O 操作及优化建议[转载]]]></title>
			<link>http://www.itecfun.com/viewtopic.php?pid=3312#p3312</link>
			<description><![CDATA[<p><a href="http://www.ibm.com/developerworks/cn/java/j-lo-io-optimize/index.html" rel="nofollow">Java I/O 操作及优化建议</a><br />Java NIO<br />Java.nio 包是 Java 在 1.4 版本之后新增加的包，专门用来提高 I/O 操作的效率。<br />表 1 所示是 I/O 与 NIO 之间的对比内容。<br />表 1. I/O VS NIO<br />-----------------------------------<br />I/O&#160; &#160;&#160; &#160; &#160; &#160; &#160; &#160;|&#160; &#160; &#160; &#160; &#160; &#160;NIO<br />-----------------------------------<br />面向流&#160; &#160; &#160; &#160; &#160; |&#160; &#160; &#160; &#160; &#160;面向缓冲<br />-----------------------------------<br />阻塞 IO&#160; &#160; &#160; &#160; &#160;|&#160; &#160; &#160; &#160; &#160;非阻塞 IO<br />-----------------------------------<br />无&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;|&#160; &#160; &#160; &#160; &#160; 选择器<br />------------------------------------<br />NIO 是基于块 (Block) 的，它以块为基本单位处理数据。在 NIO 中，最为重要的两个组件是缓冲 Buffer 和通道 Channel。缓冲是一块连续的内存块，是 NIO 读写数据的中转地。通道标识缓冲数据的源头或者目的地，它用于向缓冲读取或者写入数据，是访问缓冲的接口。Channel 是一个双向通道，即可读，也可写。Stream 是单向的。应用程序不能直接对 Channel 进行读写操作，而必须通过 Buffer 来进行，即 Channel 是通过 Buffer 来读写数据的。<br />使用 Buffer 读写数据一般遵循以下四个步骤：<br />1.写入数据到 Buffer；<br />2.调用 flip() 方法；<br />3.从 Buffer 中读取数据；<br />4.调用 clear() 方法或者 compact() 方法。<br />当向 Buffer 写入数据时，Buffer 会记录下写了多少数据。一旦要读取数据，需要通过 flip() 方法将 Buffer 从写模式切换到读模式。在读模式下，可以读取之前写入到 Buffer 的所有数据。<br />一旦读完了所有的数据，就需要清空缓冲区，让它可以再次被写入。有两种方式能清空缓冲区：调用 clear() 或 compact() 方法。clear() 方法会清空整个缓冲区。compact() 方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处，新写入的数据将放到缓冲区未读数据的后面。</p><p>Buffer的接口层次<br /><strong>Buffer<br />&#160; &#160; ByteBuffer<br />&#160; &#160; &#160; &#160; HeapByteBuffer<br />&#160; &#160; &#160; &#160; MappedByteBuffer<br />&#160; &#160; CharBuffer<br />&#160; &#160; DoubleBuffer<br />&#160; &#160; FloatBuffer<br />&#160; &#160; IntBuffer<br />&#160; &#160; LongBuffer<br />&#160; &#160; ShortBuffer<br /></strong></p><p><strong>Buffer 写数据有两种情况：</strong><br />1.从 Channel 写到 Buffer，如例子中 Channel 从文件中读取数据，写到 Channel；<br />2.直接调用 put 方法，往里面写数据。</p><p><strong>从 Buffer 中读取数据有两种方式：</strong><br />1.从 Buffer 读取数据到 Channel；<br />2.使用 get() 方法从 Buffer 中读取数据。</p><p>Buffer 的 rewin 方法将 position 设回 0，所以你可以重读 Buffer 中的所有数据。limit 保持不变，仍然表示能从 Buffer 中读取多少个元素（byte、char 等）。<br />clear() 和 compact() 方法<br />一旦读完 Buffer 中的数据，需要让 Buffer 准备好再次被写入。可以通过 clear() 或 compact() 方法来完成。<br />如果调用的是 clear() 方法，position 将被设回 0，limit 被设置成 capacity 的值。换句话说，Buffer 被清空了。Buffer 中的数据并未清除，只是这些标记告诉我们可以从哪里开始往 Buffer 里写数据。<br />如果 Buffer 中有一些未读的数据，调用 clear() 方法，数据将“被遗忘”，意味着不再有任何标记会告诉你哪些数据被读过，哪些还没有。如果 Buffer 中仍有未读的数据，且后续还需要这些数据，但是此时想要先写些数据，那么使用 compact() 方法。compact() 方法将所有未读的数据拷贝到 Buffer 起始处。然后将 position 设到最后一个未读元素正后面。limit 属性依然像 clear() 方法一样，设置成 capacity。现在 Buffer 准备好写数据了，但是不会覆盖未读的数据。</p><p><strong>Buffer 参数</strong><br />Buffer 有 3 个重要的参数：位置 (position)、容量 (capacity) 和上限 (limit)。<br /><strong>capacity </strong>是指 Buffer 的大小，在 Buffer 建立的时候已经确定。<br /><strong>limit </strong>当 Buffer 处于写模式，指还可以写入多少数据；处于读模式，指还有多少数据可以读。<br /><strong>position </strong>当 Buffer 处于写模式，指下一个写数据的位置；处于读模式，当前将要读取的数据的位置。</p><p>每读写一个数据，position+1，也就是 limit 和 position 在 Buffer 的读/写时的含义不一样。当调用 Buffer 的 flip 方法，由写模式变为读模式时，limit(读)=position(写)，position(读) =0。<br /><strong><br />散射&amp;聚集</strong><br />NIO 提供了处理结构化数据的方法，称之为散射 (Scattering) 和聚集 (Gathering)。散射是指将数据读入一组 Buffer 中，而不仅仅是一个。聚集与之相反，指将数据写入一组 Buffer 中。散射和聚集的基本使用方法和对单个 Buffer 操作时的使用方法相当类似。在散射读取中，通道依次填充每个缓冲区。填满一个缓冲区后，它就开始填充下一个，在某种意义上，缓冲区数组就像一个大缓冲区。在已知文件具体结构的情况下，可以构造若干个符合文件结构的 Buffer，使得各个 Buffer 的大小恰好符合文件各段结构的大小。此时，通过散射读的方式可以一次将内容装配到各个对应的 Buffer 中，从而简化操作。如果需要创建指定格式的文件，只要先构造好大小合适的 Buffer 对象，使用聚集写的方式，便可以很快地创建出文件。清单 1 以 FileChannel 为例，展示如何使用散射和聚集读写结构化文件。(代码看原文)</p>]]></description>
			<author><![CDATA[dummy@example.com (osborn)]]></author>
			<pubDate>Wed, 10 Jun 2015 01:54:57 +0000</pubDate>
			<guid>http://www.itecfun.com/viewtopic.php?pid=3312#p3312</guid>
		</item>
	</channel>
</rss>
