11.IO流

第十一章【IO流】

一、流的概念

​ 数据以二进制的形式在程序设备之间流动传输,就像水在管道里流动一样,所以就把这种数据传输的方式称之为输入流、输出流。

二、流的分类

根据数据的流向分为:输入流和输出流

  • 输入流 :把数据从其他设备上读取到程序中的流

  • 输出流 :把数据从程序中写出到其他设备上的流

根据数据的类型分为:字节流和字符流

  • 字节流 :以字节为单位(byte),读写数据的流

  • 字符流 :以字符为单位(char),读写数据的流

总的分类:

  • 字节输入流,在程序中,以字节的方式,将设备(文件、内存、网络等)中的数据读进来

  • 字节输出流,在程序中,以字节的方式,将数据写入到设备(文件、内存、网络等)中

  • 字符输入流,在程序中,以字符的方式,将设备(文件、内存、网络等)中的数据读进来

  • 字符输出流,在程序中,以字符的方式,将数据写入到设备(文件、内存、网络等)中

三、流的结构

几乎所有的流,都是派生自四个抽象的父类型:

  • InputStream,代表字节输入流类型

  • OutputStream,代表字节输出流类型

  • Reader,代表字符输入流类型

  • Writer,代表字符输出流类型

基本流【节点流】:

​ 字节输入输出流:xxxInputStream/xxxOutputStream 【xxx:设备】

​ 字符输入输出流:xxxReader/xxxWriter

包装流:字节输入输出流,字符输入输出流

image-20210308195603878

一般情况下,一个流,会具备最起码的三个特点:

  • 是输入还是输出
  • 是字节还是字符
  • 流的目的地

四、字节流

1、概述

java.io.InputStream是所有字节输入流的抽象父类型

java.io.OutputStream是所有字节输出流的抽象父类型

在代码中,使用流操作数据的的基本步骤是:

  1. 声明流
  2. 创建流
  3. 使用流
  4. 关闭流
2、控制台

让程序一直读取和写出,那么可以加入while循环,遇到“bye”结束

public class InputAndOutputStreamTest3 {
	public static void main(String[] args) {
		//1.声明流
		InputStream in = null;
		OutputStream out  = null;
		//2.创建流
		in = System.in;
		out  = System.out;
		//3.使用流
		int num = -1;
		byte[] by = new byte[1024];
		try {
			while ((num = in.read(by)) != -1) {
				out.write(by, 0, num);
				out.flush();
				if(by[num -1] == 10 && by[num -2] == 13) {
					num = num - 2;
				}
				String str = new String(by, 0, num);
				if(str.equals("bye")) {
					break;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//4.关闭流
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
3、字节数组

java.io.ByteArrayInputStream负责从字节数组中读取数据

java.io.ByteArrayOutputStream负责把数据写入到字节数组中

使用字节流,从字节数组中读取数据,以及向字节数组中写数据。

public class ByteArrayStreamTest {
	public static void main(String[] args) {
		//1.声明流
		InputStream in = null;
		OutputStream out = null;
		//2.创建流
		byte[] arr = "hello world".getBytes();
		in = new ByteArrayInputStream(arr);
		out = new ByteArrayOutputStream();
		//3.使用流
		int len = -1;
		byte[] by = new byte[1024];
		try {
			len = in.read(by);
			out.write(by, 0, len);
			out.flush();
			//4.可视化到控制台
			String str = out.toString();
			System.out.println(str);
			//5.调用ByteArrayOutputStream中的toByteArray方法,可以将写入到out对象中的数据返回
			byte[] array = ((ByteArrayOutputStream)out).toByteArray();
			System.out.println(Arrays.toString(array));
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			//6.关闭流
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
4、管道

java.io.PipedInputStream负责从管道中读取数据

java.io.PipedOutputStream负责将数据写入到管道中

使用字节流,可以从管道中读取数据,以及向管道中写数据。

public class PipedStreamTest {
	public static void main(String[] args) {
		//1.声明流
		PipedInputStream in = null;
		PipedOutputStream out = null;
		//2.创建流
		in = new PipedInputStream();
		out = new PipedOutputStream();
		//3.管道对接
		try {
			in.connect(out);
			
			Thread t1 = new WriterThread(out);
			Thread t2 = new ReaderThread(in);
			t1.start();
			t2.start();
			t1.join();
			t2.join();
			
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		System.out.println();
		System.out.println("程序运行结束");
	}
}

class WriterThread extends Thread{
	private OutputStream out;
	public WriterThread(OutputStream out) {
		this.out = out;
	}
	@Override
	public void run() {
		byte[] arr = "hello world".getBytes();
		
		try {
			for (int i = 0; i < arr.length; i++) {
				out.write(arr[i]);
				out.flush();
				Thread.sleep(100);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

class ReaderThread extends Thread{
	private InputStream in;
	public ReaderThread(InputStream in) {
		this.in = in;
	}
	@Override
	public void run() {
		int len = -1;
		try {
			while ((len = in.read()) != -1) {
				System.out.write(len);
				System.out.flush();
			}
			System.out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
5、文件

java.io.File类,是java中对文件和目录的抽象表示,主要用于文件和目录的创建、查找和删除等操作。

常用方法:

public String getAbsolutePath(),返回file的绝对路径

public String getPath() ,返回创建file对象时传入的路径参数(有可能是相对路径)

public String getName(),返回file的名字

public long length(),file如果表示文件,则返回文件内容的长度(字节个数)

public boolean exists(),判断此文件或目录是否真的存在

public boolean isDirectory() ,判断File表示的是否是一个目录

public boolean isFile(),判断file表示的是否是一个文件

使用字节流,可以从文件中读取数据,以及向文件中写数据。

java.io.FileInputStream,负责从文件中读取数据

java.io.FileOutputStream,负责把数据写入到文件中

public class FileStreamTest {
	public static void main(String[] args) {
		//1.声明流
		InputStream in = null;
		OutputStream out = null;
		
		//2.创建流
		try {
			File f1 = new File("src/com/sxu/day19/test/a.txt");
			File f2 = new File("src/com/sxu/day19/test/b.txt");
			in = new FileInputStream(f1);
			out = new FileOutputStream(f2);
			
			//3.使用流
			int len = -1;
			byte[] by = new byte[1024];
			
			while ((len = in.read(by)) != -1) {
				out.write(by,0,len);
			}
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
6、网络

转至 12.网络编程.md

五、字符流

1、概述

字符流,可以用字符的形式,读写数据,专门用于处理文本数据。

java.io.Reader是所有字符输入流的抽象父类型

java.io.Writer是所有字符输出流的抽象父类型

2、字符数组

使用字符流,从字符数组中读取数据,以及向字符数组中写数据。

java.io.CharArrayReader负责从字符数组中读取数据

java.io.CharArrayWriter负责把数据写入到字符数组中

public class ReaderAndWriterStreamTest {
	public static void main(String[] args) {
		//1.声明流
		Reader in = null;
		Writer out = null;
		
		//2.创建流
		char[] arr = "hello world".toCharArray();
		in = new CharArrayReader(arr);
		out = new CharArrayWriter();
		
		//3.使用流
		int len = -1;
		char[] ch = new char[1024];
		try {
			len = in.read(ch);
			out.write(ch, 0, len);
			out.flush();
			
			String str = out.toString();
			System.out.println(str);
			
			//CharArrayWriter中的toCharArray方法,可以将写入到out对象中的数据返回
			char[] charArray = ((CharArrayWriter)out).toCharArray();
			System.out.println(Arrays.toString(charArray));
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
3、管道

使用字符流,可以从管道中读取数据,以及向管道中写数据。

java.io.PipedReader负责从管道中读取数据

java.io.PipedWriter负责将数据写入到管道中

public class PipedTest {
	public static void main(String[] args) {
		PipedReader in = null;
		PipedWriter out = null;
		
		in = new PipedReader();
		out = new PipedWriter();
		
		try {
			in.connect(out);
			
			Thread t1 = new WriterThreaed(out);
			Thread t2 = new ReaderThread(in);
			
			t1.start();
			t2.start();
			t1.join();
			t2.join();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println();
		System.out.println("程序运行结束");
	}
}

class WriterThreaed extends Thread{
	private Writer out;
	public WriterThreaed(Writer out) {
		this.out = out;
	}
	@Override
	public void run() {
		char[] arr = "hello world".toCharArray();
		
		try {
			for (int i = 0; i < arr.length; i++) {
				out.write(arr[i]);
				out.flush();
				Thread.sleep(100);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

class ReaderThread extends Thread{
	private Reader in;
	public ReaderThread(Reader in) {
		this.in = in;
	}
	@Override
	public void run() {
		int len = -1;
		
		try {
			while ((len = in.read()) != -1) {
				System.out.write(len);
				System.out.flush();
			}
			System.out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
4、文件

使用字符流,可以从文件中读取数据,以及向文件中写数据。

java.io.FileReader ,负责从文件中读取数据

java.io.FileWriter ,负责把数据写入到文件中

public class FileTest {
	public static void main(String[] args) {
		//1.声明流
		Reader in = null;
		Writer out = null;
		
		try {
			//2.创建流
			File f1 = new File("src/com/sxu/day20/test/a.txt");
			File f2 = new File("src/com/sxu/day20/test/b.txt");
			
			in = new FileReader(f1);
			out = new FileWriter(f2);
			
			//3.使用流
			int len = -1;
			char[] ch = new char[1024];
			
			while ((len = in.read(ch)) != -1) {
				out.write(ch,0,len);
			}
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(out != null) {
				try {
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
5、其他

其他情况,使用字符流进行读写数据时,可以借助于字节流,将字节流转换为字符流来操作。因为字符流底层也是以字节为单位来操作数据的,只不过中间会把字节按照默认或指定的字符编号,把字节转成了字符而已。

六、节点流

字节流和字符流,都属于节点流

它们的特点是,可以【直接】读取某一个地方的数据,或者【直接】把数据写入到某一个地方。

七、数据流

DataOutputStream负责把指定类型的数据,转化为字节并写出去

DataInputStream负责把读取到的若干个字节,转化为指定类型的数据

八、缓冲流

字节缓冲流

java.io.BufferedInputStream,负责给字节输入流提供缓冲功能

java.io.BufferedOutputStream,负责给字节输出流提供缓冲功能

字符缓冲流

java.io.BufferedReader,负责给字符输入流提供缓冲功能

java.io.BufferedWriter,负责给字符输出流提供缓冲功能

九、转换流

java.io.OutputStreamWriter ,可以将字节输出流转换为字符输出流,并指定编码

java.io.InputStreamReader,可以将字节输入流转换为字符输入流,并指定编码

十、对象流

在java中,并非所有对象都可以进行序列化和反序列化,而是只有实现了指定接口的对象才可以进行。java.io.Serializable接口
java.io.ObjectOutputStream,将Java对象转换为字节序列,并输出到内存、文件、网络等地方java.io.ObjectInputStream,从某一个地方读取出对象的字节序列,并生成对应的对象

java中的关键字transient,可以修饰类中的属性,它的让对象在进行序列化的时候,忽略掉这个被修饰的属性

十一、随机访问流

java.io.RandomAccessFile是JavaAPI中提供的对文件进行随机访问的流

posted @ 2024-04-14 23:54  可乐爱兑姜汁  阅读(2)  评论(0编辑  收藏  举报