Java语法进阶13-文件、IO流

File

File是文件和目录路径名的抽象表示形式,即File类是文件或目录的路径,而不是文件本身,因此File类不能直接访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。

File类的对象用来表示文件和文件夹的对象。

如果这个路径名对应的文件或目录不存在,那么在堆中的File对象的成员变量就是默认值。

如果这个路径名对应的文件或目录存在,那么在堆中的File对象就根据这个路径找到对应的文件或目录,然后将一些信息获取到为File对象的成员变量赋值

File 类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变。

常用方法

方法签名方法功能
File(String pathName) 根据文件、目录的路径名构建File对象
File(String parent, String child) 构建File对象,路径名通过指定父目录与子目录方式来指定
public File(File parent,String child) 从父抽象路径名和子路径名字符串创建新的 File实例
String getName() 获取文件名
long length() 获取文件大小,无法直接获取目录大小,空目录返回0
String getPath() 获取构造路径
String getAbsolutePath() 获取绝对路径
String getCanonicalPath() 获取规范路径
long lastModified() 获取文件最后修改时间
boolean isFile() 判断是否是文件
boolean isDirectory() 判断是否是目录
boolean exists() 判断文件或目录是否实际存在
boolean isHidden() 判断是否隐藏
boolean isAbsolute() 判断是否是绝对路径
boolean canRead() 判断是否可读
boolean canWrite() 判断是否可写
createNewFile() 当且仅当具有该名称的文件尚不存在时,创建文件
mkdir()或mkdirs() 创建目录
delete() 删除文件或空目录
renameTo(File dest) 重命名文件或目录
String[] list() 获取目录里面的文件或子目录,返回String数组
File[] listFiles() 获取目录里面的文件或子目录,返回File数组
File[] listFiles(FileFilter filter) 根据过滤条件获取目录里面的文件或子目录

无论该路径下是否存在文件或者目录,都不影响File对象的创建。

如果文件或目录不存在,那么exists()、isFile()和isDirectory()都是返回false

调用listFiles方法的File对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历。

绝对路径:从盘符开始的路径,这是一个完整的路径。

相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。

规范路径:所谓规范路径名,即对路径中的“..”等进行解析后的路径名

创建和删除临时文件

  • public void deleteOnExit():当退出JVM时,删除文件,一般用于删除临时文件,一旦请求,无法取消。

  • public static File createTempFile(String prefix,String suffix) throws IOException在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。调用此方法等同于调用 createTempFile(prefix, suffix, null)。

    • prefix - 用于生成文件名的前缀字符串;必须至少三个字符。

    • suffix - 用于生成文件名的后缀字符串;如果为 null,默认为 ".tmp"

  • public static File createTempFile(String prefix,String suffix,File directory)throws IOException在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。

    • prefix - 用于生成文件名的前缀字符串;必须至少三个字符。

    • suffix - 用于生成文件名的后缀字符串;如果为 null,默认为 ".tmp"

    • directory - 将创建的文件所在的目录;如果使用默认临时文件目录,则该参数为 null

IO

Stream即流向内存的是输入流(Reader,Input),流出内存的输出流(Writer,Output)。

  • 输入流 :把数据从其他设备上读取到内存中的流。

    • 以InputStream,Reader结尾

  • 输出流 :把数据从内存 中写出到其他设备上的流。

    • 以OutputStream、Writer结尾

  • 字节流 :以字节为单位,读写数据的流。

    • 以InputStream和OutputStream结尾

  • 字符流 :以字符为单位,读写数据的流。

    • 以Reader和Writer结尾

  • 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.

  • 处理流:是对一个已存在的流进行连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。并且可进行多次包装

InputStream基类:字节输入流

抽象类字节流可以传输任意文件类型数据

  • int read():读一个字节,如果流中没有数据了,返回-1。

  • int read(byte[] data):一次读取多个字节,最多读取data.length个,把读取的数据放到data中,从data[0]开始存储,如果流中没有data.length个,那么有几个读取几个,返回实际读取的字节的个数。如果流中没有数据了,返回-1。

  • int read(byte[] data, int offset, int count):一次读取多个字节,最多读取count个,把读取的数据放到data中,从data[offset]开始存储,如果流中没有count个,那么有几个读取几个,返回实际读取的字节的个数。如果流中没有数据了,返回-1。

  • void close():关闭流资源

OutputStream基类:字节输出流

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。

  • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。

  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。

  • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。

  • public abstract void write(int b) :将指定的字节输出流。

FileInputStream类

继承InoutStream方法同上,文件输入流,从文件中读取字节。

构造方法

  • FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。

  • FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException

long skip(long n) :从输入流中跳过并丢弃 n 个字节的数据。 

读取字节read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1

FileOutputStream类

继承OutputStream方法同上,文件输出流,用于将数据写出到文件。

构造方法

  • public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。

  • public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。

  • public FileOutputStream(String name, boolean append):指定 String文件名name的文件输出流

   public FileOutputStream(File file, boolean append):指定 File 对象的文件输出流,append为true表示追加数据,false 表示清空原有数据

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据,或指定追加。

系统中的换行:

  • Windows系统里,每行结尾是 回车+换行 ,即\r\n

  • Unix系统里,每行结尾只有 换行 ,即\n

  • Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。

流的关闭原则:先开后关,后开先关。

Reader基类:字符输入流

抽象类以字符为单位读写数据,专门用于处理文本文件

  • public int read(): 读取一个字符,如果已经到达流末尾,没有数据可读了,返回-1.

  • public int read(char[] cbuf): 读取多个字符到data数组中,从data[0]开始存储,最多读取data.length个字符。返回的是实际读取的字符数。如果已经到达流末尾,没有数据可读了,返回-1.

  • abstract int read(char[] data, int offset, int len):读取多个字符到data数组中,从data[offset]开始存储,最多读取len个字符。返回的是实际读取的字符数。如果已经到达流末尾,没有数据可读了,返回-1.
  • public void close() :关闭此流并释放与此流相关联的任何系统资源
  •  long skip(long n) : 跳过n字符。 

FileReader类

继承Reader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

构造方法

  • FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象。

  • FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的名称。

当你创建一个流对象时,必须传入一个文件路径。其方法同上继承父类方法

虽然读取了一个字符,但是会自动提升为int类型。

Writer基类:字符输出流

抽象类表示用于写出字符流,将指定的字符信息写出到目的地

  • void write(int c) 写入单个字符。

  • void write(char[] cbuf)写入字符数组。

  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。

  • void write(String str)写入字符串。

  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。

  • void flush()刷新该流的缓冲。

  • void close() 关闭此流,但要先刷新它。

FileWriter类

继承Writer类是写出字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

  • FileWriter(File file): 创建一个新的 FileWriter,给定要读取的File对象。

  • FileWriter(String fileName): 创建一个新的 FileWriter,给定要读取的文件的名称。

  • FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象以及指示是否附加写入数据。
  • FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

当你创建一个流对象时,必须传入一个文件路径,其方法同上继承父类方法

未调用close方法,数据只是保存到了缓冲区,并未写出到文件中,即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。

操作IO流的步骤

(1)创建合适的IO流的对象

(2)读、写

(3)关闭IO流

要么只关闭最外层的IO流,要是都关的话,注意顺序,先关外面的再关里面的。

缓冲流

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

字节缓冲流BufferedInputStreamBufferedOutputStream

  • public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。亦可指定缓冲区大小(InputStream in, int size) 

  • public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流。亦可指定缓冲区大小(OutputStream out, int size) 

字符缓冲流BufferedReaderBufferedWriter

  • public BufferedReader(Reader in) :创建一个 新的缓冲输入流。亦可指定缓冲区大小(Reader in, int sz) 

  • public BufferedWriter(Writer out): 创建一个新的缓冲输出流。亦可指定缓冲区大小(Writer out, int sz) 

字符缓冲流的特有方法。

  • BufferedReader:public String readLine(): 读一行文字。

  • int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分从off开始读len个。 实现了基类的抽象方法
  • BufferedWriter:public void newLine(): 写一行行分隔符,由系统属性定义符号。

  • void write(char[] cbuf, int off, int len) :写入字符数组的某一部分从off开始写len个。实现了基类的抽象方法

转换流

解码:字节(看不懂的)-->字符(能看懂的)

编码:字符(能看懂的)-->字节(看不懂的) 

InputStreamReader类

  • InputStreamReader(InputStream in): 创建一个使用系统默认字符集的字符流。

  • InputStreamReader(InputStream in, String charsetName): 创建一个指定字符集的字符流。

是Reader的子类,用来解码包装字节流,把字节输入流包装为字符输入流。

应用场景:读取源为字符类型的字节流可指定字符集解码成字符流,以便阅读

OutputStreamWriter类

  • OutputStreamWriter(OutputStream in): 创建一个使用系统默认字符集的字符流。

  • OutputStreamWriter(OutputStream in, String charsetName): 创建一个指定字符集的字符流。

是Writer的子类,用来编码包装字节流,把字节输出流包装为字符输出流。

应用场景:可将要写入的字符源为字节流的数据转为字符类型写入并可按指定字符集再编码存储

转换流是字节与字符间的桥梁

数据流

 继承字节流可直接处理Java的基本数据类型,要求读写顺序一一对应

DataOutputStream:数据输出流

  • writeUTF(String)

  • writeInt(int)

  • writeDouble(double)

  • writeChar(char)

  • writeBoolean(boolean)

DataInputStream:数据输入流

  • String readUTF()

  • int readInt()

  • double readDouble()

  • char readChar()

  • boolean readBoolean()

序列化

对象序列化,用一个字节序列可以表示一个对象,该字节序列包含该对象的类型对象中存储的属性等信息,可将字节序列写出到文件。反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

 

ObjectOutputStream类

public final void writeObject (Object obj) : 将指定的对象写出到OutputStream流。

  • 该类必须实现java.io.Serializable 标记接口,不实现此接口的类将不会使任何状态序列化或反序列化,会抛NotSerializableException 

    • 如果对象的某个属性也是引用数据类型,那么如果该属性也要序列化的话,也要实现Serializable 接口

  • 该类的所有属性必须是可序列化的。如果有一个属性不需要可序列化的,则该属性必须注明是瞬态的,使用transient 关键字修饰。

  • 静态变量的值不会序列化

ObjectInputStream类

如果能找到一个对象的class文件,我们可以进行反序列化操作,调用ObjectInputStream读取对象的方法:

  • public final Object readObject () : 读取一个对象到InputStream流。

另外,当JVM反序列化对象时,能找到class文件,但是class文件在序列化对象之后发生了修改,那么反序列化操作也会失败,抛出一个InvalidClassException异常发生这个异常的原因如下:

  • 该类的序列版本号与从流中读取的类描述符的版本号不匹配

  • 该类包含未知数据类型

Serializable 接口给需要序列化的类,提供了一个序列版本号serialVersionUID 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

java.io.Externalizable接口

实现这个接口,可以自定义需要被系列化的属性使得对象能够被序列化,但是要求程序员重写两个方法:

void writeExternal(ObjectOutput out) :编写哪些属性需要序列化

void readExternal(ObjectInput in) :编写哪些属性需要反序列化

注意:读取的顺序要与写的顺序一致,虽然可以自己决定任意属性的输出和读取,但是还是建议不要输出静态的和transient属性。

PrintStream类

字节流该类调用print方法和println方法能够方便地打印各种数据类型的值,是一种便捷的输出方式。

System.in:InputStream类型对象

System.out:PrintStream类型对象

System.err:PrintStream类型对象

Scanner类

有多个构造方法可由多种方式生成从指定流的扫描对象,并实现了迭代器接口

  • boolean hasNextXxx(): 如果通过使用nextXxx()方法,此扫描器输入信息中的下一个标记可以解释为默认基数中的一个 Xxx 值,则返回 true。

  • Xxx nextXxx(): 将输入信息的下一个标记扫描为一个Xxx

新try..catch

语法格式:

try(需要关闭的资源对象的声明){
   业务逻辑代码
}catch(异常类型 e){
   处理异常代码
}catch(异常类型 e){
   处理异常代码
}
....

它没有finally,也不需要程序员去关闭资源对象,无论是否发生异常,都会关闭资源对象

posted @ 2019-12-10 22:34  远离颠倒梦想  阅读(...)  评论(...编辑  收藏