自己切片做网站,wordpress登录才能浏览,小型网站怎样优化,用wordpress做的网站有哪些前言内存映射文件(Memory-mapped File)#xff0c;指的是将一段虚拟内存逐字节映射于一个文件#xff0c;使得应用程序处理文件如同访问主内存(但在真正使用到这些数据前却不会消耗物理内存#xff0c;也不会有读写磁盘的操作)#xff0c;这要比直接文件读写快几个数量级。…前言内存映射文件(Memory-mapped File)指的是将一段虚拟内存逐字节映射于一个文件使得应用程序处理文件如同访问主内存(但在真正使用到这些数据前却不会消耗物理内存也不会有读写磁盘的操作)这要比直接文件读写快几个数量级。稍微解释一下虚拟内存(很明显不是物理内存)它是计算机系统内存管理的一种技术。像施了妖法一样使得应用程序认为它拥有连续的可用的内存实际上呢它通常是被分隔成多个物理内存的碎片还有部分暂时存储在外部磁盘存储器上在需要时进行数据交换。内存映射文件主要的用处是增加 I/O 性能特别是针对大文件。对于小文件内存映射文件反而会导致碎片空间的浪费因为内存映射总是要对齐页边界最小单位是 4 KiB一个 5 KiB 的文件将会映射占用 8 KiB 内存也就会浪费 3 KiB 内存。java.nio 包使得内存映射变得非常简单其中的核心类叫做 MappedByteBuffer字面意思为映射的字节缓冲区。01、使用 MappedByteBuffer 读取文件假设现在有一个文件名叫 cmower.txt里面的内容是沉默王二一个有趣的程序员PS哎改不了王婆卖瓜自卖自夸这个臭毛病了因为文章被盗得都怕了。这个文件放在 /resource 目录下我们可以通过下面的方法获取到它ClassLoader classLoader Cmower.class.getClassLoader(); Path path Paths.get(classLoader.getResource(cmower.txt).getPath());Path 既可以表示一个目录也可以表示一个文件就像 File 那样――当然了Path 是用来取代 File 的。然后从文件中获取一个 channel(通道对磁盘文件的一种抽象)。FileChannel fileChannel FileChannel.open(path);紧接着调用 FileChannel 类的 map 方法从 channel 中获取 MappedByteBuffer此类扩展了 ByteBuffer――提供了一些内存映射文件的基本操作方法。MappedByteBuffer mappedByteBuffer fileChannel.map(mode, position, size);稍微解释一下 map 方法的三个参数。1)mode 为文件映射模式分为三种MapMode.READ_ONLY(只读)任何试图修改缓冲区的操作将导致抛出 ReadOnlyBufferException 异常。MapMode.READ_WRITE(读/写)任何对缓冲区的更改都会在某个时刻写入文件中。需要注意的是其他映射同一个文件的程序可能不能立即看到这些修改多个程序同时进行文件映射的行为依赖于操作系统。MapMode.PRIVATE(私有) 对缓冲区的更改不会被写入到该文件任何修改对这个缓冲区来说都是私有的。2)position 为文件映射时的起始位置。3)size 为要映射的区域的大小必须是非负数不得大于Integer.MAX_VALUE。一旦把文件映射到内存缓冲区我们就可以把里面的数据读入到 CharBuffer 中并打印出来。具体的代码示例如下。CharBuffer charBuffer null; ClassLoader classLoader Cmower.class.getClassLoader(); Path path Paths.get(classLoader.getResource(cmower.txt).getPath()); try (FileChannel fileChannel FileChannel.open(path)) { MappedByteBuffer mappedByteBuffer fileChannel.map(MapMode.READ_ONLY, 0, fileChannel.size()); if (mappedByteBuffer ! null) { charBuffer Charset.forName(UTF-8).decode(mappedByteBuffer); } System.out.println(charBuffer.toString()); } catch (IOException e) { e.printStackTrace(); }由于 decode() 方法的参数是 MappedByteBuffer这就意味着我们是从内存中而不是磁盘中读入的文件内容所以速度会非常快。02、使用 MappedByteBuffer 写入文件假设现在要把下面的内容写入到一个文件名叫 cmower1.txt。沉默王二《Web全栈开发进阶之路》作者这个文件还没有创建计划放在项目的 classpath 目录下。Path path Paths.get(cmower1.txt);具体位置见下图所示。然后创建文件的通道。FileChannel fileChannel FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)仍然使用的 open 方法不过增加了 3 个参数前 2 个很好理解表示文件可读(READ)、可写(WRITE)第 3 个参数 TRUNCATE_EXISTING 的意思是如果文件已经存在并且文件已经打开将要进行 WRITE 操作则其长度被截断为 0。紧接着仍然调用 FileChannel 类的 map 方法从 channel 中获取 MappedByteBuffer。MappedByteBuffer mappedByteBuffer fileChannel.map(MapMode.READ_WRITE, 0, 1024);这一次我们把模式调整为 MapMode.READ_WRITE并且指定文件大小为 1024即 1KB 的大小。然后使用 MappedByteBuffer 中的 put() 方法将 CharBuffer 的内容保存到文件中。具体的代码示例如下。CharBuffer charBuffer CharBuffer.wrap(沉默王二《Web全栈开发进阶之路》作者); Path path Paths.get(cmower1.txt); try (FileChannel fileChannel FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) { MappedByteBuffer mappedByteBuffer fileChannel.map(MapMode.READ_WRITE, 0, 1024); if (mappedByteBuffer ! null) { mappedByteBuffer.put(Charset.forName(UTF-8).encode(charBuffer)); } } catch (IOException e) { e.printStackTrace(); }可以打开 cmower1.txt 查看一下内容确认预期的内容有没有写入成功。03、MappedByteBuffer 的遗憾据说在 Java 中使用 MappedByteBuffer 是一件非常麻烦并且痛苦的事主要表现有1)一次 map 的大小最好限制在 1.5G 左右重复 map 会增加虚拟内存回收和重新分配的压力。也就是说如果文件大小不确定的话就不太友好。2)虚拟内存由操作系统来决定什么时候刷新到磁盘这个时间不太容易被程序控制。3)MappedByteBuffer 的回收方式比较诡异。再次强调这三种说法都是据说我暂时能力有限也不能确定这种说法的准确性很遗憾。04、比较文件操作的处理时间嗨朋友阅读完以上的内容之后我想你一定对内存映射文件有了大致的了解。但我相信如果你是一名负责任的程序员你一定还想知道内存映射文件的读取速度究竟有多快。为了得出结论我叫了另外三名竞赛的选手InputStream(普通输入流)、BufferedInputStream(带缓冲的输入流)、RandomAccessFile(随机访问文件)。读取的对象是加勒比海盗4惊涛怪浪.mkv大小为 1.71G。1)普通输入流public static void inputStream(Path filename) { try (InputStream is Files.newInputStream(filename)) { int c; while((c is.read()) ! -1) { } } catch (IOException e) { e.printStackTrace(); } }2)带缓冲的输入流public static void bufferedInputStream(Path filename) { try (InputStream is new BufferedInputStream(Files.newInputStream(filename))) { int c; while((c is.read()) ! -1) { } } catch (IOException e) { e.printStackTrace(); } }3)随机访问文件public static void randomAccessFile(Path filename) { try (RandomAccessFile randomAccessFile new RandomAccessFile(filename.toFile(), r)) { for (long i 0; i randomAccessFile.length(); i) { randomAccessFile.seek(i); } } catch (IOException e) { e.printStackTrace(); } }4)内存映射文件public static void mappedFile(Path filename) { try (FileChannel fileChannel FileChannel.open(filename)) { long size fileChannel.size(); MappedByteBuffer mappedByteBuffer fileChannel.map(MapMode.READ_ONLY, 0, size); for (int i 0; i size; i) { mappedByteBuffer.get(i); } } catch (IOException e) { e.printStackTrace(); } }测试程序也很简单大致如下long start System.currentTimeMillis(); bufferedInputStream(Paths.get(jialebi.mkv)); long end System.currentTimeMillis(); System.out.println(end-start);四名选手的结果如下表所示。方法时间普通输入流龟速没有耐心等出结果随机访问文件龟速没有耐心等下去带缓冲的输入流29966内存映射文件914普通输入流和随机访问文件都慢得要命真的是龟速我没有耐心等待出结果带缓冲的输入流的表现还不错但相比内存映射文件就逊色多了。由此得出的结论就是内存映射文件上G大文件轻松处理。05、最后本篇文章主要介绍了 Java 的内存映射文件MappedByteBuffer 是其灵魂读取速度快如火箭。另外所有这些示例和代码片段都可以在 GitHub 上找到――这是一个 Maven 项目所以它很容易导入和运行。以上就是本文的全部内容希望对大家的学习有所帮助也希望大家多多支持华域联盟。