...文件映射有个需要注意的问题,就是你无法确保他被释放了。
也就是只有映射的内存被回收,文件才会被释放。否则其他进程访问就是被锁状态。
所以这个对于一个进程一个文件。如果多个进程访问一个文件,还是不是很适合。
最近看了文件内存映射。在NIO中,使用起来很方便。
文件通过内存映射以后,访问速度自然是提高了。
当然也有很多问题,现在我们来看看NIO中的内存映射文件。
public abstract class FileChannel extends
AbstractChannel implements ByteChannel, GatheringByteChannel, ScatteringByteChannel {
// This is a partial API listing
public abstract MappedByteBuffer map (MapMode mode, long position,long size)
public static class MapMode {
public static final MapMode READ_ONLY
public static final MapMode READ_WRITE
public static final MapMode PRIVATE
}
}
内存映射文件,是通过一个FileChannel来完成的,返回的MappedByteBuffer,也是一种ByteBuffer。这里有三种映射模式。主要针对这三种映射模式的差异说说。
根据map函数,我们得知,我们可以映射部分文件,也可以全部映射。
如果请求的大小,size超出文件,那么文件会相应的增长以对应映射。如果是Integer.MAX_VALUE,那么文件就会达到2.1GB
当然,如果你请求的只是一个只读文件,而你的size超出文件大小,那么就会抛出IOException。
对于 MapMode的前两种,READ_ONLY和READ_WRITE来说,都很好理解。要注意的而是,如果在一个只读文件上使用READ_WRITE,是要抛出NonWritableChannelException异常的。
MapMode.PRIVATE模式很有意思,称为“写时拷贝”(copy-on-write)的映射。这是操作系统中常用的技术。比如创建一个子进程时,子进程共享父进程的地址空间,当子进程修改空间的时候,才会拷贝要修改的部分。对于PRIVATE模式来说,只有使用put函数的时候,才会去拷贝。可能拷贝某一页或者几页。假设此时有其他的映射,是看不到本次put后的改变的。也就是说,私有的。
注意,没有unmap函数,也就是说,一旦map成功,那么即使FileChannel被关闭,映射依然存在,只有映射对应的MappedByteBuffer内存被回收,映射才算取消。
MappedByteBuffer直接反应磁盘文件,如果磁盘文件结构或大小改变,那么可能就无法访问文件。
MappedByteBuffer 直接内存访问,并不占用虚拟机内存。
MappedByteBuffer 也是ByteBuffer,所以可以用于SocketChannel之类的通道读写。
对于MappedByteBuffer还有几个函数可以介绍下。
public abstract class MappedByteBuffer extends ByteBuffer {
// This is a partial API listing
public final MappedByteBuffer load( )
public final boolean isLoaded( )
public final MappedByteBuffer force( )
}
load函数用于从磁盘文件加载到内存。这个操作将会引起大量系统调用。慎用。一旦加载完成,再次访问文件,就和访问内存一样快。但是,这些都起决于操作系统底层调用。
isLoaded函数是用来判断文件是否完全加载到内存。
force则是强制同步内存文件到磁盘。也就是把MappedByteBuffer中的更改应用到磁盘中。这里包括了文件的元数据(最近一次访问,作者,创建时间等)。当然,如果是READ_ONLY或者PRIVATE模式,则不起作用。
下面这个例子,使用内存映射文件,生成一个HTTP应答格式的文件。我们来看看这个例子:
package shaoxin.nio;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
/***
* Dummy HTTP server using MappedByteBuffer.
* Given a filename on the command line, pretend to be
* a web server and generate an HTTP response containing
* the file content preceded by appropriate headers The
* data is send with a gathering write.
*
* @author Ron Hitchens (ron@ronsoft.com)
*
*/
public class MappedHttp {
private static final String OUTPUT_FILE="MappedHttp.out";
private static final String LINE_SEP = "\r\n";
private static final String SERVER_ID = "Server: Ronsoft Dummy Server";
private static final String HTTP_HDR =
"HTTP/1.0 200 OK" + LINE_SEP + SERVER_ID + LINE_SEP;
private static final String HTTP_404_HDR =
"HTTP/1.0 404 Not Found" + LINE_SEP + SERVER_ID + LINE_SEP;
private static final String MSG_404 = "Cound not open file: ";
public static void main(String[] args) throws Exception{
if(args.length < 1){
System.err.println("Usage:filename");
return;
}
String file = args[0];
ByteBuffer header = ByteBuffer.wrap(bytes(HTTP_HDR));
ByteBuffer dynhdrs = ByteBuffer.allocate(128);
ByteBuffer[] gather = {header,dynhdrs,null};
String contentType = "unknown/unknown";
long contentLength = -1;
try{
FileInputStream fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
MappedByteBuffer filedata =
fc.map(MapMode.READ_ONLY, 0, fc.size());
gather[2] = filedata;
contentLength = fc.size();
contentType = URLConnection.guessContentTypeFromName(file);
}catch(IOException e){
//file could not be opend; report problem
ByteBuffer buf = ByteBuffer.allocate(128);
String msg = MSG_404 + LINE_SEP;
buf.put(bytes(msg));
buf.flip();
//Use the HTTP error response
gather[0] = ByteBuffer.wrap(bytes(HTTP_404_HDR));
gather[2] = buf;
contentLength = msg.length();
contentType = "text/plain";
}
StringBuffer sb = new StringBuffer();
sb.append("Content-Length: " + contentLength);
sb.append(LINE_SEP);
sb.append("Content-Type: ").append(contentType);
sb.append(LINE_SEP).append(LINE_SEP);
dynhdrs.put(bytes(sb.toString()));
dynhdrs.flip();
FileOutputStream fos = new FileOutputStream(OUTPUT_FILE);
FileChannel out = fos.getChannel();
// All the buffers have been prepared , write them out
while(out.write(gather) > 0){
//Empty body; loop until all buffers are empty
}
out.close();
System.out.println("output written to "+ OUTPUT_FILE);
}
//Convert a String to its constituent bytes
//from the ASCII character set
private static byte[] bytes(String string)throws Exception {
return (string.getBytes("US-ASCII"));
}
}
这里结合使用了scatter/gather技术。
分享到:
相关推荐
在Java NIO中,内存映射文件(MappedByteBuffer)是一个重要的特性,它允许将文件直接映射到内存中,以便于快速访问和修改文件内容。这一特性不仅提高了读写效率,而且还能用于进程间通信(IPC)。 内存映射文件的...
在标题和描述中提到的“文件内存映射缓冲区”是Java处理大文件的一种高级技术,它允许将文件直接映射到虚拟内存中,从而使得程序可以直接对文件进行读写操作,而无需通过传统的I/O流。 MappedByteBuffer的使用涉及...
7. **内存映射文件(Memory-Mapped Files)**:通过映射文件到内存,提供了一种高效的大文件处理方式,使得文件可以直接被内存操作。 8. **效率比较**:在特定场景下,`DirectByteBuffer`可能比`HeapByteBuffer`更...
Java NIO-Buffer-内存映射文件I/O - **主要内容**:演示如何利用Buffer实现内存映射文件I/O操作。 - **学习目标**:掌握高效的文件访问技术。 #### 21. Java NIO-Selector-概述 - **主要内容**:介绍Selector...
### Java NIO 处理超大数据文件的知识点详解 ...综上所述,使用Java NIO处理超大数据文件时,关键是利用好内存映射文件技术和合理的数据读取策略,通过适当的分块和数据解析方法,可以有效地提升读取速度和处理能力。
总结,Java NIO提供了一套高效、灵活的文件写入机制,包括通道、缓冲区、内存映射文件和选择器等组件。了解并掌握这些特性,能帮助开发者编写出更高效的I/O程序,特别是对于处理大量并发I/O操作的场景。在实际编程中...
除了以上提到的 Buffer 类型之外,Java NIO 还提供了一个特殊的 Buffer 类型——`MappedByteBuffer`,用于表示内存映射文件。这种方式能够提高文件的读写效率,但由于其实现较为复杂,本概述中不做详细介绍。 #### ...
4. **内存映射文件**:`MappedByteBuffer`允许将文件直接映射到内存,提供了极高的读写速度。 然而,尽管Java NIO提供了很多优势,但在实际使用中,开发者还需要注意一些潜在的问题,如内存管理(缓冲区过大可能...
4. **FileChannel**:用于文件的读写,可以实现大文件的高效传输,支持内存映射(Mmap)技术,能直接将文件映射到内存中。 5. **SocketChannel**:用于网络通信,可以建立TCP连接,进行非阻塞的读写。在`NIOServer....
4. **内存映射文件(MappedByteBuffer)**:Java NIO提供了一种高效访问大文件的方式,即内存映射文件。通过映射文件到内存,可以直接通过内存操作文件,减少了磁盘I/O的开销。 5. **非阻塞模式**:与传统的阻塞IO...
综上所述,“Large-File-Processing-master_javanio_java大文件处理_”项目涵盖了Java NIO在大文件处理中的核心技术和最佳实践,是学习和研究Java高效处理大文件的宝贵资源。通过深入理解这些知识点,并结合项目中的...
6. **内存映射文件(Memory-Mapped Files)**: NIO允许将文件直接映射到内存,使得读写文件就像操作普通缓冲区一样快速。通过MappedByteBuffer类,可以直接在内存中对文件进行操作,提高大文件处理的性能。 7. **...
4. **文件通道(File Channel)**:文件通道是直接与文件系统交互的通道,支持映射文件到内存(Memory-Mapped File)进行高速读写。 5. **网络通道(Network Channels)**:如SocketChannel和ServerSocketChannel,...
例如,FileChannel用于文件操作,它支持映射文件到内存(Memory-Mapped File)以提高读写速度;SocketChannel则用于网络通信,可以实现TCP连接的读写。 第5节会进一步深入,探讨通道的使用技巧和高级特性。这可能...
4. **文件系统操作**:NIO提供了一些新的类,如FileChannel、FileLock等,用于执行文件系统操作,如映射文件到内存、文件锁定等。 在实际应用中,NIO常用于服务器端的高并发场景,例如,开发网络服务器时,可以使用...
8. **内存映射文件(Memory-Mapped File)**: 使用MappedByteBuffer,NIO可以将文件映射到内存,使得文件操作如同操作内存一样快速,特别适合大数据处理。 在实际应用中,Java NIO通常用于高性能的服务器编程,...