Java 位流处理1

位流

 

    计算机中的数据都是以0与1的方式来存储,如果要在两个装置之间进行数据的存取,当然也是以0与1位的方式来进行,Java将数据于目的地及来源之间的流动抽象化为一个流(Stream),而流当中流动的则是位数据

 

InputStream和OutputStream

 

     计算机中实际上数据的流动是通过电路,而上面流动的则是电流,电流的电位有低位与高位,即数字的0与1位。从程序的观点来说,通常会将数据目的地(例如内存)与来源(例如文件)之间的数据流动抽象化为一个流(Stream),而其中流动的则是位数据

 

     InputStream 是所有表示位输入流的类之父类,它是一个抽象类,继承它的子类要重新定义其中所定义的抽象方法。InputStream是从装置来源地读取数据的抽象表 示,例如System中的标准输入流in对象就是一个InputStream类型的实例。在Java程序开始之后,in流对象就会开启,目的是从标准输入 装置中读取数据,这个装置通常是键盘或是用户定义的输入装置

 

     OutputStream 是所有表示位输出流的类之父类,它是一个抽象类。子类要重新定义其中所定义的抽象方法,OutputStream是用于将数据写入目的地的抽象表示。例如 System中的标准输出流对象out其类型是java.io.PrintStream,这个类是OutputStream的子类 (java.io.FilterOutputStream继承OutputStream, PrintStream再继承FilterOutputStream)。在程序开始之后,out流对象就会开启,可以通过out来将数据写至目的地装置, 这个装置通常是屏幕显示或用户定义的输出装置

 

   

import java.io.IOException;

public class Systemin {

	public static void main(String args[]) {
		try {
			System.out.println("输入字符:");
			System.out.println("输入字符十进制表示:" + System.in.read());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

执行结果

输入字符: A

输入字符十进制表示: 65

 

字符A输入后由标准输入流in读取,A的位表示以十进制来看就是65,这是A字符的编码(查查ASCII编码表就知道了)。

 

一般来说,很少直接实现InputStream或OutputStream上的方法,因为这些方法比较低级,通常会实现它们的子类。这些子类上所定义的方法在进行输入/输出时更为方便

 

FileInputStream和FileOutputStream

 

     java.io.FileInputStream 是InputStream的子类。从开头File名称上就可以知道,FileInputStream与从指定的文件中读取数据至目的地有关。而 java.io.FileOutputStream是OutputStream的子类,顾名思义,FileOutputStream主要与从来源地写入数 据至指定的文件中有关

 

    当建立一个FileInputStream或FileOutputStream的实例时,必须指定文件位置及文件名称,实例被建立时文件的流就会开启;而不使用流时,必须关闭文件流,以释放与流相依的系统资源,完成文件读/写的动作

   

    FileInputStream可以使用 read()方法一次读入一个字节,并以int类型返回,或者是使用read()方法时读入至一个byte数组,byte数组的元素有多少个,就读入多少 个字节。在将整个文件读取完成或写入完毕的过程中,这么一个byte数组通常被当作缓冲区,因为这么一个byte数组通常扮演承接数据的中间角色

 

    FileInputStream与FileOutputStream的一个例子。程序可以复制文件,它会先从来源文件读取数据至一个byte数组中,然后再将byte数组的数据写入目的文件

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileStreamDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			byte[] buffer = new byte[1024];
			// 源文件
			FileInputStream fileInputStream = new FileInputStream(new File(
					args[0]));
			FileOutputStream fileOutputStream = new FileOutputStream(new File(
					args[1]));

			// avilable()可取得未读取数据的长度
			System.out.println("复制文件:" + fileInputStream.available() + "字节");

			while (true) {
				if (fileInputStream.available() < 1024) {
					// 剩于的数据比1024少
					// 一位一位读出再写入目的文件
					int remain = -1;
					while ((remain = fileInputStream.read()) != -1) {
						fileOutputStream.write(remain);
					}
					break;
				} else {
					// 从来源文件读取数据至缓冲区
					fileInputStream.read(buffer);
					// 将数组数据写入目的文件
					fileOutputStream.write(buffer);
				}
			}
			// 关闭流
			fileInputStream.close();
			fileOutputStream.close();
			System.out.println("复制完成");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

 

       程序中 示范了两个read()方法,一个方法可以读入指定长度的数据至数组,另一个方法一次可以读入一个字节。每次读取之后,读取的光标都会往前进,如果读不到 数据则返回–1,使用available()方法获得还有多少字节可以读取。除了使用File来建立FileInputStream、 FileOutputStream的实例之外,也可以直接使用字符串指定路径来建立

 

// 来源文件
FileInputStream fileInputStream =
                 new FileInputStream(args[0]);
// 目的文件
FileOutputStream fileOutputStream =
                 new FileOutputStream(args[1]);

 

     在不使用文件流时,记得使用close()方法自行关闭流,以释放与流相依的系统资源。一个执行的结果范例如下,它将FileDemo.java复制为FileDemo.txt:

 

 

BufferedInputStream和BufferedOutputStream

 

     java.io.BufferedInputStream 与java.io.BufferedOutputStream可以为InputStream、OutputStream类的对象增加缓冲区功能。构建 BufferedInputStream实例时,需要给定一个InputStream类型的实例,实现BufferedInputStream时,实际上 最后是实现InputStream实例。同样地,在构建BufferedOutputStream时,也需要给定一个OutputStream实例,实现 BufferedOutputStream时,实际上最后是实现OutputStream实例

 

     BufferedInputStream的数据 成员buf是一个位数组,默认为2048字节。当读取数据来源时,例如文件,BufferedInputStream会尽量将buf填满。当使用read ()方法时,实际上是先读取buf中的数据,而不是直接对数据来源作读取。当buf中的数据不足时,BufferedInputStream才会再实现给 定的InputStream对象的read()方法,从指定的装置中提取数据

 

     BufferedOutputStream的数 据成员buf是一个位数组,默认为512字节。当使用write()方法写入数据时,实际上会先将数据写至buf中,当buf已满时才会实现给定的 OutputStream对象的write()方法,将buf数据写至目的地,而不是每次都对目的地作写入的动作

 

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		try {
			byte[] data = new byte[1];
			File srcFile = new File(args[0]);
			File desFile = new File(args[1]);

			BufferedInputStream bufferedInputStream = new BufferedInputStream(
					new FileInputStream(srcFile));
			BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
					new FileOutputStream(desFile));
			System.out.println("复制文件:" + srcFile.length() + "字节");

			while (bufferedInputStream.read(data) != -1) {
				bufferedOutputStream.write(data);
			}

			bufferedOutputStream.flush();
			// 关闭流
			bufferedInputStream.close();
			bufferedOutputStream.close();
			System.out.println("复制完成");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

 

为了确保缓冲区中的数据一定被写出至目的地,建议最后执行flush()将缓冲区中的数据全部写出目的流中

 

      BufferedInputStream和 BufferedOutputStream并没有改变InputStream或 OutputStream的行为,读入或写出时的动作还是InputStream和OutputStream负责。 BufferedInputStream和BufferedOutputStream只是在操作对应的方法之前,动态地为它们加上一些额外功能(像缓冲区 功能),在这里是以文件存取流为例,实际上可以在其他流对象上也使用BufferedInputStream和BufferedOutputStream 功能

 

 DataInputStream和DataOutputStream

 

    java.io.DataInputStream 和java.io.DataOutputStream可提供一些对Java基本数据类型写入的方法,像读写int、double和boolean等的方 法。由于Java的数据类型大小是规定好的,在写入或读出这些基本数据类型时,就不用担心不同平台间数据大小不同的问题

 

这里还 是以文件存取来进行说明。有时只是要存储一个对象的成员数据,而不是整个对象的信息,成员数据的类型假设都是Java的基本数据类型,这样的需求不必要使 用到与Object输入、输出相关的流对象,可以使用DataInputStream、DataOutputStream来写入或读出数据

 

下面使用范例来介绍如何使用DataInputStream与DataOutputStream。先设计一个Member类。

 

public class Member {

	private String name;

	private int age;

	public Member() {

	}

	public Member(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

 

打算将Member类实例的成员数据写入文件中,并打算在读入文件数据后,将这些数据还原为Member对象。范例14.8简单示范了如何实现这个需求。

 

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataStreamDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Member[] members = { new Member("Justin", 90), new Member("Memor", 95),
				new Member("Bush", 88) };
		try {
			DataOutputStream dataOutputStream = new DataOutputStream(
					new FileOutputStream(args[0]));
			for (Member member : members) {
				// 写入UTF字符串
				dataOutputStream.writeUTF(member.getName());
				// 写入int数据
				dataOutputStream.writeInt(member.getAge());
			}
			// 读出所有数据至目地
			dataOutputStream.flush();
			// 关闭流
			dataOutputStream.close();

			DataInputStream dataInputStream = new DataInputStream(
					new FileInputStream(args[0]));
			//读出数据并还源为对象
			for(int i=0;i<members.length;i++)
			{
				//读出UTF字符串
				String name = dataInputStream.readUTF();
				//读出int数据
				int score = dataInputStream.readInt();
				members[i] = new Member(name,score);
			}
			//关闭流
			dataInputStream.close();
			//显示还源后的数据
			for(Member member:members)
			{
				System.out.printf("%s\t%d%n", member.getName(),member.getAge());
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

  

       在从文件中读出数据时,不用费心地自行判断读入 字符串时或读入int类型时何时该停止,使用对应的readUTF()或readInt()方法就可以正确地读入完整类型数据。同样地, DataInputStream、DataOutputStream并没有改变InputStream或OutputStream的行为,读入或写出时的 动作还是InputStream、OutputStream负责。DataInputStream、DataOutputStream只是在实现对应的方 法时,动态地为它们加上类型判断功能,在这里虽然是以文件存取流为例,实际上可以在其他流对象上也使用DataInputStream、 DataOutputStream功能

 

源文件地址:http://hi.baidu.com/mdbing/blog/item/53c0b301913628031d9583fa.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值