Java中IO流除了基本的四大体系的流以外,还提供了丰富的流类供我们使用。有对数组进行操作的流对象,对字符串操作的流对象,对于基本数据类型操作的流对象等等。对于这些流对象,有的用的不多,但是还是得必须掌握的知识点。
转换流
Java的四大流体系可以按照操作对象分为:字节流和字符流。由于我们对字符的操作更加方便,在Java里面提供了将字节流转换成字符流的转换流。但是没有将字符转换成字节的流。
①InputStreamReader
InputStreamReader是字符流与字节流之间的桥梁,使用它可以将字节流包装成字符流进行操作。通过构造方法可以看出,它是一个包装类,接收一个字节输入流。InputStreamReader还可以指定字符集来进行转换。InputStreamReader使用举例:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class TransStreamDemo_1 {
/*
* 要求:
* 将键盘录入的书数据转换成大写输出到控制台
* 当写入“over”的时候,程序关闭
*/
public static void main(String[] args) throws IOException {
InputStream in =System.in;
InputStreamReader is=new InputStreamReader(in);
BufferedReader br=new BufferedReader(is);
String s =null;
while((s=br.readLine())!=null)
{
if("over".equals(s))
{
break;
}
System.out.println(s.toUpperCase());
}
br.close();
}
}
②OutputStreamWriter
outputStreamWriter是字节输出流与字符输出流的桥梁,它也是一个包装流,可以包装一个字节输出流。同时也可以指定字符集。实例代码:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class OutputStreamWriterDemo {
/**
* 使用OutputStreamWritrer向文件写入数据
*/
public static void main(String[] args) {
try
{
OutputStreamWriter writer =new OutputStreamWriter(new FileOutputStream("a.txt"));
writer.write("你好");
writer.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
序列流-----SequenceInputStream
SequenceInputStream可以将多个字节输入流实现逻辑串联。通过构造函数,接收对象为两个输入流或者是一个Enumeration对象。接收Enumeration对象用的比较普遍。对于这些串联近来的流对象,将逐个进行文件读取,直到最后一个流对象读完为止。示例代码如下:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
public class SequenceInputStreamDemo {
/**
* @param args
*/
public static void main(String[] args) {
//创建一个集合,装下所有要进行读取的流对象
ArrayList list =new ArrayList();
try
{
FileInputStream in1= new FileInputStream("a.txt");
FileInputStream in2= new FileInputStream("b.txt");
FileInputStream in3= new FileInputStream("copyText.txt");
list.add(in1);
list.add(in2);
list.add(in3);
}catch(IOException e)
{
e.printStackTrace();
}
//使用Collections类得到list的Enumeration
Enumeration e =Collections.enumeration(list);
SequenceInputStream in =new SequenceInputStream(e);
//使用模板代码
byte[] b=new byte[1024];
int h=0;
try
{
while((h=in.read(b))!=-1)
{
System.out.println(new String(b,0,h));
}
}catch(IOException es)
{
es.printStackTrace();
}
}
}
对象流
为了将对象持久化,JavaIO提供了一种可以读取对象的流。
①ObjectInputStream-----反序列化
当把对象写入文件,使用ObjectInputStream类,读取保存在文件里的对象的时候使用ObjectInputStream。这是两个逆过程。一个是序列化对象,另外一个是反序列化对象。
②OjectInputStream-----序列化
注意:要想使用对象流向文件里写入对象,此对象需要实现Serializable接口。
③Serializable接口
此接口是标记接口,没有额外需要实现的方法。实现此接口的类在序列化的时候的非静态字段和非静态方法进行序列化,static关键字和transient关键字修饰的字段和方不会序列化。当对写入的对象进行反序列化的时候,它们的值不准确。代码示例:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class SerializableDemo {
public static void main(String[] args) {
//构建一个Student对象
Student s =new Student("wangwu",20,90.0);
//写入对象
writeToFile(s);
//改变age属性,用于判断其是否被序列化
Student.age=25;
//读取对象,反序列化
Student s1=readFromFile();
//打印以验证,得到答案:25
System.out.println(s1.getAge());
//验证transient关键字。得到0.0
System.out.println(s1.getGrade());
}
public static void writeToFile(Student s)
{
try
{
ObjectOutputStream out =new ObjectOutputStream(new FileOutputStream("obj.object"));
out.writeObject(s);
out.close();
}catch(Exception e)
{
e.printStackTrace();
}
}
public static Student readFromFile()
{
Student s=null;
try
{
ObjectInputStream in=new ObjectInputStream(new FileInputStream("obj.object"));
s =(Student) in.readObject();
}catch(Exception e)
{
e.printStackTrace();
}
return s;
}
}
import java.io.Serializable;
public class Student implements Serializable{
private String name;
static int age;
transient double grade;
public Student(String name,int age,double grade)
{
this.name=name;
this.age=age;
this.grade=grade;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static int getAge() {
return age;
}
public static void setAge(int age) {
Student.age = age;
}
public double getGrade() {
return grade;
}
public void setGrade(double grade) {
this.grade = grade;
}
}
数组流
①字节数组流
字节数组流主要是对字节数组进行操作,是可以直接操作内存的类。
ByteArrayOutputStream是可以直接写字节数组的类。内部维持了一个数组来保存数据。随着数据的不断写入,数组长度自动增长。
ByteArrayinputStream可以从数组中读取数据。
注意:两个类都无需关闭资源,即使关闭,也可以再使用而不会抛出异常。代码示例:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class ByteArrayDemo {
public static void main(String[] args) {
//向对象里面写入字符串
ByteArrayInputStream in =new ByteArrayInputStream("abcde".getBytes());
//将对象中的字节数组写入到BytearrayOutputStream中
ByteArrayOutputStream out =new ByteArrayOutputStream();
int h=0;
while((h=in.read())!=-1)
{
out.write(h);
}
System.out.println(out.toString());
}
}
②字符数组流
字符数组流和字节数组流用法相同,只是操作的对象不同而已。代码示例:
import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.IOException;
public class CharArrayDemo {
public static void main(String[] args) {
CharArrayReader reader =new CharArrayReader("abcde".toCharArray());
CharArrayWriter writer =new CharArrayWriter();
int b=0;
try {
while((b=reader.read())!=-1)
{
writer.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(writer.toString());
}
}
五,随机读取流
随机读取流可以理解为任意位置读取。一:位置任意,二:可以进行读和取。
RandomAccessFile对象可以操作文件指针,到达任意位置进行读取。再有就是此对象可以写入多种形式的数据。是个很便捷的类。用于断点续传等。代码示例:
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
/**
* @param args
*/
public static void main(String[] args) {
try
{
//将文件封装起来,以或得文的属性
File f =new File("copyText.txt");
RandomAccessFile raf=new RandomAccessFile("copyText.txt","rw");
//将文件指针移动到100字节的位置
raf.seek(100);
int h=0;
byte[] b=new byte[1024];
//将文件中100以后的内容读取出来
while((h=raf.read(b))!=-1)
{
System.out.println(new String(b,0,h));
}
//文件指针移动到文件末尾
raf.seek(f.length());
//以UTF-8字符集写入中文
raf.writeUTF("中国");
}catch(IOException e)
{
e.printStackTrace();
}
}
}