Java IO -Streams

 


引言

在Java编程中,IO(输入/输出)操作是与外部世界交互的基础。无论是读取用户输入、写入文件还是通过网络传输数据,IO都是不可或缺的一部分。本文将深入探讨Java IO的各个方面,帮助您掌握这一关键技术。

Java IO基础

Java IO基于两个主要的抽象:  (Streams)和 通道 (Channels)。流是数据传输的通道,而通道是流的源头或目的地。

Streams

字节流与字符流

字节流操作原始二进制数据,适合处理图片、音频等非文本文件。而字符流操作字符数据,并自动处理字符编码的转换,适合文本文件的处理。


字节流示例

  1. try (FileInputStream fis = new FileInputStream("binaryfile.bin")) {
  2.   byte[] buffer = new byte[fis.available()];
  3.   fis.read(buffer);
  4.   // 处理字节数据
  5. } catch (IOException e) {
  6.   e.printStackTrace();
  7. }

字符流示例

  1. try (FileReader fr = new FileReader("textfile.txt")) {
  2.   char[] buffer = new char[1024];
  3.   int numChars;
  4.   while ((numChars = fr.read(buffer)) > 0) {
  5.       // 处理字符数据
  6.   }
  7. } catch (IOException e) {
  8.   e.printStackTrace();
  9. }

特殊流

对字节流或者字符流进行二次包装而产生的

缓冲流

缓冲流是字节流和字符流的包装类。缓冲流通过内部缓冲区减少物理读写次数,显著提高IO效率。BufferedInputStreamBufferedOutputStream``BufferedReaderBufferedWriter可以减少实际的IO操作次数,提高效率。

缓冲流示例

  1. try (BufferedReader br = new BufferedReader(new FileReader("textfile.txt"))) {
  2.   String line;
  3.   while ((line = br.readLine()) != null) {
  4.       // 处理每一行文本
  5.   }
  6. } catch (IOException e) {
  7.   e.printStackTrace();
  8. }

数据流

  1. 数据流是专门为了读写基本数据类型设计的,可以看作是字节流的子集,字节流的包装类。数据流可以自动处理基本数据类型的转换,如intdouble
  2. 数据流提供了方便的方法来读取和写入基本数据类型

数据流示例

  1. try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("datafile.dat"))) {
  2.   dos.writeInt(2024);
  3.   dos.writeDouble(3.14159);
  4. } catch (IOException e) {
  5.   e.printStackTrace();
  6. }

对象流

对象流是字节流的扩展,提供了对对象的序列化支持,可以将对象的状态转换为字节序列,或从字节序列中恢复对象状态

对象流示例

  1. try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("objectfile.dat"))) {
  2.   MySerializableClass obj = new MySerializableClass();
  3.   oos.writeObject(obj);
  4. } catch (IOException e) {
  5.   e.printStackTrace();
  6. }

结构图





  1. @startuml
  2. skinparam classAttributeColorBackground PaleGreen
  3. skinparam classStereotypeColor NavyBlue
  4. class InputStream {
  5. - int read()
  6. ...
  7. }
  8. class OutputStream {
  9. - void write(int b)
  10. ...
  11. }
  12. class Reader {
  13. - int read(char[] cbuf)
  14. ...
  15. }
  16. class Writer {
  17. - void write(char[] cbuf, int off, int len)
  18. ...
  19. }
  20. class ObjectInputStream {
  21. - T readObject()
  22. ...
  23. }
  24. class ObjectOutputStream {
  25. - void writeObject(Object obj)
  26. ...
  27. }
  28. class FileInputStream {
  29. + InputStream inputStream
  30. }
  31. class FileOutputStream {
  32. + OutputStream outputStream
  33. }
  34. class FileReader {
  35. + Reader reader
  36. }
  37. class FileWriter {
  38. + Writer writer
  39. }
  40. class BufferedInputStream {
  41. + InputStream inputStream
  42. }
  43. class BufferedOutputStream {
  44. + OutputStream outputStream
  45. }
  46. class BufferedReader {
  47. + Reader reader
  48. }
  49. class BufferedWriter {
  50. + Writer writer
  51. }
  52. class DataInputStream {
  53. + InputStream inputStream
  54. ...
  55. }
  56. class DataOutputStream {
  57. + OutputStream outputStream
  58. ...
  59. }
  60. class Serializable {
  61. -- 序列化接口
  62. }
  63. ObjectInputStream ..|> InputStream
  64. ObjectOutputStream ..|> OutputStream
  65. InputStream <|-- FileInputStream
  66. OutputStream <|-- FileOutputStream
  67. Reader <|-- FileReader
  68. Writer <|-- FileWriter
  69. InputStream <|-- BufferedInputStream
  70. OutputStream <|-- BufferedOutputStream
  71. Reader <|-- BufferedReader
  72. Writer <|-- BufferedWriter
  73. InputStream ..|> DataInputStream
  74. OutputStream ..|> DataOutputStream
  75. ObjectOutputStream .. Serializable
  76. @enduml

总结

  1. 当你需要处理文本数据时,应使用字符流
  2. 当你需要处理二进制数据时,应使用字节流
  3. 当你需要提高读写效率时,可以在字节流或字符流的基础上使用缓冲流
  4. 当你需要读写基本数据类型时,可以使用数据流
  5. 当你需要将对象的状态保存到文件或通过网络传输时,应使用对象流