1、 关于流的概念:流根据方向可以分为:输入流和输出流。(注意,输入和输入是相对于内存而言的,从内存中出来叫做输出,到内存中就是输入。输入流有叫做InputStream,输出流有叫做OutputStream。输入有叫做“读Read”,输出还叫做“写Write”。)

  • 流根据读取数据的方式可以分为:字节流和字符流,字节流是按照字节的方式读取,字符流是按照字符的方式读取,一次读取2个字节,java语言中一个字符占2个字节。(字节流适合读取视频、声音、图片等二进制文件;字符流读取纯文本文件。)
  • Java语言中所有的字节流都以Stream结尾,所有的字符流都含有Reader或者Writer。
  • 需要掌握的16个流:(java.io) FileInputStream/FileOutputStream/FileReader/FileWriter; BufferedReader/BufferedWriter/BufferedInputStream/BufferedOutputStream; DataInputStream/DataOutputStream; ObjectInputStream/ObjectOutputStream; InputStreamReader/OutputStreamWriter;(转换流:将字节流转换成字符流) PrintWriter/PrintStream(标准的输出流【默认输出到控制台】);

2、java语言中的流分为:四大家族(InputStream、OutputStream、Writer、Reader)

  • InputStream、OutputStream的继承结构图:

  • Reader和Writer的继承结构图:


3、 java.io.FileInputStream;文件字节输入流:

  • 可以使用构造器FileInputStream(String name)传递文件路径(相对路径或者绝对路径)参数创建FileInputStream对象:(需要注意的是,在windows操作系统中,表示文件路径可以使用“/”或者是“\”,但是“\”在java字符串中有特殊的含义,需要使用“\”转义字符表示反斜杠;在linux系统中采用正斜杠“/”。)

  • 使用read()方法来读取字节(一次读取一个字节,读取至末尾后,再读取会返回-1):(需要注意,读取返回值为int类型,为ascll编码值,读取效率低):

  • 使用read(byte[] b)方法来读取多个字节(字节数有指定传递的参数b指定,返回值为读取的总字节个数):

  • 构造器String(byte[] bytes)方法可以将byte[]数组中的所有字节解码转换成字符串:

  • 构造器String(byte[] bytes, int offset, int length) 可以将byte[]数组中的指定的子数组中的字节解码成字符串:

  • close()方法用以关闭流(流开启后必须关闭),在finally语句块中使用,需要判断该流是否为null再进行关闭:

  • available()方法返回流中剩余的估计的字节数:

  • skip(long n)方法表示在这个输入流中跳过并抛弃n个字节:


4、 java.io.FileOutputStream;文件字节输出流:(推荐结束前为了保证数据全部写入硬盘,进行刷新操作)

  • 构造器FileOuptStream(String name)方法创建FileOutputStream对象,此构造器会将源文件中的内容覆盖,谨慎使用。(如果文件不存在则自动创建)

  • 构造器FileOuptStream(String name, boolean append)方法表示创建FileOutputStream对象,并在写入数据到文件中时是以追加的方式写入:

  • String类的getBytes()方法:把字符串编码成指定的的字节序列,并存储在新创建的一个字节数组中:

  • 将字节数组中的所有字节写入到文件输出流中:

  • Flushable接口中的flush()方法:强制刷新输出流,以此保证将所有的缓存中的字节/字符全部写入流中:

  • 将字节数组中的子数组中的指定字节写入到文件输出流中:


5、java.io.FileReader:文件字符输入流(需要注意,字节读取文本文件可能会导致乱码,因为byte类型为1字节;所以文本文件尽量选择使用字符流,因为char类型为2字节)

  • 构造器FileReader(String fileName)方法和FileInputStream类似。

  • 抽象类Reader中的read(char[] cbuf)方法:读取字符数组中的所有字符序列,每次方法调用返回读取的字符序列个数;读取至末尾后,该方法再次读取会返回-1。

  • 类InputStreamReader中的read(char[] cbuf, int offset, int length)方法:读取字符数组中的部分字符序列,每次方法调用返回读取的字符序列个数;读取至末尾后,该方法再此读取会返回-1。


6、java.io.FileWriter:文件字符输出流

  • 构造器FileWriter(String fileName)方法创建文件字符输出流,字符序列写入文件时覆盖文件内容。

  • 构造器FileWriter(String fileName, boolean append)方法创建文件字符输出流,字符序列写入文件时追加文件内容。

  • 类OutputStreamWriter中的write(String str, int off, int len)方法:写入指定字符串的一部分。

  • 类OutputStreamWriter中的write(char[] cbuf, int off, int len)方法:写入指定字符数组的一部分。


7、java.io.BufferedReader:带有缓冲区的字符输入流(将文件字符输入流包装成带有缓冲区的的字符输入流)

  • 构造器创建一个BufferedReader对象(处理流或者说是包装),参数为一个Reader类型的对象,可以为FileReader对象。(需要注意的是,关闭只需要关闭最外层的包装流即可。)

  • readLine()方法中从流中读取一行数据:(如果返回的对象为null,则表示读取已结束。行尾不带换行符。)

  • java.io.InputStreamReader中的构造器InputStreamReader(InputStream in)方法可以将InputStream字节输入流转换成InputSreamReader转换流。 (InputStreamReader类继承至Reader抽象类)

  • System.in返回的是一个标准的输入流,默认接收键盘输入:


8、java.io.BufferedWriter:带有缓冲区的字符输出流:

  • 构造器BufferedWriter(Writer out)方法和BufferedWriter构造器方法类似:

  • newLine()方法向输出流中写入一个行分隔符:

  • write(char [] cbuf, int off, int len)方法向输出流中写入字符数组中的一部分:

  • write(String s, int off, int len)方法像输出流中写入字符串中的一部分:


9、java.io.DataOutputStream:数据字节输出流(可以将内存中的 int i = 10;写入到硬盘文件中,写进入的不是字符串,写进入的是二进制数据(带类型))

  • 构造器DataOutputStream(OutputStream out)方法创建一个新的数据输出流将内存中数据写入到指定的底层输出流中:

  • 将内存中的java数据写入到底层输出流中:(写入的文件为二进制文件。)


10、java.io.DataInputStream:数据字节输入流(需要注意的是,要使用该流读取数据,必须提前知道该文件中数据的存储格式和顺序。读取的顺序必须和写入的顺序相同。)

  • 读取数据字节输入流中的数据值:

11、java.io.PrintStream:标准的输出流,默认打印到控制台,以字节方式。(PrintStream ps = System.out;)

  • 可以改变输出方向:重新指定标准输出流(可以将打印输出到指定的文件中)

  • 构造器PringStream方法创建新的打印流(需要传递OutputStream参数对象)


12、java.io.ObjectOutputStream:序列化java对象到硬盘。(Serial)(需要序列化的java对象,对象类需要实现Serializable接口)

  • 构造器ObjectOutputStream(OutputStream out)方法创建序列化流(需要传入一个字节输出流对象):(文件中写进入的数据为二进制文件)

  • java.io.Serializable接口是一个“可序列化的”标识接口,该接口没有任何方法。(与之类似的接口还有:java.lang.Cloneable接口【可克隆的】)

  • 标识接口的作用:起到标识的作用,JVM如果看到该对象实现了某个标识接口,给予特殊的待遇。(给类实现Serializable接口,在编译时编译器会给该类添加一个long serialVersionUID(static final)序列化版本号属性,在序列化后的硬盘文件中记录该序列化版本号,以此和反序列化时编译后的对象类中的序列化版本号做对比。)

  • writeObject(Object obj)方法将指定的对象写入到序列化流中:


13、java.io.ObjectInputStream:将硬盘中的数据“反序列化”到JVM内存中。(DeSerial)(在反序列化的过程中,序列化时创建的对象类的.class文件将会被会被重新使用。)

  • ObjectInputStream类构造器与ObjectOutputStream类构造器相似:

  • 从反序列化流中读取一个对象:


14、序列化版本号:如果一个类实现Serializable接口,(所谓的特殊待遇)会给该类添加一个long serialVersionUID(static final)属性。(如果将该对象类重新编译(重新生成对象类的.class文件),序列化版本号属性serialVersionUID可能会发生变化【如果类中的代码发生改变】。)

  • 序列化版本号不对应,反序列化时可能会出现java.io.InvalidClassException异常:
  • 一般情况下,不让系统自动生成,自己在类中手动提供一个序列化版本号。
  • 如果不想让类中属性参加序列化,需要使用transient关键字修饰。

15、java.io.File类:File类与流无关,不能通过该类完成文件的读和写。(File是文件和目录路径名的抽象表示形式。即代表的是硬盘中的文件或者目录)

  • 构造器File(String pathname)方法通过将给定的路径名字符串来创建File对象:

  • exists()方法检测File对象中给定的绝对路径中是否存在对应的文件或者目录:

12a0977cc1ceb215e83cff548aac2f54.png

  • mkdir()方法或者createNewFile()方法是指在当前路径中创建目录或者文件:(使用exists()方法进行检测)

  • mkdirs()方法是指创建多重目录(如果使用exists()方法进行检测目录不存在。)

  • 判断File对象表示的文件是否可执行、可读、可写:

  • getAbsolutePath()方法获取绝对路径:

  • getParent()方法获取文件或者是目录中的父路径:(或者为null,如果不存在父目录)

  • lastModified()方法获取文件最后一次修改时间:

  • length()方法返回文件的长度(字节数):

  • listFiles()方法返回绝对路径(绝对路径为目录的情况)下的所有File数组(包括文件和目录):