*概述

---通过FileChannel的map(),可以使用directbuffer的方式读写文件内容,这里称之为内存映射.

Open Declaration MappedByteBuffer java.nio.channels.FileChannel.map(MapMode mode, long position, long size) throws IOException

*MappedByteBuffer

---优点

没有系统调用,节省了时间,这是使用directbuffer的好处,没有JVM和系统之间的复制操作.

---特殊的buffer,对应文件内容在虚拟内存中的一个区域,是direct buffer.所以创建需要的代价更大,适用于对大文件操作的情况.

---map()调用时的参数MapMode,它是FileChannel的静态内部类,定义对bufffer内容的执行方式

MapMode.READ_ONLY,只能对buffer进行读操作,否则抛出异常,NonWritableChannelException.

MapMode.READ_WRITE,可读可写,修改会写入文件.

MapMode.PRIVATE,可读可写,但是修改的内容不会写入文件,只是buffer自身的改变,称之为”copy on write”.

“copy on write”的好处,同一文件的多个buffer,可以共享同一片内存页.

注意,同一文件的MapMode.READ_ONLY和MapMode.READ_WRITE是公用同一个数组,但是MapMode.PRIVATE却是各自独立的.

*MappedByteBuffer的API

---load()

将buffer的内容,加载到物理内存中,目的是为了更快的操作.

但是这个方法受到很多因素的影响,如文件系统,JVM,系统内存等,总之慎用.

---force()

将buffer修改的内容,全部写入文件.只对MapMode.READ_WRITE有效

*示例一

---from java nio,说明了同一个文件的各种模式的MappedByteBuffer之间的关系

package nio.channel;

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
/**
 * Test behavior of Memory mapped buffer types. Create a file, write
 * some data to it, then create three different types of mappings
 * to it. Observe the effects of changes through the buffer APIs
 * and updating the file directly. The data spans page boundaries
 * to illustrate the page-oriented nature of Copy-On-Write mappings.
 *
 * @author Ron Hitchens (ron@ronsoft.com)
 */
public class MapFile
{
	public static void main (String [] argv)
	throws Exception
	{
		// Create a temp file and get a channel connected to it
		File tempFile = File.createTempFile ("mmaptest", null);
		RandomAccessFile file = new RandomAccessFile (tempFile, "rw");
		FileChannel channel = file.getChannel();
		ByteBuffer temp = ByteBuffer.allocate (100);
		// Put something in the file, starting at location 0
		temp.put ("This is the file content".getBytes());
		temp.flip();
		channel.write (temp, 0);
		// Put something else in the file, starting at location 8192.
		// 8192 is 8 KB, almost certainly a different memory/FS page.
		// This may cause a file hole, depending on the
		// filesystem page size.
		temp.clear();
		temp.put ("This is more file content".getBytes());
		temp.flip();
		channel.write (temp, 8192);
		// Create three types of mappings to the same file
		MappedByteBuffer ro = channel.map (
				FileChannel.MapMode.READ_ONLY, 0, channel.size());
		MappedByteBuffer rw = channel.map (
				FileChannel.MapMode.READ_WRITE, 0, channel.size());
		MappedByteBuffer cow = channel.map (
				FileChannel.MapMode.PRIVATE, 0, channel.size());
		// the buffer states before any modifications
		System.out.println ("Begin");
		showBuffers (ro, rw, cow);
		// Modify the copy-on-write buffer
		cow.position (8);
		cow.put ("COW".getBytes());
		System.out.println ("Change to COW buffer");
		showBuffers (ro, rw, cow);
		// Modify the read/write buffer
		rw.position (9);
		rw.put (" R/W ".getBytes());
		rw.position (8194);
		rw.put (" R/W ".getBytes());
		rw.force();
		System.out.println ("Change to R/W buffer");
		showBuffers (ro, rw, cow);
		// Write to the file through the channel; hit both pages
		temp.clear();
		temp.put ("Channel write ".getBytes());
		temp.flip();
		channel.write (temp, 0);
		temp.rewind();
		channel.write (temp, 8202);
		System.out.println ("Write on channel");
		showBuffers (ro, rw, cow);
		// Modify the copy-on-write buffer again
		cow.position (8207);
		cow.put (" COW2 ".getBytes());
		System.out.println ("Second change to COW buffer");
		showBuffers (ro, rw, cow);
		// Modify the read/write buffer
		rw.position (0);
		rw.put (" R/W2 ".getBytes());
		rw.position (8210);
		rw.put (" R/W2 ".getBytes());
		rw.force();
		System.out.println ("Second change to R/W buffer");
		showBuffers (ro, rw, cow);
		
		// cleanup
		channel.close();
		file.close();
		tempFile.delete();
	}
	
	// Show the current content of the three buffers
	public static void showBuffers (ByteBuffer ro, ByteBuffer rw,
			ByteBuffer cow)
	throws Exception
	{
		dumpBuffer ("R/O", ro);
		dumpBuffer ("R/W", rw);
		dumpBuffer ("COW", cow);
		System.out.println (" ");
	}
	// Dump buffer content, counting and skipping nulls
	public static void dumpBuffer (String prefix, ByteBuffer buffer)
	throws Exception
	{
		System.out.print (prefix + ": '");
		int nulls = 0;
		int limit = buffer.limit();
		for (int i = 0; i < limit; i++) {
			char c = (char) buffer.get (i);
			if (c == '\u0000') {
				nulls++;
				continue;
			}
			if (nulls != 0) {
				System.out.print ("|[" + nulls
						+ " nulls]|");
				nulls = 0;
			}
			System.out.print (c);
		}
		System.out.println ("'");
	}
}

*示例二

---说明同一文件的MapMode.PRIVATE的buffer之间是互补影响的,且force()是无效的

/**
 * Mar 27, 2011 by dzh
 */
package nio.channel;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

/**
 * @author dzh
 *
 */
public class MapFile1 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			File tempFile =File.createTempFile("tempFile", null);
			RandomAccessFile raf =new RandomAccessFile(tempFile,"rw");
			FileChannel fc =raf.getChannel();
			
			//initialize file's content
			ByteBuffer buffer =ByteBuffer.allocate(100);
			buffer.put("The whether has been bad these day in GuangZhou".getBytes());
			buffer.flip();
			fc.write(buffer);
			
			MappedByteBuffer mbb0 =fc.map(MapMode.PRIVATE, 0, fc.size());
			MappedByteBuffer mbb1 =fc.map(MapMode.PRIVATE, 0, fc.size());
			
			System.out.println("Change mbb0 buffer");
			mbb0.position(4);
			mbb0.put("dzh".getBytes());
			showBuffer("mbb0",mbb0); //The dzhther has been bad these day in GuangZhou
			showBuffer("mbb1",mbb1); //The whether has been bad these day in GuangZhou
			
			mbb0.force(); //no effect
			MappedByteBuffer content =fc.map(MapMode.PRIVATE, 0, fc.size());
			showBuffer("file content", content); //The whether has been bad these day in GuangZhou
			
			raf.close();
			tempFile.delete();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 输出buffer的内容
	 * @param name
	 * @param buffer
	 */
	private static void showBuffer(String name,MappedByteBuffer buffer){
		System.out.println(name+":");
		for(int i=0;i<buffer.limit();i++){
			char c =(char) buffer.get(i);
			System.out.print(c);
		}
		System.out.println(" ");
	}

}

相关文章:

  • 2021-12-05
  • 2021-12-01
  • 2021-08-09
  • 2022-01-18
  • 2021-11-12
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-16
  • 2022-12-23
  • 2021-05-28
  • 2022-12-23
  • 2021-05-16
  • 2021-09-18
  • 2021-08-03
相关资源
相似解决方案