JAVA IO 模块的整理

一、概念介绍

二、四个抽象基类

三、文件流

四、对象流

五、派生流

六、NIO简单介绍

七、socket简单介绍

有道云笔记分享地址:
http://note.youdao.com/noteshare?id=f56dc5f830a79c90fcefad642b5e9572&sub=5D3DAE5BBF6D40ECBC8D1B8AF60175F4

一、概念介绍
1、什么是IO(input/output)?
在java中简单讲就是基于数据流进行输入输出的操作(也叫读写)。这些数据流表示了字符或者字节数据的流动序列(01顺序)。

数据流是一串连续不断的数据的集合,从一段到另一端。

java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。将数据冲外存中读取到内存中的称为输入流,将数据从内存写入外存中的称为输出流。

数据源可以是键盘、文件,内存,网络
数据输出可以使显示器、打印机、文件、网络

2、什么是字节/字符?
先介绍字节的由来:
电脑怎么存储数据?核心是磁盘(软盘、硬盘、磁盘、内存、缓存)

电脑–二进制—只能识别01

图灵机(无限纸条)+晶体管(开/关状态)

电路高低电平2个状态—-磁盘—切割磁感线—电流—电压

用0和1的顺序来保存数据—–(1字节=8位)
00000000—-许
00001111—-江
11111111—-鹏
—-编码表(4,6,7,8)
电脑(计算机)—数字+符号—-4位(2^4=16)(需求和硬件设施所限)
数字+符号+字母——6位(BCDIC) (以上打卡机)
数字+符号+字母+特殊字符+欧洲字符——7位(ASCII)、
8位(IBM。向前兼容,所以成为标准)

随着计算机的发展,各国文化语言的不同。(国际化)
数字+符号+字母+各国语言—-16位(unicode)(94年)—-2^16=65536
—UTF-8、16、32—–IOS、GBK之类的,转换编码(对应规则)。
java默认采用的是unicode编码。(1字符=2字节)

“字节”是一个8位的物理存贮单元,是计算机存储的最小单位,
而“字符”则是一个文化相关的符号。

关于字和字长,看情况讲解:字:计算机处理“字节”,字长:处理的位数

3、什么是编码/解码?
上面提到编码表,也就是用“字典”的形式记录一段01序列所代表的含义。
我们知道,计算机实际存储的是单位是字节,而人们直观能理解的其实是字符
所以字节数据和字符数据之间的相互转化就叫编码和解码。

二、四个抽象基类

首先引入两个抽象基类:(JDK1.0)
public abstract class InputStream implements Closeable {
public abstract class OutputStream implements Closeable, Flushable {

从字面上理解就是:输入流和输出流(针对字节的)

随后由添加了两个抽象基类:(JDK1.1)
public abstract class Reader implements Readable, Closeable {
public abstract class Writer implements Appendable, Closeable, Flushable {

从字面上理解就是:读和写(针对字符的)

延伸1:——基本发展
一开始计算机并不是面向“大众“的,是学术界、军方等使用的,核心是面向机器的,所以一开始的输入/输出实际上只有”字节流“的相关处理。(手工打孔的纸带)
随着操作系统的出现和发展,计算机越来越面向”大众“,核心渐渐偏向了人的使用体验,所以才出现了”字符流“的相关处理。(批处理、多道、实时、通用的操作系统)

JDK历史:
1996年1月,第一个JDK-JDK1.0诞生 字节流以及派生
1996年4月,10个最主要的操作系统供应商申明将在其产品中嵌入JAVA技术
1997年2月18日,JDK1.1发布 字符流以及派生

延伸2:——编码/解码(转换流)
实际上就是字节流数据和字符流数据之间的转换。
public class InputStreamReader extends Reader { 字节到字符 解码 (读,变成字符)
public class OutputStreamWriter extends Writer { 字符到字节 编码 (写,变成字节)

构造器(字节流,编码方式)。
ex:不管是字节流还是字符流,实际上本质都是处理“字节流”,传入了字节流,那么需要继承字符流来进行进一步加工,所以名称方面 字节+字符。

延伸3:——适用情况
①字节流:视频、音频、图片
②字符流:文本 ————–(符号、文字)

③首先知道字符流是”文化符号“,文化不同—-语言不同—-文字体现。所以字符流的出现主要是为了解决文本文件的。
④其实对于文本文件也可以用字节流,但是效率不高,而且如果取的字节数定义为奇数的话可能取不到汉字,因为汉字是两个字节的,所以用字节流处理文本可能存在乱码问题。

延伸4:——接口简介
①close()程序中打开的文件 IO 资源(字节流)不属于内存里(字符流)的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。
close()方法在Closeable 中是公有的,流的打开(open)是相应实现类的构造器调用的,是私有的。

②flush()方法,内存中的缓存区域,一般情况都是缓存大小达到一定数值然后进行输出,如果最后的数据不够自动输出数值,就要手动刷出,不然调用close关闭通道,内存中的数据就不会输出的。

③Reader接口中:public int read(char cbuf[]) throws IOException {
Readable接口中:public int read(java.nio.CharBuffer cb) throws IOException; 在缓存中读取数据。

④append()可以追加字符序列。常用实现类:StringBuffer/StringBuilder

三、文件流

public class FileInputStream extends InputStream{
public class FileOutputStream extends OutputStream{

public class FileReader extends InputStreamReader { //机器上二进制字节数据,所以继承转换流
public class FileWriter extends OutputStreamWriter {

为什么引入文件流?
上面讲的字节、字符、输入、输出。都是很抽象的读/写操作。而具体到操作系统中,最直接的表现就是“文件”以及”文件夹“,文本文件、音频文件、视频文件、压缩包之类的。所以要引入文件流。

以上四个文件流,只负责数据的传输。

必须引入另一个类File类(系统中的位置、操作文件本身)
public class File implements Serializable, Comparable{
①File类对象表示一个文件或者路径。
针对File类对象本身的操作(创建/删除/重命名/文件还是目录/是否存在/路径下的文件列表、最后修改日期、获取绝对路径等等)
②只要涉及文件内容的,File是无能为力的,必须由io流来完成(参见上面4个类)。
③File类的对象常作为io流的具体实现类的构造器的形参。
④使用:通过获取文件后缀(文件名的操作),判断使用字节/字符。

四、对象流

public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants{

public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants{

①用于存储和读取对象的处理流。
可以把Java中的对象写入到数据源中(持久化),也能把对象从数据源中还原回来。
②传输的对象必须可序列化,实现以下两种接口
public interface Serializable { //空接口,只是标识而已
public interface Externalizable extends java.io.Serializable {

(属性对象是引用类,必须引用类也继承接口,否则本类不能序列化)
③第一种是自动序列化 空接口–标识作用
自动序列化对象时会跳过transient修饰的成员变量(不希望存储和传输的敏感变量eg.密码)。
第二种是手动序列化
通过实现接口方法手动添要加序列化的对象的属性(transient在这里没用)
④序列化是针对对象的(属性),所以static变量不能被序列化。

注意:
①因为transient修饰的变量不会被序列化,所以反序列化后访问是null,属性还在
但是对象对static修饰的变量操作,在反序列化后是可以访问到最新值的(JVM中类的值)
②java虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(序列化只是存储数据,还需要class文件来拼接对象,但是不会调用构造器)
③序列化 ID:固定的 1L、随机生成一个不重复的 long 类型数据(相当于密钥限定)

深入理解JAVA序列化
http://www.cnblogs.com/wxgblogs/p/5849951.html

延伸1:——为什么要序列化对象?
在Java中,对象的序列化与反序列化被广泛应用到RMI(远程方法调用)及网络传输中。
RMI:开发分布式网络应用,可以被看作是RPC的Java版本。

对象流的父接口如下:
public interface ObjectInput extends DataInput, AutoCloseable {
public interface ObjectOutput extends DataOutput, AutoCloseable {

延伸2:——为什么要继承数据流接口?
①类对象的属性不仅仅是byte、char类型,还有String、int、boolean等。
②数据流可以方便地操作Java语言的基本数据类型(8种)。
③详细见第三个——–数据流接口

五、派生流

因为派生流是由很多人共同完成的,锦上添花的功能,并不是IO流的核心。

标准流

public final class System { lang包下的,非IO体系:

public final static InputStream in = null;
public final static PrintStream out = null;
public final static PrintStream err = null;

public class PrintStream extends FilterOutputStream implements Appendable, Closeable{
字节输出流里面只有write系列方法。
打印流私有化了write方法,然后向外提供print系列的方法。

数据流

public class DataInputStream extends FilterInputStream implements DataInput {
public class DataOutputStream extends FilterOutputStream implements DataOutput {

①上面我们知道了,先有字节处理流,然后有字符处理流。.
②java中的数据类型
基本数据类型: (数据流)
整数值型:byte,short,int,long,
字符型:char
浮点类型:float,double
布尔型:boolean

引用类型:
类:(对象流)、(字符串流)
数组:(数组流)
接口
③数据流能更好的处理java语言的基本数据类型(其实就是基本类型之间的转换)。

数组流

public class ByteArrayInputStream extends InputStream {
public class ByteArrayOutputStream extends OutputStream {

public class CharArrayReader extends Reader {
public class CharArrayWriter extends Writer {

管道流

public class PipedInputStream extends InputStream {
public class PipedOutputStream extends OutputStream {

public class PipedReader extends Reader {
public class PipedWriter extends Writer {

管道流,用于线程间的通信。
构造器形参均是另一个线程对应的的处理流。
一个线程的PipedInputStream对象从另外一个线程的PipedOutputStream对象读取输入。
(connect方法:用来连接另一个线程用的—-构造器初始化管道信息之后会自动调用)

字符串流

public class StringReader extends Reader {
public class StringWriter extends Writer {

其实就是数组流中的字符数组流的升级版。

缓冲流

public class BufferedInputStream extends FilterInputStream {
public class FilterInputStream extends InputStream {

为什么引入缓冲流?
FileInputStream : public native int read() throws IOException;
BufferedInputStream: public synchronized int read() throws IOException {

调用原生的native方法(动态链接库),进行磁盘IO操作,磁盘消耗大+速度慢。
将指定大小的数据读到内存缓冲区,再调用原生read进行实际写入。

原理上讲缓冲会快一些,但是具体的性能还待定。缓冲区大小、堆缓冲区与直接缓冲区等等。

随机文件流
public class RandomAccessFile implements DataOutput, DataInput, Closeable {

由后缀就能知道,只能对文件进行操作。
记录指针———-读取部分文件内容,断点播放。
(根据文件的hashcode生成一个位置存入文件)

节点流:直接作用在输入端和输出端的。
处理流:在节点流的基础上重新包装的流。

区分:——–>看构造参数
构造参数是物理节点—–>节点流
构造参数是已经存在的流—–>处理流

六、NIO简单介绍

New IO 就是针对IO做的一些改善,核心是三个概念:
通道(Channel )、缓冲区(Buffer)、选择器(Selector)

①通道(Channel )

FileChannel:用于读取、写入、映射和操作文件的通道。
DatagramChannel:通过 UDP 读写网络中的数据通道。
SocketChannel:通过 TCP 读写网络中的数据。
ServerSocketChannel:监听 TCP 连接,每一个新进来的连接都会创建一个 SocketChannel。

TCP:先有链接,再有数据。 (打电话、都在线、专线一对一、安全)
UDP:无连接,直接发送。(发邮件、一方在线、可以面向多个、速度快)

传统流对象区别:——.>map()方法
①传统流对象是面向流的处理,通道是面向块的处理。
②流对象可以直接访问数据,通道只能和缓冲区进行数据的交互。
③通道是没有构造器的,通过对应流对象调用getChannel()进行获取不同的通道。

②缓冲区(Buffer)
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer

③选择器(Selector)

Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector
可使一个单独的线程管理多个 Channel。Selector 是非阻塞 IO 的核心。

①传统的 IO 流都是阻塞式的。
当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。
因此,在完成网络通信进行 IO 操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端需要处理大量客户端时,性能急剧下降。

标准输入流,在控制台进行输入,如果不按回车键,线程会一直阻塞,因为标准输入流用了缓冲流,读取一行数据,直到读取到换行符才结束。

② Java NIO 是非阻塞模式的。
当线程从某通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。
单独的线程可以管理多个输入和输出通道。
因此,NIO 可以让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端。

NIO支持面向缓冲区的、基于通道的IO操作,可以将文件整体或者部分内容直接映射到内存,这样访问速度就快很多。

JDK1.4之后IO包有部分类重新用NIO实现过。

七、socket简单介绍

public class ServerSocket implements java.io.Closeable {
public class Socket implements java.io.Closeable {

域名(DNS)—–>IP(计算机)——>端口(进程)
端口号与IP地址的组合得出一个网络套接字(socket)

Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输。
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端

客户端:
①据指定服务端的 IP 地址+端口号构造 Socket 类对象——建立链接
②通过socket对象获取相应的字节流
③数据的处理、关闭IO、

关闭socket链接。

服务端:
①创建socket服务端,绑定端口和监听请求。
②获取请求链接的socket对象
③通过socket对象获取相应的字节流
④数据的处理,关闭socket和socket service

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值