《Java核心技术卷二》笔记(二)文件操作和内存映射文件

文件操作

上一篇已经总结了流操作,其中也包括文件的读写。文件系统除了读写以为还有很多其他的操作,如复制、移动、删除、目录浏览、属性读写等。在Java7之前,一直使用File类用于文件的操作。Java7提供了Path,Paths,Files,FileSystem等类,使文件操作变得简单和全面。此外还有很多第三方库也提供了文件操作的便捷类如common.io中的FileUtils类,Ant api提供的FileSet等类。

1.File类的使用

Java7之前版本中,File类即代表了路径对象也封装了文件的绝大部分操作。

  File

    • File(String pathname)
    • File(String parent, String child)
    • File(File parent, String child)
    • File(URI uri)
    • URI toURI()
    • Path toPath()
    • String getPath()/toString()
    • String getName()  最后一段
    • String getParent()
    • File getParentFile()
    • String getAbsolutePath()
    • File getAbsoluteFile()
    • String getCanonicalPath()
    • File getCanonicalFile()
    • boolean isAbsolute()
    • boolean isFile()
    • boolean isDirectoy()
    • boolean exists()
    • long length()
    • boolean createNewFile()
    • boolean delete()
    • void deleteOnExit()
    • boolean mkdir()
    • boolean mkdirs()
    • boolean renameTo(File dst)
    • File createTempFile(String prefix, String suffix, File directory)
    • File createTempFile(String prefix, String suffix)
    • String[] list()
    • String[] list(FilenameFilter filter)
    • File[] listFiles()
    • File[] listFiles(FilenameFilter filter)
    • File[] listFiles(FileFilter filter)
    • boolean isHidden()
    • long lastModified()
    • boolean canRead()
    • boolean canWrite()
    • boolean canExecute()
    • boolean setLastModified(long time)
    • boolean setReadOnly()
    • boolean setWritable(boolean writable, boolean ownerOnly)
    • boolean setWritable(boolean writable)
    • boolean setReadable(boolean readable, boolean ownerOnly)
    • boolean setReadable(boolean readable)
    • boolean setExecutable(boolean executable, boolean ownerOnly)
    • boolean setExecutable(boolean executable)
    • long getTotalSpace()    返回文件所在分区的总大小
    • long getFreeSpace()
    • long getUsableSpace()

2.Path接口和Files类的使用

Java7中提供了Path接口代表了文件系统路径对象,而Files类封装了文件系统的绝大部分操作。

基本用法 

Paths      使用默认的FileSystem类生成Path对象

    • static Path get(String first, String... more)     拼出路径
    • static Path get(URI uri)    将URI对象转化成Path对象

File类的Path toPath()方法也可以将File对象转化成Path对象。 

Path  路径对象

    • File toFile()
    • URI toUri()
    • String toString()
    • Path normalize()     移除., ..等冗余路径元素
    • Path toAbsolutePath()   返回等价的绝对路径
    • Path relativize(Path other)   返回相对于other的相对路径
    • Path getParent()    返回父路径
    • Path getFileName()    返回路径最后一个部件
    • Path getRoot()    返回根路径
    • Path resolve(Path/String other)     如果other为绝对路径,返回other;否则,将other接在this路径的后面返回。
    • Path resolveSibling(Path/String other)   如果other为绝对路径,返回other;否则,将other接在this的父路径后面返回。
    • boolean startsWith(Path/String other)
    • boolean endsWith(Path/String other)

files类方法中涉及的Option选项用的是不定参数,同时使用多个选项的方式为:

  Files.copy(src, dst, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);

Files

    • static byte[]  readAllBytes(Path path)     不太适合大文件
    • static List<String> readAllLines(Path path, Charset cs)    不太适合大文件
    • static Path write(Path path, byte[] bytes,  OpenOption...options)       如StandardOpenOption.APPEND|READ|WRITE....
    • static Path write(Path path, Iterable<? extends CharSequence>, Charset cs, OpenOption... options)
    • static InputStream newInputStream(Path p, OpenOption...options)     将文件打开为输入流
    • static OutputStream newOutputStream(Path p, OpenOption...options)   将文件打开为输出流
    • static BufferedReader newBufferedReader(Path path, Charset cs)
    • static BufferedWriter newBufferedWriter(Path path, Charset cs, OpenOption...options)
    • static Path copy(Path src, Path dst, CopyOption...options)         如StandardCopyOption.REPLACE_EXISTING|COPY_ATTRIBUTES|ATOMIC_MOVE
    • static Path copy(Path src, OutputStream os )
    • static Path copy(InputStream src, Path dst, CopyOption...options)
    • static Path move(Path src, Path dst, CopyOption...options)
    • static void delete(Path path)     删除的文件不存在会抛出异常,下面这个方法更省事
    • static boolean deleteIfExists(Path path)
    • static Path createDirectory(Path dir, FileAttribute<?> ...attrs)   不会自动创建中间目录
    • static Path createDirectorys(Path dir, FileAttribute<?> ...attrs)    自动创建中间目录
    • static Path createFile(Path path, FileAttribute<?> ...attrs)    不会自动创建中间目录,文件已经存在也会抛出异常,检查文件存在和创建文件是原子操作,其他程序在这个过程中也无法创建文件。
    • static Path createTempFile(Path path, String prefix, String suffix, FileAttribute<?>...attr)  创建临时文件,可以固定文件名前缀或(和)后缀,中间部分随机生成。未指定Path的重载方法会自动在适当的临时文件目录中创建临时文件。
    • static long size(Path path)   文件字节数
    • static boolean exists(Path path, LinkOption...option) 
    • static boolean noExists(Path path, LinkOption...option)
    • static boolean isHidden(Path path)
    • static boolean isReadable(Path path)
    • static boolean isWritable(Path path)
    • static boolean isExecutable(Path path)
    • static boolean isRegularFile(Path path, LinkOption...option)
    • static boolean isDirectory(Path path, LinkOption...option)
    • static boolean isSymbolicLink(Path path)
    • static UserPrincipal getOwner(Path path, LinkOption...option)
    • static Path setOwner(Path path, UserPrincipal owner)
    • static Set<PosixFilePermission> getPosixFilePermissions(Path path, LinkOption...option)
    • static Path setPosixFilePermissions(Path path, Set<PosixFilePermission> perms)
    • static FileTime getLastModifiedTime(Path path, LinkOption...option)
    • static Path setLastModifiedTime(Path path, FileTime time)
    • static <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options)
    • static Map<String,Object> readAttributes(Path path, String attributes, LinkOption... options)
    • static Object getAttribute(Path path, String attribute, LinkOption...options)
    • static Path setAttribute(Path path, String attribute, Object value, LinkOption...options)
    • static DirectoryStream<Path> newDirectoryStream(Path path)    生成的DirectoryStream类实现了Iterable<T>接口,可以用来迭代目录内容
    • static DirectorySteram<Path> newDirectoryStream(Path path, String glob)    生成的DirectoryStream可以迭代与glob模式匹配的目录内容(glob模式见后面)
    • static DirectoryStream<Path> newDirectoryStream(Path path, Filter<? super Path> filter)  生成的DirectoryStream可以迭代与过滤器匹配的目录内容
    • static Path walkFileTree(Path path, FileVisitor<? super Path> visitor)     遍历目录内容
    • static Path walkFileTree(Path path, Set<FileVisitOption> options, int maxDepth, FileVisitor<? super Path> visitor)

文件属性

  通过读取文件属性对象可以获取文件的各种属性信息(直接使用Files类的一些方法也可以获取或设置部分属性信息)。

  BasicFileAttributes接口描述了文件的通用属性(FileTime类型的创建/最后一次访问/最后一次修改时间,常规文件/目录/符号链接,文件大小,文件主键),通用属性获取方式为: BasicFileAttributes attributes=Files.readAttributes(path, BasicFileAttributes.class);

    Posix兼容文件系统还可以获取Posix属性:PosixFileAttributes attributes=Files.readAttributes(path, PosixFileAttributes.class);

  PosixFilePermission为枚举类型,对应Posix的9种权限。

  BasicFileAttributes

    • FileTime creationTime()
    • FileTime lastAccessTime()
    • FileTime lastModifiedTime()
    • boolean isRegularFile()
    • boolean isDirectory()
    • boolean isSymoblicLink()
    • boolean isOther()  上面三种类型都不是
    • long size()
    • Object fileKey()   文件唯一标识

  PosixFileAttributes  implements  BasicFileAttributes

    • UserPrincipal owner()
    • UserPrincipal group()
    • Set<PosixFilePermission> permissions()

目录迭代

File类的list方法在目录包含大量的文件时效率较低,Files提供了改进的方法Directory newDirectoryStream(Path dir) 可以迭代当前目录中的对象(不包含子目录中对象)。该方法还有一个支持glob模式的重载和一个支持过滤器的重载。

Glob模式

    • *  当前目录中匹配0个或多个字符
    • **    所有子目录中匹配0个或多个字符
    • ?  匹配一个字符
    • [...]  匹配一个字符集合,可用连字符 - 和取反符 ‘ ,如[0-9A-Za-z], [‘0-9]
    • {.. , ..}  匹配由 , 分隔的任意选项
    • \  转义glob特殊字符
     DirectoryStream<Path> iter=Files.newDirectoryStream(Paths.get("H://zipTest"));
        DirectoryStream<Path> iter1=Files.newDirectoryStream(Paths.get("H://zipTest"),"*.txt");

        DirectoryStream<Path> iter2=Files.newDirectoryStream(Paths.get("H://zipTest"),new DirectoryStream.Filter<Path>(){
            @Override
            public boolean accept(Path entry) throws IOException {
                return !Files.isDirectory(entry);
            }});

        System.out.println("---all---");
        for(Path p: iter)
            System.out.println(p.toString());

        System.out.println("---*.txt---");
        for(Path p: iter1)
            System.out.println(p.toString());

        System.out.println("---only file---");
        for(Path p: iter2)
            System.out.println(p.toString());

目录遍历

遍历目录中以及所有子目录中所有项目,使用walkFileTree方法,该方法需要传入一个FileVisitor接口的对象。SimpleFileVisitor是一个实现了该接口的便捷类,该类中visitFileFailed方法会抛出异常终止遍历,其他方法什么都不做。

FileVisitor<T>

    • FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)      一个目录被处理前被调用
    • FileVisitResult postVisitDirectory(T dir, IOException exc)     一个目录被处理后被调用
    • FileVisitResult visitFile(T file, BasicFileAttributes attrs)    遇到一个文件时调用(T为Path)
    • FileVisitResult visitFileFailed(T file, IOException exc)   访问文件发生错误时调用,如无权限

walkFileTree遍历时会读取项目的属性用来判断该项目是目录还是文件,读取到的属性值就顺便传给FileVisitor的方法,FileVisitor的方法里就不需要手动去读属性了。

FileVisitor的每个方法都返回FileVisitResult枚举,指示如何进行后续操作。

  FileVisitorResult

    • CONTINUE      继续访问下一个项目
    • TERMINATE   终止遍历
    • SKIP_SUBTREE   跳过这个目录下的所有子项,继续遍历
    • SKIP_SIBLINGS  跳过这个目录的所有平级兄弟项目,继续遍历
        Files.walkFileTree(Paths.get("H://zipTest"), new SimpleFileVisitor<Path>()
        {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException
            {
                System.out.println(dir.toString());
                return FileVisitResult.CONTINUE;
            }
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
            {
                System.out.println("\t"+file.toString());
                return FileVisitResult.CONTINUE;
            }
            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
            {
                return FileVisitResult.CONTINUE;
            }
        });

zip文件系统

Path、Files等类默认都是使用的当前操作系统的磁盘文件系统类型,也可以使用其他类型的文件系统。

FileSystems.newFileSystem(xxx)方法可以创建一个文件内的文件系统,然后使用和普通文件系统一样的方式操作该文件的内容。  (基于一个文件创建文件系统时会遍历 FileSystemProvider的installedProviders方法返回的所有FileSystemProvider,查找一个能创建该文件系统的FileSystemProvider,没有找到的话还查找ClassLoader能加载的文件系统...)

直接用Paths.get(xxx)方法获取是在默认文件系统里的路径(等价于FileSystems.getDefault().getPath(xxx); ),而使用FileSystem对象的getPath()方法获取的路径就是该文件系统中的路径。

        FileSystem fs=FileSystems.newFileSystem(Paths.get("ziptest.zip"), null);
        Path copyFile=Paths.get("copyfile.txt");     Files.deleteIfExists(copyFile);
        Files.copy(fs.getPath("textfile.txt"), copyFile);

        Files.walkFileTree(fs.getPath("/"), new SimpleFileVisitor<Path>(){
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException
            {
                System.out.println(file.toString());
                return FileVisitResult.CONTINUE;
            }
        });     fs.close();

3.底层的文件系统

FileSystems

FileSystem

留坑待填...

内存映射文件

内存映射文件只指将整个文件或者文件的一部分映射到内存中,这个文件就可以像内存数组一样访问。内存映射速度比带缓存的流还要快一点(带缓冲的流可以极大提高读写速度)。内存映射适用于需要随机访问大文件,对应顺序对入的中小文件没必要使用。

内存映射文件会用到FileChannel类,对文件的读写都转化成了对内存缓冲区的操作。内存映射文件的操作:首先是建立文件通道,然后调用map方法获取映射的内存缓冲区,最后操作内存缓冲区即可(缓冲区中的更改会在适当的时候和通道关闭时写回存储设备)。

FileChannel类是对磁盘文件的一种抽象,读写操作都是与缓冲区交互,主要用在内存映射,文件加锁机制,以及文件间快速数据传递等操作系统特性。

  FileChannel

    • static FileChannel open(Path path, OpenOption... options)    也使用Files类介绍中提到的StandardOpenOption
    • static FileChannel open(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs)
    • long size()     文件大小
    • long position()   返回文件指针位置
    • void position(long pos)    设置文件指针位置
    • void force(boolean metaData)    强制将文件的变更同步到存储设备
    • FileChannel truncate(long size)     截断
    • int read(ByteBuffer dst)...    从通道读入内容到缓冲区
    • int write(ByteBuffer src)...     将缓冲区内容写入通道
    • long transferTo(xxx)
    • long transferFrom(xxx)
    • MappedByteBuffer map(MapMode, long startposition, long size)    MapMode.READ_ONLY|READ_WRITE|PRIVATE
    • void close()     关闭通道,如果有可写的内存映射,其中的更改会写回存储设备

 FileInputStream

    • FileChannel getChannel()

   FileOutputStream

    • FileChannel getChannel()

   RandomAccessFile

    • FileChannel getChannel()

    

        CRC32 crc=new CRC32();
        CRC32 crc1=new CRC32();

        FileChannel fc=FileChannel.open(Paths.get("copyfile.txt"),StandardOpenOption.READ,StandardOpenOption.WRITE);
        MappedByteBuffer buffer=fc.map(MapMode.READ_WRITE, 0, fc.size());

        //随机访问缓冲区
        for(int p=0; p<buffer.limit(); p++)
        {
            int c=buffer.get(p);
            crc.update(c);
        }

        //顺序访问缓冲区
        for(int p=0; p<buffer.limit(); p++)
        {
            int c=buffer.get();
            crc1.update(c);
        }

        System.out.println(Long.toHexString(crc.getValue()));
        System.out.println(Long.toHexString(crc1.getValue()));

内存缓冲区

前面的例子已经用到了缓冲区类,现在详述总结一下这些类。缓冲区类其实就是相同类型数据构成的一个数组,再加上对缓冲区操作的一些方法。

缓冲区类的共同特点:

  • 都有一个固定的容量,不可改变。
  • 有一个读写位置,下一个值在此位置读写。
  • 有一个界限,超过它之后读写就没有意义。
  • 一个可选的标记位置,可以移动到该位置重复读入或写出。
  • 各个位置的关系为:0<=标记<=读写位置<=界限<=容量
  • 写和读操作在缓冲区上反复交替进行,缓冲区被循环使用。

缓冲区类一般都使用静态的allocate()方法创建或者使用warp()方法将一个数组包装成缓冲区对象。

使用过程:

  • 重置:调用clear()方法,缓冲区的位置=0,界限=容量。
  • 写入:然后向缓冲区写入数据,直到缓冲区位置=容量(占满)或者数据已经写完。
  • 反转:调用flip()方法,缓冲区界限=位置,位置=0
  • 读取:从缓冲区读取数据,直到位置=界限。然后再重置,一直循环...

读写的过程中可以调用rewind()将位置重置为0,重头读写。或者调用mark()/reset()使用标记,重新读写部分内容。

java中缓冲区都继承自Buffer抽象类,继承关系如下(不包括StringBuffer)。

  Buffer

    • ByteBuffer

      • MappedByteBuffer
    • CharBuffer
    • DoubleBuffer
    • FloatBuffer
    • IntBuffer
    • LongBuffer
    • ShortBuffer

 

  Buffer

    • Buffer clear()   重置(读写位置=0,界限=容量),准备写入
    • Buffer flip()    反转(界限=读写位置,新读写位置=0),准备读取
    • Buffer rewind()   界限不变,读写位置=0,可以重头读写
    • Buffer mark()   在当前读写位置设置标记
    • Buffer reset()   重置读写位置到标记,可以重新标记后的内容
    • int remaining()    剩余可读或写的数量,即 limit-position
    • boolean hasRemaining()  是否还可读或可写。即 position<limit ?
    • int position()   返回当前的读写位置
    • Buffer position(int newpos)   改变读写位置
    • int capacity()    返回缓冲区容量
    • int limit()    返回限制位置
    • Buffer limit(int limit)  设置限制位置
    • boolean hasArray()    该Buffer是否是包装了一个数组
    • Object array()     返回该Buffer包装的数组
    • int arrayOffset()   如果包装了数组,返回数组被用作缓冲的起始位置(可以将数组的一部分包装成缓冲区)。
    • boolean isDirect()
    • boolean isReadOnly()

最最常用的缓冲区类ByteBufferCharBuffer已经在前一篇中写过 : http://www.cnblogs.com/pixy/p/4779820.html

  MappedByteBuffer

    • boolean isLoaded()
    • MappedByteBuffer load()
    • MappedByteBuffer force()

 

文件加锁机制

文件加锁机制可以防止多个同时执行的程序修改同一个文件导致文件被破坏。文件加锁也通过FileChannel类实现。

文件锁是由整个Java虚拟机持有的,由同一个虚拟器启动的不同Java进程不能同时独占锁定同一个文件。

文件加锁机制依赖于底层文件系统,有些系统无法锁定,有些系统锁定后不能映射,有些系统关闭一个通道会是否对应文件上所有的锁(避免在一个文件上使用多个通道),网络文件系统尽量避免使用锁。

  FileChannel

    • FileLock lock()    阻塞直到获得锁
    • FileLock lock(long position, long size, boolean shared)   锁定文件的一部分,阻塞直到获得锁(锁定区域之后新增内容不会被锁,除非size设为Long.MAX_VALUE), shared设为true时获得共享税(允许多个进程读入,阻止任何进程独占)。
    • FileLock tryLock()     立刻返回,无法获得锁时返回null
    • FileLock tryLock(long position, long size, boolean shared)

  FileLock

    • void close()
    • boolean isShared()    返回是否为共享锁
时间: 2024-12-05 19:07:21

《Java核心技术卷二》笔记(二)文件操作和内存映射文件的相关文章

随机访问文件RandomAccessFile 与 内存映射文件MappedByteBuffer

一.RandomAccessFile RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必相同:但是其大小和位置必须是可知的.但是该类仅限于操作文件. RandomAccessFile不属于InputStream和OutputStream类系的.实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系

笔记:I/O流-内存映射文件

内存映射文件时利用虚拟内存实现来将一个文件或者文件的一部分映射到内存中,然后整个文件就可以当作数组一样的访问,这个比传统的文件操作要快得多,Java 使用内存映射文件首先需要从文件中获取一个channel(通道),通道时磁盘文件的一个抽象,他使得我们可以访问诸如内存映射.文件加锁机制以及文件间快速数据传递等操作系统特性,然后通过调用 FileChannel 类的 map 方法从这个通道获取一个映射块(ByteBuffer),然后就可以读取/写入文件块内容,map 支持的模式有如下: FileCh

JAVA I/O(三)内存映射文件

<Java编程思想>中对内存映射文件有详细的介绍,此处仅做简单记录和总结.内存映射文件允许创建和修改因为太大而不能放入内存的文件. 1. 内存映射文件简单实例 import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class LargeMappedFiles { priv

【WIN32进阶之路】:内存映射文件

第一章:源起  遇到一个问题,如果一个客户数据文件有2g大,客户要通过界面查询文件中的数据并用列表控件显示数据,要怎么处理这个文件才能让应用程序不会长时间无响应,客户感觉不到程序的卡顿? 第二章:解决之道 第一反应是用内存映射文件处理大文件,将文件分成数次映射至内存地址空间,避免一次性缓冲整个文件带来的界面长时间无响应,并将暂时不用的内存映射文件取消映射,客户是用列表控件进行显示,那就可以在首次加载的时候只加载第一页的内容就进行显示,之后在缓冲下一页的内容,当用户查看中间页面的内容时可以缓冲将当

内存映射文件

一段内存地址空间,映射着物理存储器上一个已经存在于磁盘上的文件.在对该文件进行操作之前必须首先对文件进行映射.使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作. 内存映射文件,是由一个文件到一块内存的映射.Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping). API: HANDLE CreateFileMapping(HANDLE hFile,LPSECURITY_ATTRIBUTES lpFileMappingAttribute

C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转

原文:C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped 转 节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作系统中地位相当.实际上,任何想要共享数据的通信模型都会在幕后使用它. 内存映射文件究竟是个什么?内存映射文件允许你保留一块地址空间,然后将该物理存储映射到这块内存空间中进行操作.物理存储是文件管理,而内存

VC++ 中使用内存映射文件处理大文件

摘要: 本文给出了一种方便实用的解决大文件的读取.存储等处理的方法,并结合相关程序代码对具体的实现过程进行了介绍. 引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile().ReadFile()和MFC提供的CFile类等.一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB.几百GB.乃至几TB的海量存储,再以通常的文件处理方法进行处

MemoryMappedFile 内存映射文件 msdn

http://msdn.microsoft.com/zh-cn/library/dd997372%28v=vs.110%29.aspx 内存映射文件 .NET Framework 4.5 其他版本 1(共 1)对本文的评价是有帮助 - 评价此主题 内存映射文件包含虚拟内存中文件的内容. 利用文件与内存空间之间的映射,应用程序(包括多个进程)可以通过直接在内存中进行读写来修改文件. Managing Memory-Mapped Files in Win32 in the MSDN Library.

C# .Net 多进程同步 通信 共享内存 内存映射文件 Memory Mapped

节点通信存在两种模型:共享内存(Shared memory)和消息传递(Messages passing). 内存映射文件对于托管世界的开发人员来说似乎很陌生,但它确实已经是很远古的技术了,而且在操作系统中地位相当.实际上,任何想要共享数据的通信模型都会在幕后使用它. 内存映射文件究竟是个什么?内存映射文件允许你保留一块地址空间,然后将该物理存储映射到这块内存空间中进行操作.物理存储是文件管理,而内存映射文件是操作系统级内存管理. 优势:     1.访问磁盘文件上的数据不需执行I/O操作和缓存