欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

NULL);//被打断 } return 昆山软件定制开发 ret 0xFF;//与0xFF做按位的与运算

点击: 次  来源:宝鼎软件 时间:2017-06-14

原文出处: 左潇龙

上一章我们已经阐明过FileInputStream的构建进程,接下来我们就来看一下read要领的读取进程。

我们先来看下FileInputStream中的四个有关read的要领的源码,如下。

public native int read() throws IOException;

    private native int readBytes(byte b[], int off, int len) throws IOException;

    public int read(byte b[]) throws IOException {
    return readBytes(b, 0, b.length);
    }

    public int read(byte b[], int off, int len) throws IOException {
    return readBytes(b, off, len);
    }

可以看到,个中有两个当处所法,两个不是当处所法,可是照旧内部照旧挪用的当处所法,那么我们研究的重点就是这两个当处所法到底是如何实现的。

下面是这两个当处所法的源码,很是简朴,列位请看。

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_read(JNIEnv *env, jobject this) {
    return readSingle(env, this, fis_fd);//每一个当地的实例要领默认的两个参数,JNI情况与工具的实例
}

JNIEXPORT jint JNICALL
Java_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this,
        jbyteArray bytes, jint off, jint len) {//除了前两个参数,后三个就是readBytes要领通报进来的,字节数组、起始位置、长度三个参数
    return readBytes(env, this, bytes, off, len, fis_fd);
}

可以看到,这两个当处所法的实现只是将任务又转给了两个要领,readSingle和ReadBytes,软件开发,请留意,在挪用这两个要领时,除了常用的env和this工具,以及从JAVA情况传过来的参数之外,还多了一个参数fis_fd,这个工具就是上一章中FileInputStream类中的fd属性的地点偏移量了。

那么下面我们首先来看readSingle要领的实现,如下。

/*
    env和this参数就不再表明白
    fid就是FileInputStream类中fd属性的地点偏移量
    通过fid和this实例可以获取FileInputStream类中fd属性的内存地点
*/
jint
readSingle(JNIEnv *env, jobject this, jfieldID fid) {
    jint nread;//存储读取后返回的功效值
    char ret;//存储读取出来的字符
    FD fd = GET_FD(this, fid);//这个获取到的FD其实就是之前handle属性的值,也就是文件的句柄
    if (fd == -1) {
        JNU_ThrowIOException(env, "Stream Closed");
        return -1;//假如文件句柄便是-1,说明文件流已封锁
    }
    nread = (jint)IO_Read(fd, &ret, 1);//读取一个字符,而且赋给ret变量
    //以下按照返回的int值判定读取的功效
    if (nread == 0) { /* EOF */
        return -1;//代表流已到末端,返回-1
    } else if (nread == JVM_IO_ERR) { /* error */
        JNU_ThrowIOExceptionWithLastError(env, "Read error");//IO错误
    } else if (nread == JVM_IO_INTR) {
        JNU_ThrowByName(env, "java/io/InterruptedIOException", NULL);//被打断
    }
    return ret & 0xFF;//与0xFF做按位的与运算,去除高于8位bit的位
}

可以看到,这个要领其实最要害的就是IO_Read这个宏界说的处理惩罚,而IO_Read其实只是代表了一个要领名称叫handleRead,我们去看一下handleRead的源码。

/*
    fd就是handle属性的值
    buf是收取读取内容的数组
    len是读取的长度,可以看到,这个参数传进来的是1
    函数返回的值代表的是实际读取的字符长度
*/
JNIEXPORT
size_t
handleRead(jlong fd, void *buf, jint len)
{
    DWORD read = 0;
    BOOL result = 0;
    HANDLE h = (HANDLE)fd;
    if (h == INVALID_HANDLE_VALUE) {//假如句柄是无效的,则返回-1
        return -1;
    }
    //这里ReadFile又是一个现有的函数,和上一章的CreateFile是一样的
    //都是WIN API的函数,可以百度搜索它的浸染与参数详解,领略它并不难
    result = ReadFile(h,          /* File handle to read */  //文件句柄
                      buf,        /* address to put data */  //存放数据的地点
                      len,        /* number of bytes to read */  //要读取的长度
                      &read,      /* number of bytes read */  //实际读取的长度
                      NULL);      /* no overlapped struct */  //只有对文件举办重叠操纵时才需要传值
    if (result == 0) {//假如没读取出来对象,劳务派遣管理系统,则判定是到了文件末端返回0,照旧报错了返回-1
        int error = GetLastError();
        if (error == ERROR_BROKEN_PIPE) {
            return 0; /* EOF */
        }
        return -1;
    }
    return read;
}

到此,劳务派遣管理系统,根基上就完全看完了无参数的read要领的源码,它的道理其实很简朴,就是操作handle这个句柄,利用ReadFile的WIN API函数读取了一个字符,不外值得留意的是,这些都是windows系统下的实现方法,所以不行认为这些源码代表了所有系统下的环境。

然而对付带有参数的read要领,其道理与无参read要领是一样的,并且最终也是挪用的handleRead这个要领,只是读取的长度不再是1罢了。