最近做一个很简单的函数,要两个返回值,我打算有一个类封装一下返回,后来领导要求使用StringBuilder返回,不用StringBuffer,因为局部变量StringBuffer最后还是要编译为StringBuilder,因为StringBuilder没有任何同步。问了一下大家的看法,风南说InputStream 的int read(byte[] b) 从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中,也是类似的,看来有必要研究一下IO了。 InputStream类中重要的函数,只有一个抽象的有用, public abstract int read() throws IOException;其他两个read的意义不大。 public int read(byte b[], int off, int len) throws IOException 和 public int read(byte b[]) throws IOException { return read(b, 0, b.length); }下面看它的子类FileInputStream的实现, /* File Descriptor - handle to the open file */ private FileDescriptor fd;这个很重要,这是文件句柄,C语言使用fopen函数的都知道。/** * Opens the specified file for reading. * @param name the name of the file */ private native void open(String name) throws FileNotFoundException; /** * Reads a byte of data from this input stream. This method blocks * if no input is yet available. * * @return the next byte of data, or <code>-1</code> if the end of the * file is reached. * @exception IOException if an I/O error occurs. */ public native int read() throws IOException; /** * Reads a subarray as a sequence of bytes. * @param b the data to be written * @param off the start offset in the data * @param len the number of bytes that are written * @exception IOException If an I/O error has occurred. */ private native int readBytes(byte b[], int off, int len) throws IOException;子类修改了父的实现 /** * Reads up to <code>b.length</code> bytes of data from this input * stream into an array of bytes. This method blocks until some input * is available. * * @param b the buffer into which the data is read. * @return the total number of bytes read into the buffer, or * <code>-1</code> if there is no more data because the end of * the file has been reached. * @exception IOException if an I/O error occurs. */ public int read(byte b[]) throws IOException { return readBytes(b, 0, b.length); } /** * Reads up to <code>len</code> bytes of data from this input stream * into an array of bytes. If <code>len</code> is not zero, the method * blocks until some input is available; otherwise, no * bytes are read and <code>0</code> is returned. * * @param b the buffer into which the data is read. * @param off the start offset in the destination array <code>b</code> * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or * <code>-1</code> if there is no more data because the end of * the file has been reached. * @exception NullPointerException If <code>b</code> is <code>null</code>. * @exception IndexOutOfBoundsException If <code>off</code> is negative, * <code>len</code> is negative, or <code>len</code> is greater than * <code>b.length - off</code> * @exception IOException if an I/O error occurs. */ public int read(byte b[], int off, int len) throws IOException { return readBytes(b, off, len); }看出readBytes是关键的所在,windows的native code中只有JNIEXPORT void JNICALLJava_java_io_FileInputStream_close0(JNIEnv *env, jobject this) { handleClose(env, this, fis_fd);}是平台相关的。其他的在share中FileInputStream.c代码jfieldID fis_fd; /* id for jobject 'fd' in java.io.FileInputStream *//************************************************************** * static methods to store field ID's in initializers */得到fd的值,这个很重要JNIEXPORT void JNICALLJava_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) { fis_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;");}/************************************************************** * Input stream */JNIEXPORT void JNICALLJava_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) { fileOpen(env, this, path, fis_fd, O_RDONLY);}JNIEXPORT jint JNICALLJava_java_io_FileInputStream_read(JNIEnv *env, jobject this) { return readSingle(env, this, fis_fd);}JNIEXPORT jint JNICALLJava_java_io_FileInputStream_readBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len) { return readBytes(env, this, bytes, off, len, fis_fd);}JNIEXPORT jlong JNICALLJava_java_io_FileInputStream_skip(JNIEnv *env, jobject this, jlong toSkip) { jlong cur = jlong_zero; jlong end = jlong_zero; FD fd = GET_FD(this, fis_fd); if ((cur = IO_Lseek(fd, (jlong)0, (jint)SEEK_CUR)) == -1) { JNU_ThrowIOExceptionWithLastError(env, "Seek error"); } else if ((end = IO_Lseek(fd, toSkip, (jint)SEEK_CUR)) == -1) { JNU_ThrowIOExceptionWithLastError(env, "Seek error"); } return (end - cur);}JNIEXPORT jint JNICALLJava_java_io_FileInputStream_available(JNIEnv *env, jobject this) { jlong ret; FD fd = GET_FD(this, fis_fd); if (IO_Available(fd, &ret)) { if (ret > INT_MAX) { ret = (jlong) INT_MAX; } return jlong_to_jint(ret); } JNU_ThrowIOExceptionWithLastError(env, NULL); return 0;}主要是readBytes的实现,打开io_util.c文件/* IO helper functions */intreadSingle(JNIEnv *env, jobject this, jfieldID fid) { int nread; char ret; FD fd = GET_FD(this, fid); 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", 0); } return ret & 0xFF;}/* The maximum size of a stack-allocated buffer. */#define BUF_SIZE 8192intreadBytes(JNIEnv *env, jobject this, jbyteArray bytes, jint off, jint len, jfieldID fid){ int nread, datalen; char stackBuf[BUF_SIZE]; char *buf = 0; FD fd; if (IS_NULL(bytes)) { JNU_ThrowNullPointerException(env, 0); return -1; } datalen = (*env)->GetArrayLength(env, bytes); if ((off < 0) || (off > datalen) || (len < 0) || ((off + len) > datalen) || ((off + len) < 0)) { JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", 0); return -1; } if (len == 0) { return 0; } else if (len > BUF_SIZE) { buf = malloc(len); if (buf == 0) { JNU_ThrowOutOfMemoryError(env, 0); return 0; } } else { buf = stackBuf; } fd = GET_FD(this, fid); nread = IO_Read(fd, buf, len); if (nread > 0) { (*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf); } else if (nread == JVM_IO_ERR) { JNU_ThrowIOExceptionWithLastError(env, "Read error"); } else if (nread == JVM_IO_INTR) { /* EOF */ JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); } else { /* EOF */ nread = -1; } if (buf != stackBuf) { free(buf); } return nread;}注意IO_Read在io_util_md.h做了手脚的,#define IO_Read JVM_Read其实就是JVM_Read,JVM_Read在hotspot源码中定义的 //%note jvm_r6 return (jint)hpi::read(fd, buf, nbytes);hpi定义了大量的函数 // HPI_FileInterface static inline char* native_path(char *path); static inline int file_type(const char *path); static inline int open(const char *name, int mode, int perm); static inline int close(int fd); static inline jlong lseek(int fd, jlong off, int whence); static inline int ftruncate(int fd, jlong length); static inline int fsync(int fd); static inline int available(int fd, jlong *bytes); static inline size_t read(int fd, void *buf, unsigned int nBytes); static inline size_t write(int fd, const void *buf, unsigned int nBytes); static inline int fsize(int fd, jlong *size);这就是和平台相关的代码了。window下通过HPIDECL宏转换的 |