关于IO流的其它操作

转换流:把字节流转换为字符流,将获取到的字节通过查编码表获取到对应字符
InputStreamReader将字节输入流转换成字符输入流
在这里插入图片描述
OutputStreamWriter将字节输出流装换为字符输出流
在这里插入图片描述
推回输入流:读取数据的时候,它都是按顺序读取的,在流的内部会维护一个指针,在读取的同时,指针会向后移动,直到读完为止。但是如果读取出来的数据不是我们想要的,又想把它放回去该如何做呢?这个时候我们就会用到推回输入流了,用推回输入流读取数据可以把数据给推回到输入流的缓冲区中,可以把已经读取的数据推回去。
主要有两个类:PushbackInputStream和PushbbackReader
注意:推回缓冲区的内容大小不能超过缓冲区的大小

	//创建字符输入流
	Reader in=new FileReader("E:/z/Array.java");
     //创建推回输入流 指定推回缓冲区大小为64 若不指定,默认缓冲区大小为64
	PushbackReader reader=new PushbackReader(in,64);//64代表缓冲区大小,64个单位
	//临时存放读取的数据
	char[] char1=new char[32];//区域的大小一般是缓冲区大小的一半 设置要找的字符的长度
	int count=0;//存放读取的字符数(实际读取了多少字符)
	String strOld="";//存放上一次读取的结果
	//读取数据
	while ((count=reader.read(char1,0,char1.length))!=-1) {
	//本次读取的内容
	String str=new String(char1,0,count);//转成String 
    //上一次读取的+本次读取的内容    判断的时候是两次,避免查找的字符被截断,如果要找的字符已经远远大于缓  冲区了,就会有截断的可能
	String strContent=strOld+str;
	//查找目标字符串的索引位置
	int targetIndex=strContent.indexOf("使用,");//查找对应的字符串的索引
	if (targetIndex>-1) {
		//如果找到就推回去,推回到流里面去(将本次内容和上次内容一起推回缓冲区)
		//推回缓冲区的内容大小不能超过缓冲区的大小   缓冲区的大小是动态变化的
		reader.unread(strContent.toCharArray());//没有读取   推回去的是一个数组
		//推回去之后要重新读取
		//如果前面的字符>32(临时数组的大小)
		if (targetIndex>32) {//这个位置的索引就代表着前面的长度(大小)
			//重新new一下char1
			char1=new char[targetIndex];//把数组变量的长度加大
		} 
			//再读取一下 (再次读取指定长度的内容,就是目标字符串之前的内容)
			reader.read(char1,0,char1.length);
			str=new String(char1);//输出来的是整个容器
			System.out.print(str);
			break;//跳出循环				
		} else {
			//为找到目标字符串
			//直接输出
			System.out.print(strOld);//这次没有找到,证明它上次就不存在  这一次+上一次的没有被找到,上一次没有找到,但这次有可能有找到
			//更新一下
			strOld=str;
		}
	}

缓冲流:在读写数据时,让数据在缓冲区能减少系统实际对原始数据来源的存取次数,因为一次能做多个数据单位的操作。相较而言,对于直接从文件读取数据或将数据写入文件,比起缓冲区的读写要慢多了。所以使用缓冲区的流,一般都会比没有缓冲区的流效率更高。拥有缓冲区的流被称为缓冲流,包括BufferedInputStream、BuffetedOutputStream类和BufferedReader、BufferedWriter类。缓冲流把数据从原始流成块的读入或把数据积累到一个大数据块后再成批写出,通过减少资源的读写次数来加快程序的执行。
BufferedInputStream:该类实现缓冲的输入流。
BufferedOutputStream:该类实现缓冲的输出流。
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。
BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字 符串的高效写入。
缓冲区是给IO流提高效率的,也就意味着,缓冲区对象建立时,必须要有流对象。

	//BufferedReader类:Reader的子类
	Reader in=new FileReader("E:/z/Array.java");
	BufferedReader reader=new BufferedReader(in);//用缓冲流来读取  可以自定义大小
	String str="";
	//使用readLine()比较方便地读取一行
	while ((str=reader.readLine())!=null) {//一次性读取到换行符为止,只能读取字符串
		System.out.println(str);
	}
	//关闭流
	reader.close();
	//BufferedWriter类:Writer的子类
	Writer out=new FileWriter("E:/z/z/BufferedWriter.txt");//创建一个文件
	BufferedWriter writer=new BufferedWriter(out);
	for (int i = 0; i < 10; i++) {
		writer.write("Hello EveryOne:"+i);
		//写入一个行分隔符
		writer.newLine();
	}
	//刷新该流的缓冲
	writer.flush();
	//关闭流
	writer.close();

访问数组
ByteArrayInputStream(源):内存
ByteArrayOutputStream(目的)::内存。
这两个流对象不涉及底层资源调用,操作的都是内存中数组,所以不需要关闭资源。直接操作字节数组就可以了,为什么还要把数组封装到流对象中呢?因为数组本身没有方法,只有 一个length属性。为了便于数组的操作,将数组进行封装,对外提供方法操作数组中的元素。
对于数组元素操作无非两种操作:设置(写)和获取(读),而这两个操作正好对应流的读写操作。这两个对象就是使用了流的读写思想来操作数组。

	String str1="ByteArrayInputStream ByteArrayOutputStream;";
	//ByteArrayInputStream:可以将字节数组转化为输入流
	//ByteArrayOutputStream:可以捕获内存缓冲区的数据,转换成字节数组 
	ByteArrayOutputStream out=new ByteArrayOutputStream();//内部相当于定了一个数组容器  可变数组
	//写入数据
	out.write(str1.getBytes());
	//转换为byte数组
	byte[] byte1=out.toByteArray();//toByteArray()一般把很多数据合并到一个数组的时候使用  转成固定大小的值
     //通过数组输入流循环,循环的方式遍历读取出来     一般用在网络传输
	ByteArrayInputStream in=new ByteArrayInputStream(byte1);//把byte数组转化为输入流
	byte[] byte2=new byte[1024];
	int count=0;
	while ((count=in.read(byte2, 0, byte2.length))!=-1) {
		System.out.println(new String(byte2,0,count));
	}
	//ByteArrayInputStream ByteArrayOutputStream不需要关闭流 ,读取的是内存,内存是不需要关闭的

访问字符串
StringReader:用来将字符串转换成字符输入流。然后使用字符输入流提供的方式进行操作,也可以提供给其它高级字符输入流来使用。如可以将该字符输入流提供给BufferedReader输入流使用。
在这里插入图片描述
执行结果:
在这里插入图片描述
StringWriter:在内存中缓存读取到的所有字符串,然后使用通过toString方法一次性全部输出字符串
在这里插入图片描述
管道流(了解):管道流是用来在多个线程之间进行信息传递的Java流,被号称是难使用的流,被使用的频率比较低,管道输入流和管道输出流可以像管道一样对接上,管道输入流就可以读取管道输出流写入的数据。
注意:需要加入多线程技术,因为单线程,先执行read,会发生死锁, 因为read方法是阻塞式的,没有数据的read方法会让线程等待
管道流包括四个类:PipedOutputStream/PipedWriter和PipedInputStream/PipedReader
其中PipedOutputStream/PipedWriter是写入者/生产者、发送者
PipedOutputStream/ PipedReader是读取者/消费者/接收者
在使用管道流之前,需要注意以下要点:

  • 管道流仅用于多个线程之间传递信息,若用在同一个线程中可能会造成死锁
  • 管道流的输入输出是成对的,一个输出流只能对应一个输入流,使用构造函数或者connect函数进行连接
  • 一对管道流包含一个缓冲区,其默认值为1024个字节,若要改变缓冲区大小,可以使用带有参数的构造器
  • 管道的读写操作是互相阻塞的,当缓冲区为空时,读操作阻塞;当缓冲区满时,写操作阻塞
  • 管道依附于线程,所以若线程结束,则虽然管道流对象还在,仍然会报错“read dead end”
  • 管道流的读取方法与普通流不同,只有输出流正确close时,输出流才能读到-1

RandomAccessFile类: 是Java输入/输出流体系中功能丰富的文件内容访问类
特点:
1、该对象既可读取,又可写入。
2、该对象中定义了一个大型的 byte 数组,通过定义指针来操作这个数组。
3、可以通过该对象的 getFilePointer() 获取指针的位置,通过 seek() 方法设置指针的位置。
4、该对象操作的源和目的必须是文件。
5、该对象内部封装了字节输入流和字节输出流
RandomAccessFile四种访问模式

  • “r”:以只读方式打开指定文件。如果试图对该RandomAccessFile执行写入方法, 都将抛出IOException异常。

  • “rw”:以读、写方式打开指定文件。如果该文件尚不存在,则尝试创建该文件

  • “rws”:以读、写方式打开指定文件。相对于"rw"模式,还要求对文件的内容或元 数据的每个更新都同步写入到底层存储设备。

  • “rwd”:以读、写方式打开指定文件。相对于"rw"模式,还要求对文件的内容的每 个更新都同步写入到底层存储设备

对象序列化:指将一个Java对象写入IO流中,持久存放在磁盘上,是以二进制流的形式存放的,也就是序列化之后是乱码的;
如果需要让某个对象支持序列化机制,则必须让它的类是可序列化的,若让某个类是可序列化的,该类必须实现Serializable(常用)或Externalizable接口。
在这里插入图片描述
在这里插入图片描述
执行结果:
在这里插入图片描述
反序列化:通过反序列化可以把序列化的二进制流中的数据恢复成Java对象。
在这里插入图片描述
执行结果:
在这里插入图片描述
Properties类:java中操作配置文件的类
它是以键值对的形式存在的,键和值都是字符串类型,通过load()方法将流中的数据加载到集合中
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值