IO的概念以及java.io包
我的理解就是以自己的程序作为主体,输出即就是从程序中输出,输入即就是从外面输入到程序中。
输入:外部源——>程序
输出:程序——>输出目标(文件)
外部源和输出目标:磁盘文件、网络连接、内存缓存
Java程序通过流执行I/O。流(stream)是一种抽象,它要么产生信息,要么使用信息。流通过Java的I/O系统链接到物理设备。
所有流的行为方式是相同的,尽管与它们链接的设备是不同的。因此,可以为任意类型的设备应用相同的I/O类和方法。这意味着可以将许多不同类型的输入:磁盘文件、键盘或网络socket,抽象为一个输入流。反之,一个输出流可以引用控制台、磁盘文件或网络连接。流是一种处理输入/输出的清晰方式,例如,代码中的所有部分都不需要理解键盘和网络之间的区别。
流是Java在由java.io包定义的类层次中实现的。各种流类
System.in标准输入流对象:接收键盘输入
System.out标准输出流对象:直接输出到控制台
File类
File既可以表示一个文件,也可以表示一个目录或者路径。
创建File对象
File对象描述了文件/目录本身的属性。File对象用于获取和操作与磁盘文件/目录关联的信息,例如权限、时间、日期以及目录路径,并且还可以浏览子目录层次。
File(String directoryPath) //路径可以指向一个文件,也可指向一个目录
File(String directoryPath, String filename) //主要用于创建表示文件的File对象
File(File dirObj, String filename) //主要用于创建表示文件的File对象
File(URI uriObj) //URI表示网络上的一个文件
File常用的方法
- boolean exists() //File对象所表示的文件或目录是否存在
- String getName() //获取文件名或路径名
- String getPath() //返回整个路径(如果是文件的,还会包含文件名)
- String getAbsolutePath()//返回绝对路径
- boolean isFile()//判断是否是一个文件
- boolean isDirectory()//是否是一个目录
- boolean createNewFile() 创建新文件,只能创建文件,如果目录不存在,则异常
- boolean mkdir() 只能创建一层目录 make dirctory
- boolean mkdirs() 可以创建多层目录
- boolean delete() 删除文件或文件夹(要求文件夹为空)
- File[ ] listFiles() 返回值类型为list
- String[] list();
- boolean canWrite() 判断文件对象表示的文件/目录是否可以写入
- boolean canRead() 判断文件对象表示的文件/目录是否可以读取
- long length() 返回文件的长度
提示:
- 数组:length属性,数组的长度
- String:length()方法,字符串中字符的个数
- File:length()方法,文件内容的长度(字节数)
- 注意:集合使用size()方法确定集合中元素的个数
提示:File类中重写了equals()方法,比较的文件路径
流
流的概念
Java中的流是个抽象的概念,当程序需要从某个数据源读入数据的时候,就会开启一个数据流,数据源可以是文件、内存或网络等等。相反地,需要写出数据到某个数据源目的地的时候,也会开启一个数据流,这个数据源目的地也可以是文件、内存或网络等等。
流的分类
Java中的流可以从不同的角度进行分类:
- 按照流的方向不同:分为输入流和输出流。
- 按照处理数据单位的不同:分为字节流(8位)和字符流(16位)。
- 按照功能不同:分为节点流和处理流。
节点流:是可以从一个特定的数据源(节点)读写数据的流(例如文件,内存)。
处理流:是“连接”在已经存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
对其他流类进行进一步的包装,提供附加功能,例如后面介绍的各种缓存流。
要求:给出一个类名,要知道是字符流还是字节流、是输入流还是输出流
IO流结构图
字符流
1、Reader和Writer
Reader和Writer是所有字符输入流和字符输出流的父类,抽象类
Reader类定义的常用方法:
- int read() 读取单个字符。
- int read(char[] cbuf) 将字符读入数组。
- abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
Writer类定义的常用方法:
- void write(char[] cbuf) 写入字符数组。
- abstract void write(char[]cbuf, int off, int len) 写入字符数组的某一部分。
- void write(int c) 写入单个字符。
- void write(Stringstr) 写入字符串。
- void write(String str, int off, int len) 写入字符串的某一部分。
2、FileReader和FileWriter
FileReader类是Reader的子类,用于创建可以用于读取文件内容的Reader对象。
最常用的两个构造方法:
- FileReader(String filePath)
- FileReader(File fileObj)
每个构造方法都会抛出FileNotFoundException异常
FileWriter类是Writer的子类,用于创建能够用于写入文件的Writer对象。
最常用的四个构造方法:
- FileWriter(String filePath)
- FileWriter(File fileObj)
- FileWriter(String filePath, boolean append)
- FileWriter(File fileObj, boolean append)
它们都会抛出IOException异常。如果append为true,则输出被追加到文件的末尾。
FileWriter对象的创建不依赖于已经存在的文件。当创建对象时,FileWriter会在打开文件之前为输出创建文件。
字节流
1、InputStream和OutputStream类
InputStream和OutputStream是所有字节输入流和字节输出流的父类,抽象类。
InputStream抽象类定义的常用方法:
- int read() 读一次 返回一个字节对应的整数
- public int read(byte[] b)throws IOException从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
- close() //关闭流,使用完流对象后必须关系
OutputStream抽象类定义的常用方法:
- write(int b)
- write(byte[] b)
- close()
2、FileInputStream和FileOutputStream
FileInputStream类是InputStream的子类,用于创建一个可以用于从文件读取内容的InputStream对象。
两个常用的构造方法:
- FileInputStream(String filePath)
- FileInputStream(File fileObj)
都会抛出FileNotFoundException异常
FileOutputStream类是OutputStream的子类,用于创建能够用于向文件写入字节的OutputStream对象。它的四个构造方法如下所示:
- FileOutputStream(String filePath)
- FileOutputStream(File fileObj)
- FileOutputStream(String filePath,boolean append)
- FileOutputStream(File fileObj,boolean append)
它们都可能抛出FileNotFoundException异常。如果append为true,则以追加方式打开文件。
FileOutputStream对象的创建不依赖于已经存在的文件。当创建对象时,FileOutputStream会在打开文件之前创建文件。
3、DataOutputStream和DataInputStream(了解)
通过DataOutputStream和DataInputStream类,可以向流中写入基本类型数据或从流中读取基本类型数据。它们分别实现了DataOutput和DataInput接口。
DataOutputStream(OutputStream outputStream) //注意构造方法的参数
DataInputStream(InputStream inputStream)
假如,希望将一个基本类型的数据写入到文件中。
FileOutputStream fs = new FileOutputStream(“D:\\123.txt”);
DataOutputStream ds = new DataOutputStream(fs );
缓存流
缓存流属于处理流,是对其他流类增加一个内存缓存,以提高性能。即,缓存流是对其他流的进一步包装。
缓存流= 现有的流类+ 内存缓存
缓存字节流
对于面向字节的流,缓存流将一个内存缓存附加到I/O系统。这种流允许Java在一定字节上执行多次I/O操作,从而提升性能。缓存的字节流类是BufferedInputStream和BufferedOutputStream。
1、BufferedInputStream类
缓存I/O是很常见的性能优化。Java的BufferedInputStream类允许将任何InputStream对象包装进一个缓存流中以提高性能。
BufferedInputStream类有两个构造方法:
- BufferedInputStream(InputStream inputStream) //使用默认缓存大小
- BufferedInputStream(InputStream inputStream, int bufSize) //指定缓存大小
2、BufferedOutputStream类
除了增加了flush()方法之外,BufferedOutputStream与所有OutputStream类似,该方法用于确保将数据缓存写入被缓存的流中。
BufferedOutputStream是通过减少系统实际写数据的次数来提高性能的,因此可能需要调用flush()要求立即写入缓存中的所有数据。
Java中用于输出的缓存只是为了提高性能。下面是两个构造函数:
- BufferedOutputStream(OutputStream outputStream)
- BufferedOutputStream(OutputStream outputStream, int bufSize)
缓存的字符流
1、BufferedReader
BufferedReader通过缓存输入提高性能。它具有两个构造方法:
- BufferedReader(ReaderinputStream) //默认缓存大小
- BufferedReader(Reader inputStream, int bufSize)
关闭BufferedReader对象也会导致inputStream所指定的底层流被关闭。
提示:
BufferedReader类提供了ReadLine()方法,用于读取一行。
//BufferedReader类,继承了read()方法
2、BufferedWriter
BufferedWriter是缓存输出的Writer。使用BufferedWriter可以通过减少实际向输出设备物理地写入数据的次数来提高性能。
BufferedWriter具有以下这两个构造方法:
- BufferedWriter(WriteroutputStream)
- BufferedWriter(WriteroutputStream, int bufSize)
BufferedWriter类也增加了flush()方法。
序列化与反序列化
序列化(串行化)是将对象的状态写入到字节流的过程。反序列化是从流中回复这些对象。
如果希望将程序的状态保存到永久性存储区域(例如文件)这是很有用的。
Serializable接口
只有实现了Serializable接口的类能够通过串行化功能进行保存和恢复。Serializable接口没有定义成员。它简单地用于指示类可以被串行化。如果类是可串行化的,它的所有子类也是可串行化的。
不能保存static变量。
ObjectOutput和ObjectInput接口
ObjectOutput接口定义了writeObject()方法,它用于序列化对象。
ObjectInput接口定义readObject()方法,用于反序列化对象。
ObjectInputStream和ObjectOutputStream类
ObjectOutputStream类扩展了OutputStream类,并实现了ObjectOutput接口。ObjectOutputStream负责将对象写入到流中。该类的一个构造方法如下所示:
- ObjectOutputStream(OutputStream outStream) throws IOException
ObjectInputStream类扩展了InputStream类,并实现了ObjectInput接口。ObjectInputStream负责从流中读取对象。该类的一个构造方法如下所示:
- ObjectInputStream(InputStream inStream) throws IOException
形参inStream是从中读取序列化对象的输入流。
关闭ObjectInputStream对象会自动关闭inStream所指定的底层流。