`

InputStream 源码分析

阅读更多
InputStream是所有输入字节流类的超类。所有InputStream的子类必须提供返回下个字节的方法。

public abstract class InputStream implements Closeable {

	private static final int SKIP_BUFFER_SIZE = 2048;

	private static byte[] skipBuffer;

	// 从输入流中读取下个字节的数据,返回的字节是以int类型表示的(0~255)。如果已经到了流的末尾,返回-1。这个方法会被阻断直到输入流可用,已经到了末尾,或者抛出异常。
	public abstract int read() throws IOException;

	// 从流中读取b长度的字节到b中。
	public int read(byte b[]) throws IOException {
		return read(b, 0, b.length);
	}

	// 从流中读取最多len长度的字节并存储到b中,返回实际读取的字节数。
	// 这个方法会被阻断直到输入流可用,已经到了末尾,或者抛出异常。
	// 如果数组长度为0,那么不会读取字节,返回0;否则试着去读取至少一个字节,如果到了流的末尾,返回-1。
	// 第一个读取的字节会被保存到b[0]中,下一个会被保存到b[1]中。读取的字节数最大值是b的长度。b中剩余的部分不受影响。
	// 该方法重复调用read()。如果第一次调用报IOException异常,该异常会被抛到该方法。如果接下来对read()的调用报IOException异常,异常会被获取并当成是文件的结尾。前面读取的字节会被保存到b中,返回读取的字节数。该方法的默认实现会阻断直到已经读取len长度字节的数据,检测到文件末尾,或者有异常抛出。子类可以提供更高效的实现。
	public int read(byte b[], int off, int len) throws IOException {
		if (b == null) {
			throw new NullPointerException();
		} else if (off < 0 || len < 0 || len > b.length - off) {
			throw new IndexOutOfBoundsException();
		} else if (len == 0) {
			return 0;
		}

		int c = read();
		if (c == -1) {
			return -1;
		}
		b[off] = (byte)c;

		int i = 1;
		try {
			for (; i < len ; i++) {
				c = read();
				if (c == -1) {
					break;
				}
				b[off + i] = (byte)c;
			}
		} catch (IOException ee) {
		}
		return i;
	}

	// 从输入流中跳过并丢弃 n 个字节的数据。  
	//出于各种原因,skip 方法最终跳过的字节数可能更少一些,甚至可能为0。这可能是一些因素导致的,在跳过n个字节之前已经到达文件末尾只是其中一种可能。返回实际跳过的字节数。如果n为负值,不跳过任何字节。
	// 该方法创建一个字节数组并不断地读取数据放到里面直至读取到n个字节或者到达流末尾。子类可以提供更高效的方法实现。
	public long skip(long n) throws IOException {

		long remaining = n;
		int nr;
		if (skipBuffer == null)
			skipBuffer = new byte[SKIP_BUFFER_SIZE];

		byte[] localSkipBuffer = skipBuffer;
		
		if (n <= 0) {
			return 0;
		}

		while (remaining > 0) {
			nr = read(localSkipBuffer, 0,
				(int) Math.min(SKIP_BUFFER_SIZE, remaining));
			if (nr < 0) {
				break;
			}
			remaining -= nr;
		}
	
		return n - remaining;
	}

	// 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。  
	// 某些子类会返回流的所有字节数,有些不会。根据这个返回值来分配一个缓冲区来存取流中的所有数据是不对的。
	// 子类需要重写该方法。  
	public int available() throws IOException {
		return 0;
	}

	// 关闭流并且释放所有和这个流关联的系统资源
	public void close() throws IOException {}

	// 在流中标记当前位置。以后再调用reset时就可以再回到这个mark过的地方,这样再次读取到同样的字节。
	// readlimit参数告诉系统,在读出这么多个字符之前,这个mark保持有效。
	// mark通常的规范是:如果markSupported返回true,在调用mark方法后,流以某种方式记录所有读取的字节,当调用reset方法后,能够再次提供同样的字节。但是,在调用reset之前,流不必记录readlimit以外的字节。
	// 在已经关闭的流上调用mark方法对流没有影响
	public synchronized void mark(int readlimit) {}

	// 将该输入流重新定位到上一次调用mark方法时标记的位置
	// 如果markSupported返回true:
	//  如果从流创建后,mark还未被调用过,或者调用mark后,读取的字节数大于mark的参数readlimit,可能会抛出IOException异常。
	//  如果异常没有抛出,上次调用mark方法读取的所有字节(从文件的起始位置,如果mark方法没有调用)能够再次提供给以后的read方法,后跟任何从调用 reset 时起将作为下一输入数据的字节。
	// 如果markSupported返回false:
	//   对 reset 的调用可能抛出 IOException
	//   如果未抛出 IOException,则将该流重新设置为一种固定状态,该状态取决于输入流的特定类型及其创建方式。提供给 read 方法后续调用者的字节取决于特定类型的输入流。
	public synchronized void reset() throws IOException {
		throw new IOException("mark/reset not supported");
	}

	// 查看输入流是否支持mark和reset方法。对于某个特定的流实例来说,是否支持mark和reset方法是不变的属性。
	public boolean markSupported() {
		return false;
	}
分享到:
评论

相关推荐

    java InputStream读取数据问题

    10. **源码分析**: - 分析`InputStream`的源码有助于理解其工作原理,特别是对于自定义输入流或优化读取性能的情况。 综上所述,解决“Java InputStream读取数据问题”涉及理解`InputStream`的工作机制,熟练掌握...

    Socket中InputStream的read方法的阻塞特性

    Socket中的InputStream的`read`方法是Java网络编程中一个核心的概念,它在处理客户端与服务器之间的数据传输时起着至关重要的作用。...同时,结合源码分析,我们可以深入理解Java I/O的内部实现,提升编程技能。

    Java rt.jar 源码分析

    这篇博客文章《Java rt.jar 源码分析》可能探讨了以下几个关键知识点: 1. **Java基础类库**:rt.jar中的类库涵盖了Java语言的核心功能,包括对象模型、基本类型、集合框架、多线程、网络编程、I/O流、反射、异常...

    INPUTSTREAM

    标签 "源码" 暗示这篇博客可能深入剖析了 `InputStream` 类的源代码,分析了其实现细节和设计思路。这可能包括类的构造函数、方法的实现逻辑以及与其他类的协作关系。 "工具" 标签可能意味着博客作者讨论了如何利用...

    Mybatis源码分析.md

    ### Mybatis源码分析 #### 1. 解析配置文件,创建SQLSessionFactory 在MyBatis框架中,创建`SQLSessionFactory`是初始化整个框架的重要步骤之一。这一过程涉及到了配置文件的读取与解析,以及如何构建出可以用于...

    Rome使用简单说明二(部分关键源码分析)

    《Rome使用简单说明二(部分关键源码分析)》 在Java开发中,Rome是一个非常实用的工具,主要用于RSS和Atom feed的处理。它提供了丰富的API,使得开发者能够轻松地读取、创建和更新这些格式的feed。本文将深入探讨...

    通过JDK源码学习InputStream详解

    总之,InputStream是Java IO库中的核心类,理解其源码有助于深入学习Java IO机制,提升程序设计和问题排查的能力。通过阅读源码,开发者可以更好地理解Java IO流的工作原理,从而在实际编程中更加游刃有余。

    corejava7源码

    《Core Java 7源码分析》 在Java编程领域,Core Java系列书籍是广大开发者学习和进阶的重要参考资料。Core Java 7,即《Core Java Volume I - Fundamentals》的第七版,它深入探讨了Java语言的核心特性,包括面向...

    疯狂Java flashget源码

    3. **网络I/O**:Java的Socket编程和InputStream/OutputStream类是进行网络通信的基础。源码中可能会用到BufferedInputStream和BufferedOutputStream来提高I/O效率,以及HttpURLConnection或HttpClient类来处理HTTP...

    FilterOutputStream 源码分析

    《FilterOutputStream 源码分析》 FilterOutputStream 是 Java I/O 流库中的一个关键类,它是所有“过滤”输出流的基础。这个类的主要目的是为了提供一个基础框架,用于在输出流之上添加额外的功能,例如数据压缩、...

    JavaCodeAnalysis:Java源码分析学习

    在Java编程世界里,源码分析是提升编程技能和理解框架内部运作机制的关键步骤。"JavaCodeAnalysis"项目正致力于帮助开发者深入理解Java语言及其常用库的底层实现。这个项目包含了一个名为"JavaCodeAnalysis-master...

    Android Socket源码实现与PC通讯

    本文将深入探讨Android Socket源码实现与PC通讯的核心概念、步骤以及具体Java源码解析。 Socket,也被称为套接字,是网络编程中的基本组件,它提供了进程间通信(IPC,Inter-Process Communication)的能力,尤其...

    Java常用类源码

    通过源码分析,我们可以理解它们各自的性能特点和适用场景。 3. `HashMap` 和 `TreeMap` 类:这两个类实现了`Map`接口,用于存储键值对。`HashMap`提供快速的插入、删除和查找,依赖于哈希表;`TreeMap`则按照键的...

    JDK源码选读

    源码分析是提高Java程序员技能的关键步骤,因为通过阅读源码,我们可以理解Java平台如何处理内存管理、多线程、类加载、异常处理等核心概念。 1. **内存管理**:JDK中的`java.lang.Runtime`类提供了与Java虚拟机...

    Java中的InputStreamReader和OutputStreamWriter源码分析_动力节点Java学院整理

    Java中的InputStreamReader和OutputStreamWriter源码分析 InputStreamReader是Java中用于将字节输入流转换成字符输入流的类,它继承自Reader类。下面是InputStreamReader的源码分析: 构造方法 InputStreamReader...

    从源码分析Android的Glide库的图片加载流程及特点

    Android的Glide库是一款广泛使用的多媒体资源管理库,尤其在处理图片加载方面表现出色。Glide以其高效、简洁的API和强大的...通过对源码的深入分析,我们可以更好地理解和优化Glide的使用,提升应用的性能和用户体验。

    raw源码Android

    四、raw源码分析 分析raw源码,主要是为了理解代码的执行流程、算法实现、数据结构以及错误处理等方面。这有助于优化性能,解决潜在问题,甚至进行二次开发。通常会用到以下工具和技巧: 1. 使用IDE(如Android ...

    corejava 源码

    源码分析可以帮助我们理解如何有效地使用异常处理来增加程序的健壮性。 4. **集合框架**:Java集合框架是处理对象集合的重要工具,包括List、Set、Queue等接口,以及ArrayList、LinkedList、HashSet、HashMap等实现...

Global site tag (gtag.js) - Google Analytics