要想java学的好,IO流就必须会

什么是IO流呢,换句话来说什么是流呢?
我们来看下什么是流。

流简介

Java把这些不同类型的输入、输出源抽象为流(stream),用统一接口来表示,从而使程序简单明了。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流 等等
Java对数据的操作是通过流的方式,IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的对象都在IO包中。

流分类

我们在java中,将流分类的
按数据流的方向不同:输入流In,输出流Out。
按处理数据单位不同:字节流,字符流。
字节流:数据流中最小的数据单元是字节。
顶层为抽象类
InputStream OutputStream
字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
顶层为抽象类
Writer Reader
对象流

按功能不同:节点流,处理流。
(1)程序用于直接操作目标设备所对应的类叫节点流。
(2)程序通过一个间接流类去调用节点流类,以达到更加灵活方便地读写各种类型的数据,这个间接流类就是处理流。
**

我们来看图让我们对这个更加清晰一些

流体系

在这里插入图片描述
在这里插入图片描述这篇文章我们来认识一些字节流吧

字节流

字节流
常用方法
int read()每次读一个字节
int read(char cbuf[])读取cbuf指定数组大小的字节数装载到cbuf中【最后一次有多少读多 其它位置为默认值】
int read(char cbuf[], int offset, int length) 读取数据装载到cbuf数组中,指定开始位置和长度
int available( );调用此方法表还有多少数据可以读取
close( );关闭
字符流
常用方法
void write(int)写数据
void close()关闭流
void flush()强制输出
我们来看下字节流最简单的一个流
文件输入输出流FileInputStream
在这里插入图片描述在这里插入图片描述在这里插入图片描述上面的是字节流的文件输入输出流的案例 是不是很简单的
接下来我们来看下稍微加点难度的
缓冲流
BufferedInputStream

BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。
特点:
缓冲区、处理流
不多说我们直接上代码

	package byte_stream;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.FileInputStream;

/**
 * 缓冲输入流
 * @author wenber
 *
 */
public class TestBufferedInputStream {
	
	public static void main(String[] args) {
		
		FileInputStream fis=null;
		BufferedInputStream bis=null;
		try {
			//创建节点流
			fis=new FileInputStream("d:/test/readme.txt");
			//创建处理流[带缓冲]
			bis=new BufferedInputStream(fis);
			
			//标记位置
			bis.mark(0);
			//流中还有多少字节可读
			System.out.println(bis.available());
			//读取数据
			System.out.println("第一次读取="+(char)(bis.read()));
			//流中还有多少字节可读【每读一次少一次】
			System.out.println(bis.available());
			//==================================重置
			bis.reset();//回到标记的位置 重新开始
			System.out.println("重新开始==="+(char)(bis.read()));
			
			//跳过指定的字节数 进行读取
			bis.skip(1);
			System.out.println("skip==="+(char)(bis.read()));
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				if(fis!=null)fis.close();
				if(bis!=null)bis.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		
		
	}

}

在这里插入图片描述我们来看下字节数组输入输出流
ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。 关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
看代码

package byte_stream;

import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 * 测试ByteArray流
 * @author wenber
 *
 */
public class TestByteArray {
	
	public static void main(String[] args) {
		
		
		try {
			String msg="abcdefg";
			//将字符串转成字节数组
			byte[] buf=msg.getBytes();
			//ByteArrayInputStream bis=new ByteArrayInputStream(buf);
			
			//1:数据 字节数组 2从哪开始【offset偏移量】 3:长度
			ByteArrayInputStream bis=new ByteArrayInputStream(buf,4,2);
			
			//添加标记
			bis.mark(0);
			System.out.println(bis.read());
			//重置
			bis.reset();
			
			//关闭了流 仍然可以进行读取
			bis.close();
			System.out.println(bis.read());
			
			System.out.println("是否支持 mark/reset="+bis.markSupported());
			
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		
	}

}

在这里插入图片描述

SequenceInputStream合并流

SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

package byte_stream;

import java.io.FileInputStream;
import java.io.SequenceInputStream;
import java.util.Vector;

/**
 * 测试合并流
 * @author wenber
 *
 */
public class TestSequenceStream {
	
	public static void main(String[] args) {
		
		testOne();
		testTwo();
		
	}


	/**
	 * 合并多个
	 */
	private static void testTwo() {
		SequenceInputStream sis=null;
		//用来存入所有的流
		Vector<FileInputStream> vector=new Vector<FileInputStream>();
		try {
			vector.add(new FileInputStream("d:/test/a.txt"));
			vector.add(new FileInputStream("d:/test/b.txt"));
			vector.add(new FileInputStream("d:/test/c.txt"));
			//合并多个流【将vector集合中的所有流合并】
			sis=new SequenceInputStream(vector.elements());
			int m;
			while((m=sis.read())>0){
				System.out.println((char)m);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				for (int i = 0; i < vector.size(); i++) {
					if(vector.get(i)!=null)vector.get(i).close();
				}
				if(sis!=null)sis.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	

	/**
	 * 合并两个
	 */
	private static void testOne() {
		FileInputStream fis1=null;
		FileInputStream fis2=null;
		SequenceInputStream sis=null;
		try {
			fis1=new FileInputStream("d:/test/a.txt");
			fis2=new FileInputStream("d:/test/b.txt");
			//合并上面的两个流
			sis=new SequenceInputStream(fis1, fis2);
			
			int m;
			while((m=sis.read())>0){
				System.out.println((char)m);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				if(fis1!=null)fis1.close();
				if(fis2!=null)fis2.close();
				if(sis!=null)sis.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}

}

在这里插入图片描述

package byteio;

import java.io.FileInputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

/**
 * 测试合并流
 * @author wenber
 *
 */
public class TestSequenceInputStream {
	
	public static void main(String[] args) {
		
		try {
			FileInputStream fis1=new FileInputStream("d://io/a.txt");
			FileInputStream fis2=new FileInputStream("d://io/b.txt");
			//创建集合
			Vector<FileInputStream> vector=new Vector<FileInputStream>();
			//将流添加到集合中
			vector.add(fis1);
			vector.add(fis2);
			//将流转为枚举对象
			Enumeration<FileInputStream> enums=vector.elements();
			
			//SequenceInputStream seq=new SequenceInputStream(fis1, fis2);
			//将枚举中的流 合并成一个序列流
			SequenceInputStream seq=new SequenceInputStream(enums);
			int a;
			while((a=seq.read())>0){
				System.out.println((char)a);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	

}

InputStreamReader桥接流

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。
我们看代码

package char_stream;

import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * 字节转字符的桥接流
 * @author wenber
 *
 */
public class TestInputStreamReader {
	
	public static void main(String[] args) {
		
		FileInputStream fis=null;
		InputStreamReader isr=null;
		try {
			fis=new FileInputStream("d:/test/readme.txt");
			//将FileInputStream字节流传入InputStreamReader字符桥接流
			isr=new InputStreamReader(fis,"UTF-8");
			int m;
			while((m=isr.read())>0){
				System.out.println((char)m);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				if(fis!=null)fis.close();
				if(isr!=null)isr.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		
	}

}

这个是字节流中的几种必将常用的流,希望可以帮助大家能更好的理解
其实只要把字节流基本搞懂了,字符流是差不多的。
我们下篇文章来看看字符流是怎么去实现的和IO流的序列化以及反序列化
有哪些地方不是很好的希望大家可以在下面评论提示一下哦

猜你喜欢

转载自blog.csdn.net/qq_43402310/article/details/106339237