黑马程序员_I/O流(字节流)

---------- android培训java培训、java学习型技术博客,期待与您交流!----------

        与字符流相类似,字节流也有两个基类:InputStream和OutputStream。在操作非文本文件时,必须得使用字节流来完成。同理,字节流中专门操作文件的子类对象是:FileInputStream和FileOutputStream。FileInputStream对象在读取文件数据上也有两种方法,除了调用读取流自身的read方法外,还有自定义一个字节数组来读取的方法,两种方法依然都以返回值-1来表示已达读取流末尾。值得注意的是,FileInputStream类中的available方法使得在自定义字节数组用来读取时,字节数组的大小刚刚好,即定义了一个刚刚好的缓冲区,不用再循环操作来完成读取。

        同字符流的情况类似,为了提高字节流的操作效率,其同样使用了缓冲区来实现。字节流的两个缓冲区子类对象是BufferedInputStream和BufferedOutputStream。和字符流中提到的一样,理解了字节流的缓冲区技术原理后,我们自己也可以定义一个类来模拟BufferedInputStream。来看一下这个模拟的MyBufferedInputStream类:

import java.io.*;
class MyBufferedInputStream{
	private InputStream in;
	private byte[] buf = new byte[1024*4];
	private int pos = 0,count = 0;
	MyBufferedInputStream(InputStream in){
		this.in = in;
	}
	//一次读一个字节,从缓冲区(字节数组)获取。
	public int myRead() throws IOException {
		//通过in对象读取硬盘上的数据,并存储到buf中。
		if(count==0){
			count = in.read(buf);
			if(count<0)
				return -1;
			pos = 0;
			byte b = buf[pos];
			count--;
			pos++;
			return b&255;
		}
		else if(count>0){
			byte b = buf[pos];
			count--;
			pos++;
			return b&0xff;
		}
		return -1;
	}
	public void myClose() throws IOException {
		in.close();
	}
}

        字节流自定义缓冲区类相对于字符流的,需要注意一个问题。非文本文件的字节流数据中,很可能存在连续“1”的数据段,字节数组在读取字节流数据时如果读入的刚好是八个二进制位的1时,就等于读取到了十进制的-1,程序就会认为已经读取到字节流数据末尾,不再读取数据。再考虑到byte类型虽然取的是八个二进制位,但其返回后接收得类型是定义为int型的myRead,因此我们需要做相应的数据转换来保持数据与原读取数据相同且不出现被识别为-1的情形。转换过程如下:

byte: -1 ---> int:-1
11111111 ---> 11111111 11111111 11111111 11111111
11111111 --->提升了一个int类型还是-1,原因是在8个二进制1前面补的是1导致的。
那么我只要在前面补0,即可保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?
 11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------
 00000000 00000000 00000000 11111111
            这也是为什么上面自定义缓冲区类中byte型对象b在返回时都要“与”上255(0xff是十六进制表示)的原因。

        前面的例子都是文件到文件间的数据传输,假如现在的要求是读取键盘录入,并打印在控制台上,当录入的数据是“over”时,录入停止,这该如何完成。读取键盘录入,默认使用的是System.in和System.out,简单完成如下

import java.io.*;
class ReadIn{
	public static void main(String[] args) throws IOException {
		InputStream in = System.in;
		StringBuilder sb = new StringBuilder();
		while(true){
			int ch = in.read();
			if(ch=='\r')
				continue;
			if(ch=='\n'){
				String s = sb.toString();
				if("over".equals(s))
					break;
				System.out.println(s.toUpperCase());
				sb.delete(0,sb.length());
			}
			else
				sb.append((char)ch);
		}
	}
}
        通过以上的键盘录入一行数据并打印其大写,容易看出其原理就是用System.in读取一行数据然后再用System.out打印到控制台上,读取一行数据的原理很自然能够使我们联想到readLine方法。readLine方法是字符流BufferedReader的方法,而键盘录入的read方法是字节流InputStream的方法,要使用字符流缓冲区的readLine方法就需要先将字节流转换成字符流。因此,就需要用到两个新的子类:InputStreamReader和OutputStreamWriter。它们是连接字节流和字符流的桥梁。使用这两个新的子类后,前面键盘录入的例子就可以简化成:

import java.io.*;
class TransStreamDemo{
	public static void main(String[] args) throws IOException {
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

		String line = null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
	}
}
        现在来总结一下,流操作的基本规律。流操作的难点在于流对象有很多,在具体需求前不知道用哪个来完成。事实上只要做到三个明确,答案也就跃然纸上了。首先,明确源和目的。源考虑输入流,基类有Reader和InputStream;目的考虑输出流,基类有Writer和OutputStream。其次,明确操作的数据是否是纯文本。如果是,选用字符流;如果不是,则选用字节流。最后,明确使用哪个具体的对象。往往通过设备来进行区分,包括源设备和目的设备。

        最后扩展一点,涉及到字符编码转换时,通常需要用到转换流


---------- android培训java培训、java学习型技术博客,期待与您交流!----------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值