最近做一个很简单的函数,要两个返回值,我打算有一个类封装一下返回,后来领导要求使用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 JNICALL
Java_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 JNICALL
Java_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) {
fis_fd = (*env)->GetFieldID(env, fdClass, "fd", "Ljava/io/FileDescriptor;");
}
/**************************************************************
* Input stream
*/
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) {
fileOpen(env, this, path, fis_fd, O_RDONLY);
}
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);
}
JNIEXPORT jlong JNICALL
Java_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 JNICALL
Java_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 */
int
readSingle(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 8192
int
readBytes(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宏转换的
分享到:
相关推荐
Java源码大全是一个珍贵的学习资源,它包含了作者在参加上海杰普培训时积累的重要Java基础知识。这个压缩包可能包括了核心Java(Core Java)的各个方面,如I/O(输入/输出)、多线程(Thread)以及其他关键概念。...
Java源码注释翻译是一个重要的开发工具,尤其对于那些阅读英文源码或处理国际开源项目时,能够快速理解和学习代码的含义。这个项目的核心目标是批量处理Java源码文件,将其中的类注释自动翻译成中文,以帮助开发者...
Java源码集合是一个珍贵的学习资源,它包含了从大一开始积累的31个不同Java项目,适合于课程设计、毕业设计以及个人技能提升。这个压缩包是开发者或学习者的一个宝库,提供了各种类型的代码示例,有助于深入理解Java...
【毕向东Java源码】是针对Java初学者和进阶者的一份宝贵资源,由知名IT教育专家毕向东先生编写的教学源代码集合。这份源码涵盖了Java编程的基础到高级概念,旨在帮助学习者深入理解Java语言的核心机制,并通过实际...
"140个Java源码实例"是一份珍贵的学习资源,它包含了多个实际编程场景下的代码示例,旨在帮助初学者更好地理解和掌握Java编程。 在学习这140个Java源码实例时,我们可以按照以下主要知识点进行分类和深入学习: 1....
8. **设计模式**:Java源码包可能包含常见的设计模式实现,如工厂模式、单例模式、观察者模式、装饰器模式等,这些都是软件工程中提升代码质量和可维护性的关键。 9. **Java Swing与JavaFX**:如果源码涉及到图形...
《深入解析CoreJava源码》 Java语言作为世界上最流行的编程语言之一,其强大的跨平台能力和丰富的类库使得它在各种领域都有广泛的应用。对于初学者和有经验的开发者来说,理解Java的核心概念和源码是提升技能的关键...
【标题】:“http简易服务器 java 源码”是指基于Java编程语言实现的一个简单的HTTP服务器。这个服务器能够处理HTTP请求,提供基本的Web服务功能。 【描述】:该服务器源码实现了两个关键特性:一是“重定向”,即...
在Java开发过程中,将源码编译并打包成JAR(Java Archive)文件是一项常见的任务。JAR文件是Java平台特有的归档格式,它能够包含类文件、资源文件以及元数据,便于分发和执行。这里我们将详细讲解如何通过编写Java...
这个"音乐播放器java源码"提供了一种实现方式,可以帮助我们深入理解Java编程语言以及多媒体处理技术。下面将详细介绍该源码可能包含的关键知识点。 1. **Java基础** - 类与对象:音乐播放器程序肯定包含了多个类...
Java源码笔记主要涵盖的是Java编程语言的核心概念和高级特性,特别是与网络编程相关的部分。在深入理解Java源码的过程中,我们不仅可以了解到语言的基础结构,还能探索其在网络通信中的应用。下面将对Java源码和网络...
这个压缩包“Java源码读写Properties文件.rar”包含了一份关于如何使用Java来读取和写入Properties文件的源代码示例。下面我们将详细探讨这个主题。 首先,Properties类是Java的标准库类,位于`java.util`包下,它...
在本资源中,我们拥有一个名为"java源码:Java实现的视频播放程序源码.rar"的压缩包,其中包含了使用Java编程语言实现的视频播放器的源代码。这个项目可以被视为一个经典案例,用于学习Java编程以及多媒体处理技术。...
源码中可能包含读取本地文件并将其内容作为HTTP响应返回的部分,这可能使用到`FileInputStream`和`BufferedInputStream`等I/O流类。 5. 响应构建 服务器需要构造并发送HTTP响应,包括状态行、响应头和响应体。状态...
"一起来画画_JAVA源码.rar" 是一个包含JAVA源代码的压缩文件,旨在提供一个绘画相关的编程项目。从标签"java 画画"我们可以推断,这个项目可能是一个使用Java语言开发的图形用户界面(GUI)应用程序,允许用户在屏幕...
Java源码是编程者学习和理解Java编程语言的宝贵资源,它揭示了程序背后的逻辑和实现细节。在Java世界中,源码是用Java编程语言编写的文本文件,通常以.java为扩展名。这些文件包含了类、方法、变量定义以及其他编程...
源码中可能包含使用FileInputStream、FileOutputStream、BufferedReader、PrintWriter等类的例子。 6. **多线程**:Java支持多线程编程,可以同时执行多个任务。例子可能涵盖Thread类、Runnable接口的使用,以及...
【Java源码:赛马游戏】是一个非常适合初学者学习的编程项目,它涵盖了Java语言的基础知识,以及如何在Eclipse或MyEclipse等集成开发环境中部署和运行Java应用程序。通过这个项目,我们可以深入理解面向对象编程的...
9. **文件I/O操作**:读取图片文件需要使用Java的文件I/O流,如`FileInputStream`和`BufferedImage`,以读取和处理图像数据。 这个"Viewer.jar"程序是一个很好的学习示例,对于想要了解如何在Java Swing环境中创建...
Java 的 File 类用于文件的创建、读取和写入,而 FileInputStream 和 FileOutputStream 分别用于读写操作。源码中,开发者可能会实现打开文件对话框,并使用 BufferedReader 和 BufferedWriter 进行文本的读取和写入...