1 Java IO原理
- I/O是input/output的缩写,IO技术是非常实用的技术,用于处理设备之间的数据传输。如读写文件,网络通讯等。
- Java程序中,对于数据的输入输出操作以“流Stream”的方式进行。
- java.io包下提供了各种“流”类和接口,用来获取不同种类的数据,并通过标准的方法输入或输出数据。
- 输入:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
- 输出:将程序(内存)数据输出到磁盘、光盘等存储设备中。
2 IO流的分类
2.1 按照操作数据单位的不同
- 字节流
- 字符流
2.2 按照数据流的流向不同
- 输入流
- 输出流
2.3 按照流的角色的不同
- 节点流:直接从数据源源或目的地读写数据。
- 处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
2.4 抽象基类
- Java的IO流一共涉及到40多个类,实际上非常规则,都是从上面的4个抽象基类派生出来的。
- 由这四个类派生出来的子类的名称大都是以其父类名作为子类名的后缀。
3 字符流
3.1 概述
- 字符流只能操作普通文本文件,比如.txt、.java、.c等。
3.2 FileReader
- 将文件的内容读取,一次只能读取一个字符,读取到文件末尾的时候返回-1。
public int read() throws IOException{}
- 示例:
package day20; import java.io.File; import java.io.FileReader; import java.io.IOException; /** * 使用FileReader读取文件 */ public class FileReaderTest { public static void main(String[] args) { File file = new File("D:" + File.separator + "a.txt"); FileReader fileReader = null; try { fileReader = new FileReader(file); int ch; while (-1 != (ch = fileReader.read())) { System.out.print((char) ch); } } catch (Exception e) { e.printStackTrace(); } finally { if (null != fileReader) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
- 读取文件的内容,一次可以读取指定长度的字符。
package day20; import java.io.File; import java.io.FileReader; import java.io.IOException; /** * 使用FileReader读取文件 */ public class FileReaderTest { public static void main(String[] args) { File file = new File("D:" + File.separator + "a.txt"); FileReader fileReader = null; try { fileReader = new FileReader(file); char[] buffer = new char[1024]; int len = 0 ; while (-1 != (len = fileReader.read(buffer))){ System.out.print(new String(buffer,0,len)); } } catch (Exception e) { e.printStackTrace(); } finally { if (null != fileReader) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
3.3 FileWriter
- 示例:
package day20; import java.io.File; import java.io.FileWriter; import java.io.IOException; /** * 将内存的内容写入到文件中 */ public class FileWriterTest { public static void main(String[] args) { File file = new File("b.txt"); FileWriter fileWriter = null; try { fileWriter = new FileWriter(file); fileWriter.write("abcedf"); } catch (IOException e) { e.printStackTrace(); } finally { if(null != fileWriter){ try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
3.4 复制
- 示例:
package day20; import java.io.*; public class FileReaderWriterTest { public static void main(String[] args) { FileReader fileReader = null; FileWriter fileWriter = null; try { fileReader = new FileReader(new File("b.txt")); fileWriter = new FileWriter(new File("c.txt")); char[] chs = new char[1024]; int len; while (-1 != (len = fileReader.read(chs))) { fileWriter.write(chs, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != fileReader) { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != fileWriter) { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
4 字节流
- 字节流一般用于处理非文本类,比如视频、音频、Word文档、PPT等。
- 示例:使用字节流复制文件。
package day20; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileInputOutputStreamTest { public static void main(String[] args) { FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(new File("hello.txt")); fileOutputStream = new FileOutputStream(new File("world.txt")); byte[] bytes = new byte[1024]; int len; while (-1 != (len = fileInputStream.read(bytes))) { fileOutputStream.write(bytes,0,len); } } catch (Exception e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
5 缓冲流
5.1 概述
- 为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类的时候,会创建一个内部缓冲区数组,缺省使用8192个字节的缓冲区。
- 缓冲流要“套接”在相应的节点流之上,根据数据操作单位的不同可以将其分为:
- BufferedInputStream和BufferedInputStream。
- BufferedReader和BufferedWriter。
- 当读取数据的时候,数据按块读入到缓冲区,其后的读操作则直接访问缓冲区。
- 当使用BufferedInputStream读取字节文件的时候,BufferedInputStream会一次性的从文件中读取8192个字节(8KB),存在缓冲区,等到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。
- 像流中写入字节的时候,不会直接在到文件中,先写到缓冲区直到缓冲区写满,BufferedOutputStream才会把缓冲区的数据一次性写到文件里。
- 关闭流的顺序和打开流的顺序相反。只要关闭最外层的流即可。
- 如果是调用带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出。
5.2 应用示例
- 示例:
package day20; import java.io.*; public class BufferedStreamTest { public static void main(String[] args) { BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try { bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("hello.txt"))); bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File("world.txt"))); byte[] bytes = new byte[1024]; int len; while (-1 != (len = bufferedInputStream.read(bytes))) { bufferedOutputStream.write(bytes, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedInputStream != null) { try { bufferedInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedOutputStream != null) { try { bufferedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
- 示例:
package day20; import java.io.*; public class BufferedStreamTest { public static void main(String[] args) { BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { bufferedReader = new BufferedReader(new FileReader(new File("hello.txt"))); bufferedWriter = new BufferedWriter(new FileWriter(new File("world.txt"))); char[] chs = new char[1024]; int len; while (-1 != (len = bufferedReader.read(chs))) { bufferedWriter.write(chs, 0, len); } } catch (Exception e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
- 示例:
package day20; import java.io.*; public class BufferedStreamTest { public static void main(String[] args) { BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { bufferedReader = new BufferedReader(new FileReader(new File("hello.txt"))); bufferedWriter = new BufferedWriter(new FileWriter(new File("world.txt"))); String str; while (null != (str = bufferedReader.readLine())) { bufferedWriter.write(str); bufferedWriter.newLine(); } } catch (Exception e) { e.printStackTrace(); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
6 转换流
6.1 概述
- 转换流提供了在字节流和字符流之间的转换。
- Java API提供了两个转换流:
- InputStreamReader:将InputStream转换为Reader。
- OutputStreamWriter:将Writer转换为OutputStream。
- 如果字节流中的数据都是字符的时候,转换成字符流操作更高效。
- 很多时候我们使用转换流来处理文件乱码问题,实现编码和解码的功能。
6.2 应用示例
- 示例:
package day20; import java.io.*; import java.nio.charset.StandardCharsets; /** * 转换流的使用 */ public class TransformationTest { public static void main(String[] args) { InputStreamReader inputStreamReader = null; OutputStreamWriter outputStreamWriter = null; try { inputStreamReader = new InputStreamReader(new FileInputStream("hello.txt"), StandardCharsets.UTF_8.toString()); outputStreamWriter = new OutputStreamWriter(new FileOutputStream("world.txt"), StandardCharsets.UTF_8.toString()); char[] chs = new char[1024]; int len; while (-1 != (len = inputStreamReader.read(chs))) { outputStreamWriter.write(chs, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (outputStreamWriter != null) { try { outputStreamWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
7 标准输入、输出流(了解)
7.1 概述
- System.in和System.out分别代表了系统标准的输入和输出设备。
- 默认情况下,输入设备是键盘,输出设备是显示器。
- System.in的类型是InputStream。
- System.out的类型是PrintStream,是OutputStream的子类。
- 重定向:通过System类的setIn()和setOut()方法对默认设备进行改变。
7.2 应用示例
- 示例:
package day20; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class SystemTest { public static void main(String[] args) { BufferedReader br = null; try { InputStreamReader isr = new InputStreamReader(System.in); br = new BufferedReader(isr); while (true) { System.out.println("请输入字符串:"); String data = br.readLine(); if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)) { System.out.println("程序结束"); break; } String upperCase = data.toUpperCase(); System.out.println(upperCase); } } catch (IOException e) { e.printStackTrace(); } finally { if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
8 打印流(了解)
8.1 概述
- 实现将基本数据类型的数据转换为字符串输出。
- 打印流:PrintStream和PrintWriter。
- 提供了一系列重载的print()和println()方法,用于多种数据类型的输出。
- PrintStream和PrintWriter的输出不会抛出IOException异常。
- PrintStream和PrintWriter有自动flush的功能。
- PrintStream打印的所有字符都使用平台的默认字符编码转换字节。在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类。
- System.out返回的是PrintStream的实例。
8.2 应用示例
- 示例:
package day20; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintStream; public class SystemTest { public static void main(String[] args) throws FileNotFoundException { System.setOut(new PrintStream(new FileOutputStream("a.txt"),true)); System.out.println("aa"); System.out.println("我是中国人,我深情的爱着我的祖国和人民!!"); } }