import java.io.*; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.zip.CRC32; public class Test { public static void main(String[] args){ MemoryMapTest.test(); } } /* 2.6 内存映射文件 2.6.1 内存映射文件的性能 java.nio包使用内存映射的过程: 1.得到一个通道 FileChannel channel = FileChannel.open(path,options); 2.通过map方法从这个通道中获得一个ByteBuffer,可以指定要映射的文件区域与模式 FileChannel.MapMode.READ_ONLY: FileChannel.MapMode.READ_WRITE: FileChannel.MapMode.PRIVATE: 3.通过ByteBuffer读写数据 //顺序遍历缓冲区所有字节 while(buffer.hasRemaining()){ byte b = buffer.get(); ... } //随机访问缓冲区字节 for(int i =0; i<buffer.limit(); i++) byte b = buffer.get(i); ... } //读写字节数组 get(byte[] bytes) get(byte[] bytes, int offset, int len) getInt,getLong,getShort,getChar,getFloat,getDouble,order buffer.order(ByteOrder.LITTLE_ENDIAN); */ class MemoryMapTest{ /* 待会找到Java编程思想中关于CRC32的用法,对比一下 CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32()); ZipOutputStream zos = new ZipOutputStream(csum); */ public static long checksumInputStream(Path filename){ try(InputStream in = Files.newInputStream(filename)) { CRC32 crc = new CRC32(); int c; while((c=in.read())!=-1){ crc.update(c); } return crc.getValue(); } catch (IOException e) { e.printStackTrace(); } return 0L; } public static long checksumBufferedInputStream(Path filename){ try(InputStream in = new BufferedInputStream(Files.newInputStream(filename))){ CRC32 crc = new CRC32(); int c; while((c=in.read())!=-1){ crc.update(c); } return crc.getValue(); } catch (IOException e) { e.printStackTrace(); } return 0L; } public static long checksumRandomAccseeFile(Path filename){ try(RandomAccessFile file = new RandomAccessFile(filename.toFile(),"r")) { long length = file.length(); CRC32 crc = new CRC32(); for(long p=0;p<length;p++){ file.seek(p); int c= file.readByte(); crc.update(c); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return 0L; } public static long checksumMappedFile(Path filename){ try(FileChannel channel = FileChannel.open(filename)) { CRC32 crc = new CRC32(); int length = (int)channel.size(); MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY,0,length); for (int p = 0; p < length; p++) { int c = buffer.get(p); crc.update(c); } return crc.getValue(); } catch (IOException e) { e.printStackTrace(); } return 0L; } public static void test(){ Path filename = Paths.get("./temp.tmp"); //InputStream System.out.println("InputStream:"); long start = System.currentTimeMillis(); long crcValue = checksumInputStream(filename); long end = System.currentTimeMillis(); System.out.println(Long.toHexString(crcValue)); System.out.println((end-start)+" milliseconds"); //RandomAccessFile System.out.println("RandomAccessFile:"); start = System.currentTimeMillis(); crcValue = checksumRandomAccseeFile(filename); end = System.currentTimeMillis(); System.out.println(Long.toHexString(crcValue)); System.out.println((end-start)+" milliseconds"); //BufferedInputStream System.out.println("BufferedInputStream:"); start = System.currentTimeMillis(); crcValue = checksumBufferedInputStream(filename); end = System.currentTimeMillis(); System.out.println(Long.toHexString(crcValue)); System.out.println((end-start)+" milliseconds"); //Mapped System.out.println("InputStream:"); start = System.currentTimeMillis(); crcValue = checksumMappedFile(filename); end = System.currentTimeMillis(); System.out.println(Long.toHexString(crcValue)); System.out.println((end-start)+" milliseconds"); } } /* 2.6.2 缓冲区数据结构 每个缓冲区都具有: 1.一个容量,它永远不能被改变 2.一个读写位置,写一个值将在此读写 3.一个界限,超过它进行读写是没有意义的 4.一个可选的标记,用于重复一个读入或写出操作 0<=标记<=位置<=界限<=容量 */ /* 2.6.3 文件加锁机制 FileLock lock = channel.lock(); FileLock lock = channel.tryLock(); FileLock lock(long start,long size,boolean shared) FileLock tryLock(long start, long size,boolean shared) 如果shared的标志为false,则锁定文件的目的是读写,如果为true,则这是一个共享锁, 它允许多个进程从文件中读入,并阻止任何进程获得独占的锁。调用FileLock类的isShared 方法可以查询你持有的锁的类型。 */
《Java核心技术卷二》笔记