IO
l File类
l IO流分类
• IO流的分类:
– IO流相对于JVM,根据传输方向划分
• 输入流
• 输出流
– IO流根据流的传输数据类型
• 字节流(按字节传输)
• 字符流(按字符传输)
l IO流体系结构,均基于四个顶层的抽象类
– 对于字节流来说
• InputStream:表示所有字节输入流的父类。
– InputStream的子类,写法都是XxxInputStream.
File f = new File("d:/hao/a.txt");
InputStream is = new FileInputStream(f);
//读取指定文件中的字节
int c = is.read();
while((c = is.read()) != -1)
{
System.out.print((char)c);
}
• OutputStream:表示所有字节输出流的父类。
– OutputStream的子类,写法均是XxxOutputStream.
– 对于字符流来说
• Reader:表示所有字符输入流的父类。
– Reader的子类,写法都是XxxReader.
• Writer:表示所有字符输出流的父类。
– Writer的子类,写法都是XxxWriter.
– 节点流和包装流
• 节点流:流对象来说,能够直接操作数据源的。
• 包装流:以节点流或包装流作为构造方法的参数。无法直接访问数据源。
l 字节流体系结构
n InputStream和OutputStream体系
– FileInputStream和FileOutputStream
• 节点流,可操作数据源文件
– ByteArrayInputStream和ByteArrayOutputStream
• 节点流,内存
– BufferedInputStream和BufferedOutputStream
• 包装流,实现缓冲
– DataInputStream和DataOutputStream
• 包装流,操作基本数据类型和String
– ObjectInputStream和ObjectOutputStream
• 包装流,操作基本数据类型和对象。
• 实现序列化和反序列化
– PrintStream
• 打印流,节点流,包装流,自动刷新,方便打印输出println方法。
l 字节流详解- 可以用于文本(较少),图片,音频,视频等操作。
• InputStream和OutputStream
– InputStream
• 1-对于输入流中的read方法,如果为接收键盘输入时,该方法是阻塞方法。当没有输入时,程序会停在read方法,等待外部输入。
• 2-对于read方法读取文件,如果已到达文件末尾,则返回 -1。
• 3-如果指定的读取文件不存在,则报FileNotFoundException异常。
– OutputStream
• 1-从程序中向文件中写信息时,如果文件不存在,则会自动创建该文件,并将数据写入到文件中;如果文件已经存在,则会覆盖已存在的文件。(覆盖相当于将原文件删除,新建文件,写入数据)
• 2-将数据写入到文件时,如果使用缓冲区,一般数据会暂时存放在缓冲区中。如果缓冲区已满,则自动将数据写入到文件中;如果缓冲区未满,则数据存放在缓冲区中。此时,必须手动的刷新缓冲区,将缓冲区中数据写入到文件中。
l FileInputStream和FileOutputStream
– 属于节点流,此时数据源是文件系统中的文件。
– FileInputStream
• 对文件内容读取。
• 包含主要方法
– int read(): 一次读取一个字节,返回int类型
– int read(byte[] bs): 一次读取多个字节,填充到bs中,返回的是真正填充到bs中的个数。
– void close():关闭对象
– int available():返回文件的字节数
– long skip(long n):忽略掉的字节数
– FileOutputStream
• 创建该对象,如果指定的文件不存在,则会自动创建该文件;如果指定的文件存在,则根据构造方法中append的值,append为false,表示覆盖重名的文件。如果想在文件末尾追加,则手动设置为true即可。
• 包含主要方法:
– void close() 关闭文件输出流对象。关闭前会刷新缓冲区
– void write(int c):一次写入一个字节
– void write(byte[] bs):一次写入一个字节数组。
– void write(byte[] bs, int index, int len):写出bs数组中一部分字节
– void flush():刷新缓冲区。
2- 带缓冲区和不带缓冲区运行速度的比较
l ByteArrayInputStream和ByteArrayOutputStream
– 属于节点流,此时数据源是字节数组(缓冲区)。close无效。
– ByteArrayInputStream
• ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
• 关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
– ByteArrayOutputStream
• 此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()获得字节数组(缓冲区)内容 和 toString() 获取字节数组转换成字符串数据,size()获得缓冲区的大小。
• 关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
l BufferedInputStream和BufferedOutputStream
– 属于包装流,实现缓冲功能。
– BufferedInputStream
• 创建 BufferedInputStream 时,会创建一个内部缓冲区数组 ,提供缓冲功能。
– BufferedOutputStream
• 该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
对于过滤流来说,只需要关闭最外层的流对象即可。
l DataInputStream和DataOutputStream
– 属于包装流,实现对Java基本数据类型和String进行读写操作。
– DataInputStream
• 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
– DataOutputStream
• 数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
– 注意:
• DataInputStream读取必须与DataOutputStream写入的顺序相同。
l ObjectInputStream和ObjectOutputStream
– 属于包装流,实现基本数据类型和对象的读写操作。
– 这两个类是实现序列化和反序列化
l PrintStream类-打印流,只能向外输出。
– PrintStream,也是OutputStream的子类。既可以作为节点流,又可以作为包装流。主要作用能够方便地打印各种数据值表示形式。
• 构造方法:
– PrintStream(File file)
– PrintStream(String fileName)
– PrintStream(OutputStream out)
– PrintStream(OutputStream out, boolean autoFlush)
» 如果atuoFlush为true,则每当写入byte数组,调用println方法或写入换行符或字节(‘\n’),都会自动刷新缓冲区。
• 常用方法:
– print(XXX)
– println(XXX)
常用字节流
总结:
l 标准的输入,输出
– 标准输出:
• System.out:表示将数据输出到控制台上。
• PrintStream ps = System.out使用PrintStream中的println,print等方法。
– 标准输入:
• System.in:表示从键盘接收数据。
• InputStream is = System.in; 使用InputStream中的read方法,获得键盘输入的数据。
• 重定向
//重定向标准输出。在此语句之后,使用System.out输出的数据,就转向了out.txt文件中 System.setOut(new PrintStream("d:/out.txt")); System.out.println("hello world");
//重定向标准输入。默认是从键盘获得输入.此语句之后,使用System.in获得数据,就是从hao.txt获取的 System.setIn(new FileInputStream("d:/hao.txt")); InputStream is = System.in; int c = -1; while((c = is.read()) != -1) { System.out.println((char)c); } |
l 字符流
对于IO其实都是以字节流形式操作。在实际使用中,文本数据比较常用,为了方便操作文本数据,对字节流进行封装,形成了字符流。
注意:
1- 字符流底层操作也是字节数据,只是对字节数据进行了处理。
2- 字符流对象中,含有码表。如果不指定,默认为JVM中的字符编码。
l Reader和Writer体系
– FileReader和FileWriter
– BufferedReader和BufferedWriter
– InputStreamReader和OutputStreamWriter
– PrintWriter
l Reader和Writer体系
– Reader类
• 用于读取字符流的抽象类
– Writer
• 用于写入字符流的抽象类
• 含有写入字符串的方法:write(String str)
l FileReader和FileWriter类
– 属于节点流,此时数据源是文件。
– 与FileInputStream,FileOutputStream类似,不同之处在于一次读取一个字符。
– FileReader和FileWriter类中的方法,都是继承自其父类。
l BufferedReader和BufferedWriter
– 属于过滤流,用于提供缓冲功能。
– BufferedReader
• 除了读取的各个方法,还提供了readLine()方法,用于读取一行字符。
– BufferedWriter
• 除了写入的各个方法,还提供了newLine()方法,用于换行。
• ‘\r\n’用于换行,但不支持跨平台。newLine()方法,可跨平台。
l InputStreamReader和OutputStreamWriter
– 转换流,可以在byte<->char之间互相转换;在转换的过程中,可以指定字符编码。
– InputStreamReader
• byte->char(解码)
– OutputStreamWriter
• char->byte(编码)
l 编码-解码
– 常见的编码表:
• ASCII:美国标准信息交换码;用一个字节的7位。
• ISO-8859-1:欧洲码表。用一个字节的8位表示。
• GB2312:中文编码表:约表示6,7千常用汉字
• GBK:中文码表,表示更多中文文字。约2万多
• GB18030:
• Unicode:万国码,所有文字用2个字节表示。Java的char型使用unicode编码。浪费空间。
• UTF-8:用最多三个字节表示一个字符。(英文占一个字节,中文占2到3个字节)
– 编码-字符或字符串转换成字节数组
• String->byte[]
– 1-str.getBytes();//按照默认字符集编码
– 2-str.getBytes(“utf-8”);//使用指定字符集编码
– 解码-字节数组转换成字符或字符串
• byte[]->String
– 1-new String(byte[]);//按照默认字符集解码
– 2-new String(byte[], “utf8”);//按照指定字符集解码
– 乱码的产生,是因为编码和解码使用的码表不一致导致。只要编码和解码码表一致即可。
l PrintWriter
– 提供方便打印字符的各种方法。可以当做节点流,也可以当做过滤流。
– 与 PrintStream 类不同,如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。
– 构造方法:
• 构造方法中可以有File, String, Writer(有刷新的重载构造方法),除此之外,还包含OutputStream(含有刷新的重载构造方法)(因为中间使用了OutputStreamWriter转换流)。
• println,print方法。