熟悉nio的朋友都知道,MappedByteBuffer大幅提高了IO效率,但却有个比较严重的问题。
看如下测试代码:
public class TestMappedByteBufferDeleteFile {
File testFile;
/**
* 创建测试文件
* @throws URISyntaxException
* @throws IOException
*/
@Before public void createFile() throws URISyntaxException, IOException {
testFile = new File(this.getClass().getResource(".").getPath() + "/test.txt");
if(!testFile.exists()) {
testFile.createNewFile();
}
FileOutputStream fos = new FileOutputStream(testFile);
fos.write("TestMappedByteBufferDeleteFile".getBytes());
fos.close();
}
/**
* 测试使用MappedByteBuffer后直接删除文件
* @throws IOException
*/
@Test public void testDeleteFile() throws IOException {
map(testFile);
testFile.delete();
Assert.assertEquals(false, testFile.exists());
}
/**
* 映射文件,返回MappedByteBuffer
* @param file
* @return
* @throws IOException
*/
public MappedByteBuffer map(File file) throws IOException {
FileInputStream in = new FileInputStream(file);
FileChannel ch = in.getChannel();
MappedByteBuffer buffer = ch.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
ch.close();
in.close();
return buffer;
}
}
Junit运行,结果断言失败,文件没删除成功。
解决方法是加上如下代码:
/**
* 清理MappedByteBuffer句柄
* @param buffer
*/
public static void clean(final MappedByteBuffer buffer) {
if (buffer == null) {
return;
}
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
try {
Method getCleanerMethod = buffer.getClass().getMethod(
"cleaner", new Class[0]);
if (getCleanerMethod != null) {
getCleanerMethod.setAccessible(true);
Object cleaner = getCleanerMethod.invoke(buffer,
new Object[0]);
Method cleanMethod = cleaner.getClass().getMethod(
"clean", new Class[0]);
if (cleanMethod != null) {
cleanMethod.invoke(cleaner, new Object[0]);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
然后将testDeleteFile() 作如下修改:
/**
* 测试使用MappedByteBuffer后调用clean方法后删除文件
* @throws IOException
*/
@Test public void testDeleteFile() throws IOException {
MappedByteBuffer buffer = map(testFile);
clean(buffer);
testFile.delete();
Assert.assertEquals(false, testFile.exists());
}
再运行Junit,成功!
之所以出现这种情况,是因为文件句柄没有被清除,还被MappedByteBuffer占据,导致外部无法操作。而要清除,得等GC收集了。
不知Sun何时可以提供MappedByteBuffer的unmap!
另请关注该链接:http://bugs.sun.com/view_bug.do?bug_id=4724038
分享到:
相关推荐
例如,Java中的`java.io`包提供了`File`类用于文件的创建、删除和重命名,而`BufferedReader`和`BufferedWriter`则用于文本文件的读写。 2. **数据解析**:数据解析是将文件内容转换为可操作结构的过程。这可能涉及...
6. **内存映射文件(Memory-Mapped File)**:Java的MappedByteBuffer允许将文件直接映射到内存,提供高性能的大数据访问。 7. **权限与访问控制**:模拟真实系统中的用户权限模型,如Unix的用户组和权限位,可以...
五、文件删除 删除文件通常很简单,Java中`File`类的`delete()`方法可以完成这个任务。需要注意的是,如果文件正在被其他进程使用,删除操作可能会失败,这时需要处理异常。 六、更复杂的IO操作 除了基本的文件操作...
2. **文件删除**:调用File类的`delete()`方法删除文件。需要注意的是,如果文件被其他程序占用,可能无法成功删除。 3. **文件移动**:通过`renameTo()`方法可以将文件移动到另一个位置,但这个方法不支持跨文件...
例如,`BufferedReader`和`PrintWriter`可以用来读写文本文件,而`FileChannel`和`MappedByteBuffer`则支持更高效的块级I/O。 6. **文件缓冲与缓存**:为了提高性能,操作系统通常会使用缓冲区来暂存文件数据。Java...
- `File`类用于文件和目录的创建、读取、删除等操作,提供文件属性的查询。 - `RandomAccessFile`支持对文件进行随机访问,适用于大文件读写。 2. **文件系统结构**: - 在Linux中,文件系统基于目录树结构,根...
19. **内存映射文件**:`java.nio.MappedByteBuffer`提供内存映射文件功能,提升大文件处理效率。 以上只是Java文件操作的一部分知识点,实际开发中还会涉及文件权限控制、并发访问、流操作等更多内容。了解并熟练...
Java文件批处理模块是一种用于高效管理大量文件的程序设计,主要应用于自动化操作,例如批量删除、移动或复制文件。在Java编程中,实现这样的功能通常涉及到对文件系统API的深入理解和利用。以下是对该模块的一些...
5. **文件删除与重命名** 使用`File.delete()`方法可删除文件,`File.renameTo(File dest)`用于重命名或移动文件。 6. **NIO操作** 使用`java.nio`包可以进行异步文件操作,例如`AsynchronousFileChannel`类。它...
Java文件操作是Java编程中必不可少的部分,它涵盖了创建、读取、写入、删除以及管理文件和目录的各种功能。在Java中,文件操作主要通过java.io包中的类和接口实现。下面将对Java文件操作进行详细的总结,并提供相关...
4. **I/O操作优化**:在Java中,可以使用`RandomAccessFile`或`MappedByteBuffer`进行磁盘I/O操作,以减少磁盘访问次数。 5. **错误处理**:考虑到上传的代码可能存在问题,应包含适当的错误处理和日志记录,以便...
当处理内存限制或性能敏感的应用时,还可以利用NIO(New I/O)的特性,如`FileChannel`和`MappedByteBuffer`进行内存映射文件操作,这允许直接在磁盘和内存之间传输数据,而无需经过CPU。 总的来说,Java提供了多种...
对于大文件的处理,NIO的内存映射文件(MappedByteBuffer)也是很好的选择,它可以将文件部分映射到内存,从而提高读写速度。 最后,Java的I/O流库提供了丰富的选择,如ObjectInputStream和ObjectOutputStream用于...
- Java的`MappedByteBuffer`类允许将文件映射到内存,使得文件操作如同访问内存一样快速,适合处理大型文件。 9. **大数据量文件读取策略** - **分块读取**:对于大文件,不一次性加载到内存,而是按需分块读取。...
7. **文件映射**:通过`MappedByteBuffer`,Java可以直接将文件映射到内存,实现高速访问。这种方式常用于大文件的处理,如日志文件或数据库文件。 8. **异步I/O**:Java 7引入了`java.nio.channels....
MappedByteBuffer允许将文件映射到内存,使得文件操作如同操作内存一样高效。 Java的IO库还提供了对象序列化和反序列化的功能,Serializable接口标记一个类可以被序列化,ObjectOutputStream和ObjectInputStream...
Android提供了Java标准的`java.io`包中的类,如`File`、`FileInputStream`、`FileOutputStream`等,用于进行文件的创建、读写、删除等操作。例如,可以使用`new File(path)`创建一个`File`对象,然后通过`...
- 考虑使用内存映射文件(`MappedByteBuffer`)来提高读取效率,尤其是在操作系统支持大文件的情况下。 - 如果内存允许,可以采用Bloom Filter或布隆过滤器来减少排序过程中不必要的比较,降低CPU使用。 - 使用...
- **File类**:提供与文件和目录路径名字符串的转换,以及文件的创建、删除等操作。 2. **文件读取**: - **FileInputStream** 和 **BufferedReader**:用于读取字节流和字符流。通常会结合BufferedReader提高...
4. **文件删除** - **File#delete()**:删除一个文件或空目录。如果文件是打开状态,可能无法删除。 - **Files#delete()**:Java 7引入的方法,提供了更丰富的异常处理机制。 5. **文件缓存操作** - **java.nio....