1.1、java.io(精读部分)

java源码阅读专栏说明

1、源码阅读不包括异常和错误

2、一篇或者几篇文章是说不清楚的。光看博客也不会有多大的进步,或者说过段时间就会忘记。java源码阅读专栏旨在根据 代码 和文档的基础上来记录一些我自己的感受和想法。当然,我也会汲取一些其他人的收获。并将它们传播。

3、最主要的是了解这些源码的编程风格和一些规范,具体的一些说明,这个接口或者类是干什么的?可能也会涉及到

接下来开始,第一个包的了解:

java.io包是继承和接口运用得最棒例子了(这话是听别人说的,可从这个包的结构,可以看出确实很流畅。),我也是初次来阅读它,确实,io在平时用的也很多。而且io里面的东西也是其他部分的一些基础。所以我准备先来看看这个包的一些东西。

概览图

在这里插入图片描述

字节流可以处理所有类型数据,如:图片,MP3,AVI视频文件,而字符流只能处理字符数据。只有是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。

Interfaces部分

在这里插入图片描述
更多其他,请参考我的另一篇博客:Java基础总结!精华版!
的第19点。

接口实际上是定义了一种规范,所有实现了相应接口的类,或者接口,都得去安照它规范去做一些开发。

Closeable

Closeable使用,其中有一个方法,close(),这个接口还有一个父接口AutoCloseable,autocloseable来自java.lang
在这里插入图片描述
在这里插入图片描述
可以看到close方法抛出的是io异常,查看后发现,InputStream,OutputStream都实现了Closeable接口。

说明,Closeable就是用来定义关闭流的一个“规范”(接口就是一种规范)。

DataInput && DataOutput

DataInput提供从二进制流读取字节,并从其中重建任何Java原语类型的数据。 同时还提供根据 UTF-8 修改版格式的数据重构 String 的工具。

DataOutput和它相反,提供将数据从任何Java基本类型转换为一系列字节,并将这些字节写入二进制流。同时还提供了一个将 String 转换成 UTF-8 修改版格式并写入所得到的系列字节的工具。

这个两个接口中有很多的方法,具体的我也不照搬文档了,但我发现,所有的接口,都是没有访问修饰符的,即 public…,因为接口中默认的,所以的方法都是公有的,且没有方法体的。

平时的开发写代码的时候,可以模仿。还有每一个方法都有对应的注释,注释也符合java的一些规范,比如最起码的,方法描述,参数介绍,返回值…

ObjectInput &ObjectOutput

在这里插入图片描述
在这里插入图片描述
如上,ObjectInput和ObjectOutput继承了两个接口。

在ObjectInput和ObjectOutput中的方法,都用了访问修饰符。作者和版本如下。。作者是佚名,jdk中有很多的代码作者,都是佚名。
在这里插入图片描述

Serializable

Serializable接口,只是一个标记接口,就是说,它没有方法和属性。
更多关于序列化,请查看我的另一篇博客:
深入【Java】底层细节知识点 的第十七点

java.io中Externalizable接口就继承了serializable接口

Flushable

Flushable 是可刷新数据的目标地。调用 flush 方法将所有已缓冲输出写入底层流。

该接口定义了一个我们常用的方法,flush(),通过将所有已缓冲输出写入底层流来刷新此流。

还有其他的一些接口,比如: ObjectInputValidation, FileFilter ,FilenameFilter , ObjectStreamConstants


Classes部分

首先,输入流,输出流是相对内存而言的。内存在一定程度上可以理解为,程序,即你写的代码;但是代码运行其实是在内存中的。这一块,jvm会进行进一步研究。

字节流:
输入流:相对于内存,向内存中写入;
输出流:相对于内存,从内存往外读;

字符流:
Reader(字符输入流),我是这样理解的,从文件(文本)中读取一些字符,然读取到内存中;
Writer(字符输出流),从内存中拿到东西写到文件中;

类这部分,我们就按照这幅图来研究,
在这里插入图片描述

InputStream

此抽象类是表示字节输入流的所有类的超类。
在这里插入图片描述
InputStream 是一个抽象类。
类中,有两个非抽象的方法:

public int read(byte b[]) throws IOException {
	return read(b, 0, b.length);
}
/**
这两个方法本身没有什么特别,特别之处,在于,没有直接用下面的方法,
而是包了一层(上面的方法)

这种,大家也都清楚,两个方法,方法名相同,参数个数或者类型不同,
叫做方法重载。

重载的好处:便于记忆筛选,体现了java的多态
*/
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;
}

接下来,看我的一个例子,这样写起来,确实清晰明了。

public void test(int i){
	//做些什么
}

public void test(int[] intArr){
	//像这样做点什么
	test(intArr[i]);
}

public void test(int[][] intArr){
	test(intArr[i][j]);
}

再比如我项目中的一个例子:

 byte[] data = null;
 try {
      InputStream in = bi2is(bi);
      //数据在底层传输的时候,是要拆分成包,帧的
      //在进行网络操作时往往出错,因为你调用available()方法时,对发发送的数据可能还没有到达,你得到的count是0。
      int count = 0;
      while (count == 0){
        count = in.available()
      }
      data = new byte[count];
      in.read(data);
      in.close();
      // 对字节数组Base64编码
      BASE64Encoder encoder = new BASE64Encoder();
      String s = encoder.encode(data);// 返回Base64编码过的字节数组字符串
//            s=s.substring(0,10);
      return s;
  } catch (IOException e) {
      e.printStackTrace();
  }
  return "";

我们只需关注 in.read(data);这行,来理解输入流中的read方法。
in中存了一些东西,我们用read方法,读出来,然后做一些处理
在这里插入图片描述

OutputStream

对称的总是美好的~

此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。

Reader

Reader是抽象类并且有俩抽象方法(read(char[], int, int) 和 close()),所以,子类都必须重写这俩方法,但一般的子类都会自定义这俩方法。

java中的字符是Unicode编码的,是双字节的。InputStream是用来处理字节的,在处理字符文本时很不方便。Java为字符文本的输入提供了专门的一套类Reader。Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。

现在是不是有一个困惑:字节和字符的区别?

字节(Byte)是一种计量单位,表示数据量多少,它是计算机信息技术用于计量存储容量的一种计量单位。

字符是指计算机中使用的文字和符号,比如1、2、3、A、B、C、~!·#¥%……—*()-+、等等。

两者不是一个位面的东西。没有可比性。

另外:不同编码里,字符和字节的对应关系不同:

  • ASCII码中:一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。
    一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。

  • UTF-8编码中:一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。

  • Unicode编码中:一个英文字符等于两个字节,一个中文(含繁体)等于两个字节。

    符号:英文标点占一个字节;中文标点占两个字节。
    举例:英文句号“.”占1个字节的大小;中文句号“。”占2个字节的大小。

  • UTF-16编码中:一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。

  • UTF-32编码中:世界上任何字符的存储都需要4个字节。

Writer

写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()

流的使用,结束以后,一定要关闭;
1、jdk1.7之前

InputStream is = null;
try {
    //使用流
}finally {
    if(is!=null){
        is.close();//抛出异常
    }
}

2、
try-with-resource(jdk1.7以后)

try(InputStream is = null;) {
    //使用流
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值