我们知道,当我们运行一个程序时,我们将Java对象加载进了JVM的内存当中,使得程序可以运行起来,当程序终止时,这些存储在JVM的Java代码就消失了,被垃圾回收了。那么,如果我们希望将Java对象以Java对象的形式保存在电脑的物理磁盘上或者希望从磁盘上读取Java信息(比如硬盘)或者我们希望在网络之间传输Java对象,应该怎么办呢?针对这种需求,Java的IO流应运而生了,IO流是作为硬盘与JVM内存的交流数据的媒介而产生的。
针对JavaIO流,我们依次讲述他的知识点。
① File类
Java中任何的操作都是要通过对象类实现的,一个文件也不例外。为此,Java中用File类的对象来指代一个文件或文件目录。
格式:File file = new File(文件路径);如File file = new File("d://io//Helloworld.txt");
文件路径格式中,//和/都可以,但是//更好,因为它可以适应夸平台性。
绝对路径:包括盘符号在内的定位的文件路径。
相对路径:当前文件目录(当前工程)下的路径。
File类对象的五类常用方法,这些方法仅仅涉及文件的创建,删除和重命名和获取文件的属性等,一旦关系到文件的具体内容,File对象就无能为力了,这就需要IO流来操作文件的具体内容。
访问文件名及相关的方法:file.getName();file.getPath();file.getAbsolutePath();file.getParent();file.renameTo(file1)要求file文件一定存在,file2文件一定不存在。
文件检测的方法:exists();canWrite();canRead();isFile();isDirectory()
获取文件常规信息:lastModified();length()
目录操作相关:file.mkdir();file.mkdirs();file.list();file.listFiles()
文件操作相关:file.delete();file.createNewFile()
② IO流概述
在Java中,IO流用来处理设备之间的数据传输,相对于Java程序,数据的输入/输出操作以流的形式进行。Java.io包下提供了各种流的类和接口,来获取不同种类的数据,并且通过标准的方法输入或输出数据。无论是输入还是输出数据,都输站在程序的角度上来考虑的。
② IO流的分类
按照流向:输入流和输出流(流入程序,从程序流出)
按照传输载体:字节流(视频/音频等)和字符流(文本文档)
按照角色:节点流(直接将内容传输,程序直接作用在文件上,四个FileInputStream,FileOutputStream,FileReader,FileWriter)和处理流(内部包含了节点流,作用流的好处是加速了节点流的传输)
四个抽象基类:InputStream,OutputStream,Reader,Writer所有的IO流的类都是从以上四个抽象基类派生的,是这四个抽象基类的子类,即所有的子类都是以其父类名作为子类名的后缀。
③ 节点流的使用
节点流又称文件流,所以四个抽象基类对应的节点流类(在基类前都加上File关键字)分别为:FileInputStream,FileOutputStream,FileReader,FileWriter.
FileInputStream:从磁盘读取一个文件的内容到程序中,这个对象指代文件的内容。可用其对象的read(new byte[1024])方法从文件读取内容到byte数组,返回字节的数目,当内容读取完毕时,方法返回-1。读取文件的内容时,这个文件一定要存在,否则会报异常。
FileOutputStream:从程序读出内容到文件。这个文件可以不存在,会自动创建;若存在,会覆盖文件的内容。
FileReader:将文件中的内容读取到程序中。传输形式是字符流。
FileWriter:从程序中读出内容到文件中。传输形式是字符流。
字符流仅仅试用于存取txt文档(且读取速度比字节流快),word也不行,图片也不行(虽然不报错,但是得到的图片会损坏,无法显示)。音频视频之类的大文件更要用字节流。
④ 缓冲流的使用
缓冲的英文意思是buffer,所以缓冲流对应四个Java流抽象基类的类是:BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。
真正开发的时候,我们使用缓冲流替代节点流,因为缓冲流的效率很高,再具体点是因为传统的IO流是阻塞式的,即read()和writer()方法是阻塞式的,当读取一个字节时,打开JavaIO资源,阻塞;读取完毕再打开IO资源,读取下一个,这样的效率很慢,因为只要没有读完,JavaIO资源就不会关闭。使用缓冲流我们采取了空间换取时间的策略,就是在磁盘或者内存中再开辟一片存储空间,当读入时,将内容通过节点流预先读入到一个空间中,然后用缓冲流包裹起来再读到程序中,这样就提升了效率;当读出时,我们先用节点流读出到一个内存中的空间中,然后再用缓冲流读出到磁盘中。
注意,我们将节点流的对象作为形参传递给缓冲流的构造器来使用,同时在关闭缓冲流之后,内部包含的节点流也会关闭,不必再手动关闭节点流。
使用缓冲流时,当read()方法读取完一次时,最好用flush()方法刷新一下。
BufferedWriter()还有一个readLine()方法可以有效的读取文件中的一行内容,效率也有提高。
⑤ 转换流
转换流的作用是为了将字节流转换为字符流。为什么要将字节流转换为字符流呢?这是因为当时word之类的文本文档时,不能用字符流只能用字节流先引入到Java程序中,然后再在Java程序中使用转换流将字节流转换为字符流进行处理,会更加的高效。
转换流时直接作用在节点流之上的,根据转换流的定义,与四个抽象基类对应的也只有两个转换流类:InputStreamReader(将输入字节流转换为输入字符流)和OutputStreamWriter(将输出字节流转换为输出字符流)。
一般来说,我们将字节流转换成字符流的过程中需要一个编码的过程,这时就用到了InputStreamReader,编码的时候默认按照GBK的编码方式。
将字符流转换为字节流的时候就是一个解码的时候,解码要和编码采取同样的规则才可以,默认也是使用GBK。
⑥标准输入输出流的使用
标准输入流:从键盘输入到程序中。System.in
标准输出流:从程序输出到控制台。System.out
⑦打印流和数据流
打印流:PrintStream打印输出字节流;PrintWriter打印输出字符流。
数据流:用来处理Java语言基本数据类型,String类型,字节数组的数据。实现类:DataInputStream,DataOutputStream。用来读取和写入基本数据类型的数据。
⑧ 对象流的使用
用于在磁盘和JVM虚拟机中读入和写出Java对象的处理流。它的强大之处在于可以把Java当中的对象写入到数据源中保存起来,也可以从数据源中将保存的Java对象读到程序中,在二者传递的过程中,是以二进制流的方式来传递的(就要用到Java当中的序列化机制)。
两个实现类:ObjectInputStream和ObjectOutputStream。
序列化:使用ObjectoutputStream将Java当中的对象以二进制流的形式(保存的二进制流是乱码)写入到磁盘中保存起来或通过网络传输到另一个节点。
反序列化:使用ObjectInputStream将保存在磁盘上的二进制流以Java对象的方式读取到Java程序中。
序列化的好处:可以将任何实现了Serializable接口的实现类的对象转化为字节数据,并使这种二进制流数据在保存或者传输的情况下还原成Java对象。
Java对象所在的类必须实现Serializable或者Externalizable接口以后,这个Java对象才可以实例化;而且这个类中的属性所在的类也必须实现序列化接口。
序列化的版本标识符:一个类实现了序列化接口,最好在这个类中在定义一个序列化的版本标识符,为了确保类不同版本的序列化兼容。
注意:一个类对象可以序列化和反序列化必须满足三点:类实现序列化接口,类中属性也实现序列化接口,类中有一个版本标识符。
⑨ RandomAccessFile类的使用。
RandomAccessFile类支持随机访问的方式,程序可以直接跳到文件的任意位置来读、写文件内容。RandomAcessFile对象包含一个记录指针,用于标识当前读写的位置。而且这个对象可以自动移动记录指针。
这个对象还有两个方法:getFilePointer();获取当前记录指针的位置。seek(long position):将文件的记录指针放到posotion指定的位置。
RandomAccessFile对象既可以当输出流对象使用又可以当输入流对象使用。
构造器:RandomAccessFile(File file,String mode)。这个mode可以使r(只读),rw(可写可读),rwd(可写可读,并且同步文件的更新),rws(可写可读,并且同步文件内容和元数据更新)。