IO流的详解!超详细!

青旅半醒 2021-11-16 13:20 393阅读 0赞

IO流

Java的IO通过java.io包下的类和接口来支持,在java.io包下主要包括输入、输出两种IO流,每种输入、输出流又可以分为字节流和字符流两大类。其中字节流是以字节为单位来处理输入输出的操作,而字符流则是以字符来处理输入输出的操作。除此之外,JavaIO使用了一种装饰器设计模式,又可以将IO流分为底层的节点流和上层的处理流。

流的分类:

1:输入流和输出流

输入流:只能从中读取数据,不能写入数据。

  1. 输出流:只能写入数据,而不能读取数据。

Java中的输入流主要是右InputStream和Reader作为基类,而输出流主要是由OutputStream和Writer作为基类。他们都是抽象类,无法创建实例。

2:字节流和字符流

字节流:的操作数据单元是8位字节。

字符流:的操作数据是16位字符。

字节流中 InputStream与OutputStream为字节流的基类,Reader和Writer为字符流的基类。

3:节点流和处理流

节点流:可以向/从 一个特定的IO设备读写数据的流, 节点流连接着数据源和程序。互相关联。

处理流:用于对已经存在的一个流进行连接和封装,通过封装后的流来实现数据的读写功能。程序使用处理流之后并不会直接连接到数据源,使用处理流的好处是,只要使用相同的处理流,程序就可以采用完全相同的输入输出代码访问不同的数据源,随着处理流封装的节点流的变化,程序实际访问的数据源也发生了变化。

流的概念模型

字节流和字符流处理的方式非常的相似,只是输入输出的单位不同而已,输入流使用隐式指针来记录从哪个位置开去读取,每当InputStream或者Reader里取出一个数据后,记录的指针自动向后移一位,除此之外,InputStream和Reader都提供了一些二方法来记录了指针的移动。输出流也一样。

处理流可以嫁接在任何一个已经存在的流的基础之上,这就允许了Java采用了相同的代码,透明的方式来访问不同的输入/输出设备的数据流,通过使用处理流,Java程序不需要在意输入输出的节点是什么,程序只要把这些节点包装成处理流,就可以使用相同的处理流的代码来进行读写。

字节流和字符流

1:输入流

InputStream和Reader是输入流的抽象基类,本身不能创建实例来进行输入,但是他们是所有输入流的模板。

它们的操作方式基本一样,只是inputStream操作的是字节,而Reader操作的是字符。

InputStream(字节输入流)方法:

int read():从输入流中读取单个字节,返回读取字节的数据。

int read(byte[ ]b):从输入流中读取最多b.length个字节的数据。并把读取出来的数据存取在b数组中,返回实际读取的字节数。

int read(byte[ ]b,int off,int len):从输入流最多读取len个字节的数据,放入数组b中,从off的位置开始存放,返回实际读取的字节数。

Reader(字节输出流的方法大致相同,字节输入流只不过存取读取的数据用byte类型的数组来进行存,但是reader使用char类型的数组进行存取,因为它是字符输入流)

那么我们如何判断读取的数据到了结尾呢?根据指针的指引,每次读取一个数据,指针向后指引,当指针为-1的时候,便说明了读取完毕。就到达了输入流的结束点。

由于inputStream和OutputStream都是抽象类,本身不能创建实例,但是他们都有一个读取文件的输入流:FileInputStream和FileReader。他们本身都是节点流————直接和文件相关联

  1. package fileinput;
  2. import java.io.FileInputStream;
  3. import java.io.FileNotFoundException;
  4. public class FileInput {
  5. public static void main(String[] args) throws Exception {
  6. FileInputStream fileInputStream=new FileInputStream("G:\\a.txt");
  7. //向使用b数组来存取G盘文件的内容
  8. //因为程序创建了长度为1024的数组来进行读取,但是长度却达不到1024,所以说只要执行一次read
  9. //就能读取所有的文本数据
  10. byte[]b=new byte[1024];
  11. //length定义一个记录存取长度的变量
  12. int len=0;
  13. while ((len=fileInputStream.read(b))!=-1){
  14. System.out.println(new String(b,0,len));
  15. }
  16. fileInputStream.close();
  17. }
  18. }

20190728144913595.png

使用FileReader来读取文件:

  1. package fileinput;
  2. import java.io.FileReader;
  3. import java.io.IOException;
  4. public class FileReaderTest {
  5. public static void main(String[] args) throws IOException{
  6. FileReader fileReader=new FileReader("G:\\b.txt");
  7. char[]c=new char[1024];
  8. int len=0;
  9. while ((len=fileReader.read(c))!=-1){
  10. System.out.println(new String(c,0,len));
  11. }
  12. fileReader.close();
  13. }
  14. }

20190728145309710.png

2:输出流(字节输出流和字符输出流)

OutputStream和Writer也非常相似

OutputStream输出流的三种方法:

1:void write(int c) 将指定的字节字符输出到输出流中,其中c既可以代表字节,也可以代表字符。

2:void write(byte【】/char【】buf):将指定的字节数组或者字符数组输出到输出流中

3:void write(byte[ ]/char [ ]buf,int off,int len)将字节数组或者字符数组从off的位置开始,长度为len的字节或者字符输出到输出流当中。

writer的方法也相似,只不过字节输出流输出的是字节或者字符,而writer输出的是字符串String

下面使用FileInputStream来进行输入,FileOutputStream来进行输出,实现文字的复制:

  1. package fileinput2;
  2. import fileinput.FileInput;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. public class CopyTest {
  7. public static void main(String[] args) throws IOException{
  8. //读取a的文件内容
  9. FileInputStream fileInputStream=new FileInputStream("G:\\a.txt");
  10. byte[]b=new byte[1024];
  11. int len=0;
  12. len=fileInputStream.read(b);
  13. fileInputStream.close();
  14. //将读取内容写入b
  15. FileOutputStream fileOutputStream=new FileOutputStream("G:\\b.txt");
  16. fileOutputStream.write(b,0,len);
  17. fileOutputStream.close();
  18. //将B中文件进行输出
  19. FileInputStream fileInputStream1=new FileInputStream("G:\\b.txt");
  20. while ((len=fileInputStream1.read(b))!=-1){
  21. System.out.println(new String(b,0,len));
  22. }
  23. fileInputStream1.close();
  24. }
  25. }

通过字符流实现文字拷贝:

  1. package fileinput2;
  2. import java.io.File;
  3. import java.io.FileReader;
  4. import java.io.FileWriter;
  5. import java.io.IOException;
  6. public class CopyString {
  7. public static void main(String[] args) throws IOException{
  8. FileReader fileReader=new FileReader("G:\\a.txt");
  9. char[]c=new char[1024];
  10. int len=0;
  11. len=fileReader.read(c);
  12. fileReader.close();
  13. //读取
  14. FileWriter fileWriter=new FileWriter("G:\\b.txt");
  15. fileWriter.write(c,0,len);
  16. fileWriter.close();
  17. //打印b
  18. FileReader fileReader1=new FileReader("G:\\b.txt");
  19. while((len=fileReader1.read(c))!=-1){
  20. System.out.println(new String(c,0,len));
  21. }
  22. fileReader1.close();
  23. }
  24. }

我们使用了输出输出流的4个抽象的基类,并且使用了4中方法来对文件输入输出等访问,

字节流 基类:FileInputStream FileOutputStream 字符流基类:FileReader FileWriter

输入流:FileInputStream FileReader 输出流:FileOutputStream FileWriter

发现使用起来比较繁琐,所以我们需要一种办法来简化操作,这时我们需要认识一下处理流了。

处理流:

我们尝试用PrintStream来对FileOutputStream进行处理输出

  1. package chuliStream;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.io.PrintStream;
  5. public class PrintStreamTest {
  6. public static void main(String[] args)throws IOException {
  7. FileOutputStream fileOutputStream=new FileOutputStream("G:\\a.txt");
  8. PrintStream ps=new PrintStream(fileOutputStream);//对字节流进行包装
  9. ps.println("嘿嘿嘿");
  10. ps.println("哈哈哈哈");//可以将里面的内容进行存储
  11. ps.close();//我们只需要关闭最上层的处理流,包装的节点流也就关闭了
  12. }
  13. }

转换流:

将字节流转换成字符流,有两个InputStreamReader和OutputStreamWriter

为什么只是字节流转换成字符流?

因为大家都知道,字节流用途更广,但是字符流操作起来比较方便,当我们知道一个文件都是文本内容,但是我们只有一个字节流,操作起来相当繁琐,所以我们需要转换流来对字节流进行转换,这样操作起来就十分的方便。

就比如说我们要从键盘上获取数据,但是标准的输入流是InputStream是字节流,处理起来十分难受,但是键盘输入的都是文本内容。普通的Reader的方法读取文本也很繁琐,所以我们引入转换输入流InputStreamReader(字符输入流),再将字符输入流包装成为BufferedReader。使用readLine方法进行一行一行读取,十分方便。

  1. package chuliStream;
  2. import java.io.*;
  3. public class ZhuanHuanLiu {
  4. public static void main(String[] args)throws Exception {
  5. InputStreamReader inputStreamReader=new InputStreamReader(System.in);
  6. BufferedReader b=new BufferedReader(inputStreamReader);//包装转换字符流
  7. // System.out.println(b.readLine());//将键盘输入的进行打印
  8. FileOutputStream file=new FileOutputStream("G:\\b.txt");
  9. OutputStreamWriter outputStreamWriter=new OutputStreamWriter(file);
  10. BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);//处理流效率高
  11. bufferedWriter.write(b.readLine());
  12. bufferedWriter.close();
  13. b.close();
  14. }
  15. }

对象的序列化:

对象的序列化就是将对象目标保存在磁盘中,或者允许网络中直接传输对象,Java序列化的机制是允许将对象直接转化为网络中的二进制流,可以通过这种二进制流传输到网络中的另一个节点,其他网络中或者程序中获得了该二进制流都可以将其还原成Java中之前的对象。

对象的序列化:是将Java中的对象写入IO流中。

对象的反序列化:从IO流中读取到 Java对象。

为了让某个类的对象可以序列化,这个类必须要是可以序列化的,所以就需要导入Serializable接口。

因为传输的是 对象,所以我们需要引入两个处理流

ObjectInputStream、ObjectOutputStream 对象输入流和对象输出流

因为这两个流都是处理流,需要包装节点类,所以在使用他们的时候还需要一个节点流来搭配着使用

ObjectOutputStream使用方法

TCP 发送方 和接收方,发送方发送对象,接收方接受对象,返回ok

  1. package socket;
  2. import java.io.*;
  3. import java.net.Socket;
  4. public class SSocket {
  5. public static void main(String[] args) throws Exception{
  6. Socket socket=new Socket("192.168.55.16",9999);
  7. ObjectOutputStream objectOutputStream=new ObjectOutputStream(
  8. socket.getOutputStream());
  9. Person p=new Person("刘大",11);
  10. Person p2=new Person("六二",15);
  11. objectOutputStream.writeObject(p);
  12. objectOutputStream.writeObject(p2);
  13. InputStreamReader inputStreamReader=new InputStreamReader(socket.getInputStream());
  14. BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
  15. String str=bufferedReader.readLine();
  16. System.out.println(str);
  17. objectOutputStream.close();
  18. inputStreamReader.close();
  19. socket.close();
  20. }
  21. }
  22. package socket;
  23. import java.io.*;
  24. import java.net.ServerSocket;
  25. import java.net.Socket;
  26. public class ServerSocketTest {
  27. public static void main(String[] args)throws Exception {
  28. ServerSocket serverSocket=new ServerSocket(9999);
  29. while (true) {
  30. Socket socket = serverSocket.accept();
  31. ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
  32. System.out.println(objectInputStream.readObject());
  33. System.out.println(objectInputStream.readObject());
  34. OutputStreamWriter outputStreamWriter=new OutputStreamWriter(socket.getOutputStream());
  35. BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);
  36. bufferedWriter.write("ok");
  37. //刷新
  38. bufferedWriter.newLine();
  39. bufferedWriter.flush();
  40. objectInputStream.close();
  41. outputStreamWriter.close();
  42. socket.close();
  43. }
  44. }
  45. }

发表评论

表情:
评论列表 (有 0 条评论,393人围观)

还没有评论,来说两句吧...

相关阅读

    相关 IO详细资源

    前言 io流用到的地方很多,就比如上传下载,传输,设计模式等....基础打扎实了,才能玩更高端的。 在博主认为真正懂IO流的优秀程序员每次在使用IO流之前都会明确分析如下

    相关 IO详解.

    目录: > 一、IO流概述 > 二、FileInputStream初步 > 三、FileOutStream的使用 > 四、文件复制 > 五、FileRead

    相关 IO-IO详细总结

    前言 io流用到的地方很多,就比如上传下载,传输,[设计模式][Link 1]等…基础打扎实了,才能玩更高端的。 真正懂IO流的优秀程序员每次在使用IO流之前都会明确分