`
greemranqq
  • 浏览: 975469 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

java底层是怎样对文件操作的

阅读更多

 一、序言

        IO操作,才程序中比较普遍,JAVA 中提出了IO/NIO 的概念,也一直在说NIO 比IO快,一直不知道原因,就想memcache 和ehcache 比较优劣一样,这些东西得自己看看如何实现的,才 知道区别,从而才知道优劣以及试用范围,而不仅仅是“听说”!这里我可以先了解下JAVA 如何操作IO的。

 

二、代码示例

       我们先看看简单文件操作:

       

 // 这是将文件转换成输入流的的一种方式,获得了流我们就能干很多事
 FileInputStream in = new FileInputStream(new File("...file"));
 

 

       再看看FileInputStream 的源码:

    

public FileInputStream(File file) throws FileNotFoundException {
	String name = (file != null ? file.getPath() : null);
        // 安全管理器,这里暂时不说
	SecurityManager security = System.getSecurityManager();
	if (security != null) {
            // 检查是否可以按这名字读取
	    security.checkRead(name);
	}
        if (name == null) {
            throw new NullPointerException();
        }
        // 获得文件描述,这个JDK 未公布
	fd = new FileDescriptor();
        // 打开文件,这是个native 方法,我们可以用openjdk 看看里面
	open(name);
    }
 

 

  在FileInputStream.c下可以找到方法

    

// open 方法
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) {
    fileOpen(env, this, path, fis_fd, O_RDONLY);
}
 

 

    OK。我们从该文件上面的引用io_util_md.c找到实现:

   

void
fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)
{
    jlong h = winFileHandleOpen(env, path, flags);
    if (h >= 0) {
        // 设置fd 的值
        SET_FD(this, h, fid);
    }
}
 

 

 

    在上面文件里面可以看到:winFileHandleOpen,

   

jlong
winFileHandleOpen(JNIEnv *env, jstring path, int flags)
{
    const DWORD access =
        (flags & O_RDWR)   ? (GENERIC_WRITE | GENERIC_READ) :
        (flags & O_WRONLY) ?  GENERIC_WRITE :
        GENERIC_READ;
    const DWORD sharing =
        FILE_SHARE_READ | FILE_SHARE_WRITE;
    const DWORD disposition =
        /* Note: O_TRUNC overrides O_CREAT */
        (flags & O_TRUNC) ? CREATE_ALWAYS :
        (flags & O_CREAT) ? OPEN_ALWAYS   :
        OPEN_EXISTING;
    const DWORD  maybeWriteThrough =
        (flags & (O_SYNC | O_DSYNC)) ?
        FILE_FLAG_WRITE_THROUGH :
        FILE_ATTRIBUTE_NORMAL;
    const DWORD maybeDeleteOnClose =
        (flags & O_TEMPORARY) ?
        FILE_FLAG_DELETE_ON_CLOSE :
        FILE_ATTRIBUTE_NORMAL;
    const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
    HANDLE h = NULL;

    if (onNT) {
        WCHAR *pathbuf = pathToNTPath(env, path, JNI_TRUE);
        if (pathbuf == NULL) {
            /* Exception already pending */
            return -1;
        }
        h = CreateFileW(
            pathbuf,            /* Wide char path name */
            access,             /* Read and/or write permission */
            sharing,            /* File sharing flags */
            NULL,               /* Security attributes */
            disposition,        /* creation disposition */
            flagsAndAttributes, /* flags and attributes */
            NULL);
        free(pathbuf);
    } else {
        WITH_PLATFORM_STRING(env, path, _ps) {
            h = CreateFile(_ps, access, sharing, NULL, disposition,
                           flagsAndAttributes, NULL);
        } END_PLATFORM_STRING(env, _ps);
    }
    if (h == INVALID_HANDLE_VALUE) {
        int error = GetLastError();
        if (error == ERROR_TOO_MANY_OPEN_FILES) {
            JNU_ThrowByName(env, JNU_JAVAIOPKG "IOException",
                            "Too many open files");
            return -1;
        }
        throwFileNotFoundException(env, path);
        return -1;
    }
    return (jlong) h;
}

 

   

 

  好吧,上面代码我也搞不明白- -,但是这几句代码:

  

  h = CreateFileW(
            pathbuf,            /* Wide char path name */
            access,             /* Read and/or write permission */
            sharing,            /* File sharing flags */
            NULL,               /* Security attributes */
            disposition,        /* creation disposition */
            flagsAndAttributes, /* flags and attributes */
            NULL);

以及
   WITH_PLATFORM_STRING(env, path, _ps) {
            h = CreateFile(_ps, access, sharing, NULL, disposition,
                           flagsAndAttributes, NULL);  

 

   我的理解是,这里通过CreateFileW方法,创建了一个类似文件描述的结构,然后通过CreateFile调windows 下面的底层方法,填充这个结构的数据,那么这个文件对象就能被我们上层对象识别了,就能是获取里面的资源。

  OK,我们现在创建了对文件之间的连接,拿到文件流对象之后,来看看我们常用的read 方法。

   

// 对字节的操作
public native int read() throws IOException;
private native int readBytes(byte b[], int off, int len) throws IOException;

 

  

  在FileInputStream.c 里面同样可以找到

  

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read(JNIEnv *env, jobject this) {
    return readSingle(env, this, fis_fd);
}

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
        jbyteArray bytes, jint off, jint len) {
    return readBytes(env, this, bytes, off, len, fis_fd);
}

 

 

    继续看io_util.c 里面:

   

jint
readSingle(JNIEnv *env, jobject this, jfieldID fid) {
    jint nread;
    char ret;
    FD fd = GET_FD(this, fid);
    if (fd == -1) {
        JNU_ThrowIOException(env, "Stream Closed");
        return -1;
    }
    // 看出是一个一个的读取,fd 表示刚才文件描述的一种结构
    nread = IO_Read(fd, &ret, 1);
    if (nread == 0) { /* EOF */
        return -1;
    } else if (nread == JVM_IO_ERR) { /* error */
        JNU_ThrowIOExceptionWithLastError(env, "Read error");
    } else if (nread == JVM_IO_INTR) {
        JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);
    }
    return ret & 0xFF;
}

 

     

     关于IO_Read 的东西,在io_util_md.h 有定义:

    

/*
 * HPI是一个与主机通信的并行接口
 * Route the routines through HPI
 */
#define IO_Write JVM_Write
#define IO_Sync JVM_Sync
#define IO_Read JVM_Read
#define IO_Lseek JVM_Lseek
#define IO_Available JVM_Available
#define IO_SetLength JVM_SetLength

 

    关于JVM_Read 我在jvm.h 里面看到

   

/*
   // 从文件里面读取 a char array
 * Read data from a file decriptor into a char array.
 * // 文件的来源
 * fd        the file descriptor to read from.
   // 读出来的存放位置
 * buf       the buffer where to put the read data.
   // 读的字节数
 * nbytes    the number of bytes to read.
 *
 * This function returns -1 on error, and 0 on success.
 */
JNIEXPORT jint JNICALL
JVM_Read(jint fd, char *buf, jint nbytes);

   

    然后在jvm.cpp 里面找到

    关于这段代码,大神告诉我是宏定义,关于C和C++ 的东西,我已经无力回天啦。

    当然我们知道了介绍,可以理解这里会让调系统的read 方法。

    这可以参考:“操作系统read 的原理实现”,google 一下很多,这里就不解释了

    jvm.cpp 里面有很多关于IO这块的,可以去看看,但是都是 宏定义。。

    关于linux 下的这些代码,还有涉及一下阻塞等东西,以后在去研究一下操作系统的东西吧。

 

JVM_LEAF(jint, JVM_Read(jint fd, char *buf, jint nbytes))
  JVMWrapper2("JVM_Read (0x%x)", fd);

  //%note jvm_r6
  return (jint)os::restartable_read(fd, buf, nbytes);
JVM_END

   

    

小结:

     1.本想了解下底层怎么操作的,但是大概了解下了,最终到read  或者write 的时候,一些基础知识不够,还是不能透彻,但是也足够我们大致了解了。

      2.按上面的思路可以看出大概的思路,虽然没写write 的过程,但是最终都是通过流,或者说字符数组在内存里面的一些操作进行,包括我们用装饰器模式搞了很多其他流,基本原理一样,仅仅为了方便加了额外的功能。

      3. 有不对的地方还请指出,仅仅是个人学习,分享作用

    

分享到:
评论
2 楼 greemranqq 2015-03-16  
zlw8282003 写道
很不错了。

~.~ 了解了解,回过头去看,又感觉很陌生
1 楼 zlw8282003 2015-03-16  
很不错了。

相关推荐

    java实现windows文件系统操作监控

    Java的`java.nio.file`包提供了丰富的文件操作接口,如`Files.setPosixFilePermissions()`和`Files.newFileChannel()`,可以用来设置权限和创建文件通道进行锁定。 7. **文件自动加密**:文件加密通常涉及对文件...

    java的底层开发工具

    Java的底层开发主要涉及到与操作系统直接交互,以实现更高效、更低级别的功能,这通常包括系统调用、原生接口(Native Interface)等技术。在Java中,JNI(Java Native Interface)是Java平台标准的一部分,它允许Java...

    java 利用webservice传输文件

    总的来说,Java利用Web服务传输文件结合JACOB调用Windows COM组件,为跨平台的文件操作提供了一种解决方案。这种技术虽然有一定的复杂性,但在某些特定的Windows集成场景下,它可以发挥很大的价值。理解并熟练掌握这...

    java文件与流操作code

    下面将详细解释Java中的文件操作和流技术。 1. **Java I/O基础** - Java的I/O库位于`java.io`包中,提供了大量的类和接口,如File、InputStream、OutputStream、Reader、Writer等,用于处理不同类型的输入输出。 ...

    Java版文件系统

    在Java编程环境中,实现一个操作系统级别的文件系统是一项挑战性的工作,因为这涉及到对底层硬件、内存管理和并发控制的理解。然而,通过使用Java提供的类库和API,我们可以构建一个模拟的文件系统,它能够进行基本...

    java读写hdf5格式文件需要使用的库

    使用这些库进行HDF5文件操作的步骤大致如下: 1. 引入依赖:将`hdf5-3.3.2.jar`添加到项目的类路径中,如果是Maven或Gradle项目,需要在构建配置文件中添加对应的依赖。 2. 配置动态链接库:在Java程序启动时,确保...

    java调用window操作系统文本转语音并生成播放文件

    在Java编程环境中,调用Windows操作系统来实现文本转语音(Text-to-Speech, TTS)并生成播放文件是一项常见的需求。这项技术可以帮助开发者为应用程序添加语音合成功能,尤其适用于无障碍应用、语音助手或者多媒体...

    java操作word xml dll文件

    - **JNA(Java Native Access)**:允许Java代码直接调用操作系统底层的函数,包括DLL文件中的函数。它提供了一种无需编写C/C++代码即可调用本地方法的方式。 - **JNR(Java Native Runner)**:类似于JNA,JNR也...

    操作系统实习 java实现模拟文件管理系统

    本实验旨在通过编写Java程序来模拟一个简单的文件管理系统,目的是让学生理解操作系统中文件管理的核心概念,并通过实际编程加深对这些概念的理解。 #### 设计思路 为了模拟文件系统的结构,采用了树形结构来表示...

    Java解析SO(ELF)文件

    同时,可能需要使用位操作和数据类型转换来处理二进制数据,因为Java默认处理的是基于字节的流,而ELF文件中的数据可能是16位、32位或64位的整数、浮点数等。 开发这样一个解析库可能会涉及到以下步骤: 1. 定义...

    FileDao.rar_dao java_filedao.class_java FileD_java 文件操作

    总的来说,`FileDao`是Java开发中一个实用的工具类,它封装了文件操作的细节,使得开发者可以更专注于业务逻辑,而不用过多关心底层文件系统的交互。了解并熟练使用这样的DAO类,能极大地提升开发效率和代码质量。

    Java上传下载文件操作用到的jar

    为了实现这些功能,开发者通常会依赖一些库,这些库提供了便捷的API来处理文件操作。在这个压缩包中,包含的“commons”系列jar文件就是用来支持文件上传和下载的核心组件。 1. **Apache Commons FileUpload**: 这...

    把wsdl文件或地址转化成java代码工具

    【标题】:“把wsdl文件或地址...MyEclipse和Apache CXF的wsdl2java工具都是常用的解决方案,它们通过解析WSDL文件,自动生成与服务接口对应的Java类,使得开发者可以专注于业务逻辑的实现,而不用关心底层通信的细节。

    JavaIO底层是如何工作的?Java开发Java经验技巧

    例如,SocketChannel用于网络通信,FileChannel用于文件操作。 6. **字符编码** Java IO处理字符时会涉及编码问题。默认的编码是平台相关的,可以通过Charset类指定特定的字符编码,如UTF-8、GBK等。 7. **对象...

    java底层核心rt包源代码

    Java的rt.jar是Java运行时环境(Runtime Environment)的核心库...总之,研究Java底层核心rt包的源代码,是提高Java技术水平的重要途径,它能帮助开发者更高效地编写、调试和优化Java应用程序,提升软件开发的专业性。

    windows 下java调用winrar压缩文件为rar 格式

    在Windows环境下,使用Java进行程序开发时,有时我们需要对文件进行压缩操作,比如将文件...这个过程涉及到了Java的本地方法调用、文件操作、第三方库集成等多个知识点,需要对Java、C/C++和WinRAR API有一定的了解。

    Java二进制IO类与文件复制操作实例

    它们在内部维护一个缓冲区,减少对底层资源的频繁调用,从而提高效率。 4. **文件复制操作** 文件复制是一个典型的二进制IO操作实例。以下是一个简单的使用`FileInputStream`和`FileOutputStream`实现文件复制的...

    java工具包封装对xml的操作javamail,翻译,io操作

    开发者可以通过阅读文档或直接使用这个库,快速地在自己的项目中实现邮件发送、文本翻译、文件操作以及XML处理等功能。这样的工具包大大降低了开发者的负担,提高了开发效率,也保证了代码的健壮性和一致性。

    java操作word可操作书签

    总之,Java 操作 Word 书签虽然可以不依赖第三方库,但需要对 XML 解析和文件操作有较深的理解。尽管这种方法较为底层,但对于特定环境和需求,可能比使用第三方库更为灵活。然而,对于大多数项目来说,使用成熟的库...

    java 文件操作及IO流

    Java 文件操作与IO流是Java编程中的核心概念,主要用于数据的读取、写入和传输。在Java中,文件操作通常涉及到`java.io`包下的类,如`File`、`FileOutputStream`、`OutputStreamWriter`和`BufferedWriter`等。下面将...

Global site tag (gtag.js) - Google Analytics