java流与文件——内存映射文件

【0】README

0.1) 本文描述转自 core java volume 2, 旨在理解 java流与文件——内存映射文件 的相关知识;
0.2)内存映射文件的目的是: 提高访问速度, 缓冲区Buffer;
0.3) 本文干货源代码均为原创, for source code , please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter1/MemoryMapTest.java


【1】intro to 内存映射文件

1.1)大多数os 都利用 虚拟内存实现来将 一个文件或文件的一部分映射到 内存中;
1.2)java.nio 包使内存映射变得简单, 下面是我们需要做的:

  • 1.2.1)首先,从文件中获得一个通道, 通道是对 磁盘文件的一种抽象, 它使我们可以访问诸如内存映射, 文件加锁机制以及文件间快速数据传递等操作系统特性;(干货——通道的定义,即对磁盘文件的抽象)
    FileChannel channel = FIleChannel.open(path , options);
  • 1.2.2) 然后, 调用FileChannel 类的map方法从这个通道中获得一个 ByteBuffer。 你可以指定想要映射的文件区域与映射模式, 支持的模式有三种(Model):
    • M1)FileChannel.MapMode.READ_ONLY: 所产生的缓冲区是只读的, 任何对该缓冲区写入都会产生异常;
    • M2)FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的;任何修改都会在这个时刻写回到文件中;
    • M3)FileChannel.MapMode.PRIVATE: 所产生的缓冲区是可写的, 但是任何修改对这个缓冲区来说都是私有的,不会传播到文件中;

1.3)一旦有了缓冲区,就可以使用 ByteBuffer 类 和 Buffer 超类的方法读写数据了;

  • 1.3.1)缓冲区支持顺序和随机数据访问, 它有一个可以通过get 和 put 操作来移动的位置;如, 像下面这样遍历缓冲区中的所有字节:
    while(buffer.hasRemaining)
    {
    byte b = buffer.get();
    }
  • 1.3.2)或者像下面这样进行随机访问:
    for(i=0;i
CRC32 crc = new CRC32();
while(more bytes)crc.update(next byte)
long checksum = crc.getValue();

这里写图片描述


【2】缓冲区数据结构

2.1)在使用内存映射时, 我们创建了单一的缓冲区横跨整个文件或我们感兴趣的文件区域。我们还可以使用更多的缓冲区来读写大小适度的信息块;
2.2)本节将简要介绍Buffer 对象上的基本操作。

  • 2.2.1)缓冲区定义:缓冲区是由具有相同类型的数值构成的数组,Buffer 类是一个抽象类, 它有众多的具体子类,包括ByteBuffer, CharBuffer, DoubleBuffer, IntBuffer, LongBuffer, ShortBuffer ; (干货——缓冲区定义)
    Attention) StringBufffer 类与这些缓冲区没有关系;
  • 2.2.2)最常用的是ByteBuffer 和 CharBuffer; (干货——最常用Buffer的是ByteBuffer 和 CharBuffer)
  • 2.2.3)每个缓冲区都具有: (干货——缓冲区的功能)

    • 2.2.3.1)一个容量: 它永远不能改变;
    • 2.2.3.2)一个读写位置: 下一个值将在此进行读写;
    • 2.2.3.3)一个界限: 超过它进行读写是没有意义的;
    • 2.2.3.4)一个可选标记:用于重复一个读入或写出操作;
    • 2.2.3.5)这些值满足下面的条件: 0 <= 标记<=读写位置 <=界限 <=容量; (干货——缓冲区中给定标记,读写位置,界限,容量的大小关系)
      这里写图片描述
  • 2.2.4)使用缓冲区的主要目的是执行写, 然后读入循环。

    • 2.2.4.1)put方法:将值添加到缓冲区;
    • 2.2.4.2)flip方法:将界限设置到当前位置,并把位置复位到0;
    • 2.2.4.3)remaining方法: 现在在 remaining 方法返回整数时(它返回的值是 “界限—位置”),不断地调用get方法;
    • 2.2.4.4)clear方法: 在我们将缓冲区的所有值都读入后, 调用clear 使缓冲区为下一次写循环做好准备。 clear 方法将位置复位到0, 并将界限复位到容量;
    • 2.2.4.5)rewind 或 mark/reset方法: 如果你想重读缓冲区, 可以使用 rewind或 mark/reset 方法;
    • 2.2.4.6)ByteBuffer.allocate 或 ByteBuffer.wrap : 要获得缓冲区,调用它们;
    • 2.2.4.7)用来自某个通道的数据填充缓冲区, 或用缓冲区的数据写出到通道: (干货代码——用来自某个通道的数据填充缓冲区, 或用缓冲区的数据写出到通道)
ByteBuffer buffer = ByteBuffer.allocate(RECORD_SIZE);
channel.read(buffer);
channel.position(newpos);
buffer.flip();
channel.write(buffer);

这里写图片描述


【3】文件加锁机制(多个程序同时修改同一个文件的情形)

3.1)problem + solution

  • 3.1.1)problem: 多个程序同时修改同一个文件的情形, 这些程序需要以某种方式进行通信, 不然文件很容易损坏;
  • 3.1.2)solution: 文件锁可以解决这个问题, 它可以控制对文件或文件中的某个范围的字节 的访问; (干货——文件锁的功能)

3.2)看个荔枝:假设应用程序将用户个人信息存储在一个配置文件中, 当用户同时调用两个线程操作该文件时;

  • 3.2.1)第一个线程,应该锁定该文件, 而第二个线程发现这个文件被锁定了, 它必须决策是等待直至解锁还是跳过这个写操作过程;(干货——文件加锁机制后线程如何决策)
FileChannel channel = FileChannel.open(path);
FileLock lock = channle.lock();
或
FileLock lock = channel.tryLock();

Attention): 通道是对磁盘文件的一种抽象; (干货——再次提醒通道定义,即通道是对磁盘文件的一种抽象)
这里写图片描述
这里写图片描述

对上述代码的分析(Analysis):

  • A1)第一个调用会阻塞直至可获得锁, 而第二个调用将立即返回, 要么返回锁,要么在所不可获得的情况下返回null;
  • A2)这个文件将保持锁定状态,直至这个通道被关闭, 或者在锁上调用 release 方法;

3.3)你还可以通过下面的调用锁定文件的一部分:

FileLock lock(long start, long size, boolean shared)
或
FileLock tryLock(long start, long size, boolean shared)
  • 3.3.1)如果shared 标志为 false, 则锁定文件的目的是读写, 而如果为 true, 则这是一个共享锁, 它允许多个进程从文件中读入, 并组织任何进程获得独占锁; (干货——tryLock方法中shared数据域的含义)
  • 3.3.2)并非所有的os 都支持共享锁, 因此你可能会请求共享锁的时候得到的是独占的锁。调用 FileLock 类的 isShared 方法可以查询你所持有的锁的类型; (干货——共享锁和独占锁的定义)

Attention)如果你锁定了文件的尾部, 而这个文件的长度随后增长超过了锁定的部分, 那么增长出来的额外区域是未锁定的, 要想锁定所有的字节,可以用 Long.MAX_VALUE 来表示尺寸;

3.4)要确保在操作完成时释放锁,与往常一样, 最好在一个 try 语句中执行释放锁的操作:

try(FileLock lock = channle.lock())
{access th elocked file or segment
}

对以上代码的分析(Analysis):

  • A1)查看 tryLock API, 你会发现(以下内容转自 java SE 8 API): (干货中的干货——shared标识的排他锁或共享锁与StandardOpenOption的对应关系)
public abstract FileLock tryLock(long position,long size,boolean shared)throws IOException
Parameters:
position - The position at which the locked region is to start; must be non-negative
size - The size of the locked region; must be non-negative, and the sum position + size must be non-negative
shared - true to request a shared lock, false to request an exclusive lock
  • A2)shared 属性值(false=排他锁, 而true=共享锁)
    • NonReadableChannelException - If shared is true but this channel was not opened for reading
    • NonWritableChannelException - If shared is false but this channel was not opened for writing
  • 也就是说,
    • 共享锁(shared = true): 对应的是 FileChannel channel = FileChannel.open(path, StandardOpenOption.READ)
    • 排他锁(shared = false): 对应的是FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE)
    • 以上对应关系出错的话,会抛出异常;

Attention) 文件加锁机制是依赖于os的, 下面是需要注意的:

  • A1)在某些系统中,文件加锁仅仅是建议性的, 如果一个应用未能获得锁,它仍旧可以向被另一个应用并发锁定的文件执行写操作;
  • A2)在某些系统中, 不能在锁定一个文件的同时将其映射到内存中;
  • A3)文件锁是由整个 java 虚拟机持有的。 如果有两个程序是由同一个虚拟机启动的, 那么他们不可能每一个都获得一个在同一个文件上的锁。当调用lock 或 tryLock 方法时, 如果虚拟机已经在同一个文件上持有另一个重叠的锁,那么这两个方法将抛出 OverlappingFileLockException;
  • A4)在一些系统中, 关闭一个通道会释放由 java 虚拟机持有的底层文件上的所有锁。 因此, 在同一个锁定文件上应该避免使用多个通道;(干货——在同一个锁定文件上应该避免使用多个通道)
  • A5)在网络文件系统上锁定文件时高度依赖于系统 的, 因此应该尽量避免;
    这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331599.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 函数式编程 示例_功能Java示例 第8部分–更多纯函数

java 函数式编程 示例这是第8部分&#xff0c;该系列的最后一部分称为“示例功能Java”。 我在本系列的每个部分中开发的示例是某种“提要处理程序”&#xff0c;用于处理文档。 在上一期文章中&#xff0c;我们已经使用Vavr库看到了一些模式匹配&#xff0c;并且还将故障也视…

html加css作品,我的影视作品,如何在博客园发布带有CSS样式的HTML

总结一下&#xff0c;我做过的视频&#xff1a;(顺便试试在博客园如何发HTML网页)发布网页总结&#xff1a;HTML可以正常发送&#xff0c;但最好将你要发布的html文件放在一个带有ID的div中&#xff0c;这样方便后期添加样式时通过ID添加&#xff0c;不会影响到网页中的其他布局…

FileInputStream

java.ioClass FileInputStream java.lang.Object java.io.InputStream java.io.FileInputStream 所有已实现的接口: Closeable public class FileInputStream extends InputStream FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。 Fil…

android console命令,我们可以通过两种方式进入Android的console: 1. 直接执行命令emulator -shell; 2....

Don’t use /usr 这样子编译出来的busybox才不会安装到你主机的/usr目录下。一定要选上。4 执行make编译源码. 如果编译过程中产生无法找到头文件的错误, 可指定交叉编译器用到的头文件所在路径. 如 $make -I./home/jo/tool/arm-2008q3/arm-none-linux-gnueabi/lib…

selenium 示例_Selenium测试中所需的功能和示例

selenium 示例所需功能是用于声明一组基本要求&#xff08;例如浏览器&#xff0c;操作系统&#xff0c;浏览器版本等的组合&#xff09;的类&#xff0c;以对Web应用程序执行自动跨浏览器测试。 当我们尝试通过Selenium自动化测试来自动化测试脚本时&#xff0c;我们需要考虑…

java流与文件——正则表达式

【0】README 0.1&#xff09; 本文描述转自 core java volume 2&#xff0c; 旨在理解 java流与文件——正则表达式 的相关知识&#xff1b; 0.2&#xff09; there are my original source code below, and for them , please visit https://github.com/pacosonTang/core-ja…

pandoc讲html转换为pdf,mac下利用Pandoc、LaTeX 转换markdown成html,pdf

环境所使用的插件有pandoc,tlmgr,fc-listcssbrew install pandoc由于mac ox 系统生成pdf 须要找到对应的编码集 全部还须要去下载LaTeX&#xff0c;进行安装html5使用tlmgr工具安装全部要的包先进行更新&#xff0c;若是提示所须要的字体没有找到安装gitsudo tlmgr update --se…

java程序连接kafka_Java的Kafka:构建安全,可扩展的消息传递应用程序

java程序连接kafka使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证&#xff0c;管理和保护。 今天尝试Okta。 当今的用户希望可以通过其计算机&#xff0c;手机&#xff0c;平板电脑或任何其他设备访问您的应用…

信息系html5论文,基于HTML5的智力游戏设计电子信息工程本科学生毕业论文.doc

基于HTML5的智力游戏设计电子信息工程本科学生毕业论文本科学生毕业论文(设计)题目(中文)&#xff1a;基于HTML5的智力游戏设计(英文)&#xff1a;Design of Intelligent Game Based on HTML5姓 名 xxx学 号 xxx院 (系) 电子与信息工程学院专业、年级 电子信息工程指导教师 xxx…

优先队列——左式堆

【0】README 0.1&#xff09; 本文文字描述部分转自 数据结构与算法分析&#xff0c; 旨在理解 优先队列——左式堆 的基础知识&#xff1b; 0.2&#xff09; 本文核心思路均为原创&#xff0c; 源代码部分借鉴 数据结构与算法分析 &#xff1b; 0.3&#xff09; for origin…

Class类中的getEnclosing*、getDeclared*与getDeclaringClass的区别

一、getEnclosing* 当前类在……中闭合Class<?>getEnclosingClass() 返回底层类的立即封闭类。 Constructor<?>getEnclosingConstructor() 如果该 Class 对象表示构造方法中的一个本地或匿名类&#xff0c;则返回 Constructor 对象&#xf…

java联接pg库_Java14:使用Java 14的新记录联接数据库表

java联接pg库您是否知道可以使用Java 14的预览记录功能将数据库表连接到Java Stream中&#xff1f; 阅读这篇简短的文章&#xff0c;并了解如何使用Speedment Stream ORM完成它。 我们将从如何设置您的项目开始。 建立 下载Java 14 。 转到Speedment Initializer并下载您的项目…

html5遍历集合数据,HTMLCollection集合能打印出来值,但是无法获取每一个值。

var imgs $("#pictureQueryTable img").prevObject[0].images;下图是上面这句打印出来的结果&#xff1a;console.log可以打印出来该集合的数据&#xff0c;但是无法获取该集合中的每一个值&#xff0c;打印该集合的length为0&#xff0c;所以也无法遍历该集合进行操…

优先队列——斜堆

【0】README 0.1&#xff09;本文部分内容转自  http://www.cnblogs.com/skywang12345/p/3638493.html&#xff0c; 旨在理解 优先队列——斜堆 的基础知识&#xff1b; 0.2&#xff09; for original source code , please visit https://github.com/pacosonTang/dataStruc…

Class的getResource与ClassLoader的getResource路径/问题

一、Class的getResource(String path)&#xff1a;URL 1、path 不以’/开头时&#xff0c;默认是从此类所在的包下取资源&#xff1b; 2、path 以’/开头时&#xff0c;则是从ClassPath根下获取&#xff1b; System.out.println(Test.class.getResource("")); Syste…

java 轻量级文件数据库_Java:如何创建轻量级数据库微服务

java 轻量级文件数据库基于云的Java数据库应用程序的数量每分钟都在增加。 许多组织部署了数百甚至数千个微服务实例。 但是&#xff0c;相对于运行时环境&#xff0c;大多数应用程序会带来惊人的不必要开销。 反过来&#xff0c;这会使应用程序运行更慢&#xff0c;运行成本更…

html中显示shell脚本的输出,网页从shell脚本中输入并显示结果

首先&#xff0c;不是在BASH脚本中使用$USERNAME。 $USERNAME是一个包含当前用户名的BASH变量。实际上&#xff0c;在BASH中使用UPPERCASE变量通常是一个糟糕的主意。大多数BASH环境变量都是大写字母&#xff0c;可能会导致混淆。让你的变量小写是个好习惯。此外&#xff0c;因…

优先队列——二项队列(binominal queue)

【0】README 0.1&#xff09; 本文文字描述部分转自 数据结构与算法分析&#xff0c; 旨在理解 优先队列——二项队列&#xff08;binominal queue&#xff09; 的基础知识&#xff1b; 0.2&#xff09; 本文核心的剖析思路均为原创&#xff08;insert&#xff0c;merge和del…

Class的getName、getSimpleName与getCanonicalName的区别

一、getName 除了数组外&#xff0c;其他的类都是输出类全名以 String 的形式返回此 Class 对象所表示的实体&#xff08;类、接口、数组类、基本类型或 void&#xff09;名称。 1、此类对象表示的是非数组类型的引用类型&#xff0c; 返回该类的二进制名称&#xff0c;Java…

apache.camel_Apache Camel 3.1 –即将推出更多骆驼核心优化

apache.camel希望一切都很好&#xff0c;您可以安全进入2020年。 Camel团队已经在忙于开发下一个Camel 3.1版本。 目标之一是继续优化骆驼核心&#xff0c;这一次我们花了一些时间来寻找路由引擎中的一些热点。 我们所研究的方面之一也是在Camel路由的每个消息中发生的对象分…