三、字符流
1.Reader和Writer抽象类
字节流提供处理任何类型输入/输出操作的足够功能,但不能直接操作Unicode字符,因而需要字符流(主要用于查看文件内容),字符流层次结构的顶层是Reader和Writer抽象类。
(1)Reader是定义Java流式字符输入模式的抽象类,Reader抽象类中的方法:
① public int read(charBuffer target) throws IOException;
② public int read();
③ public int read(char[] cbuf);
④ public abstract int read(char[] cbuf, int off, int len);
⑤ public abstract void close();
(2)Writer是定义流式字符输出的抽象类,该类的方法都返回void值并在出错条件下抛出IOException异常,Writer抽象类中的方法:
① public void write();
② public void write(char[] cbuf);
③ public abstract void write(char[] cbuf, int off, int len);
④ public void write(String str) throws IOException;
⑤ public void write(String str, int off, int len);
⑥ public Writer append();
⑦ public abstract void flush();
⑧ public abstract void close();
2.FileReader和FileWriter
(1)FileReader类表示可以读取文件内容的Reader类,构造方法:
public FileReader(String filePath);
public FileReader(File fileObj);
(2)FileWriter类可以表示写文件的Writer类,构造方法:
public FileWriter(String filePath);
public FileWriter(String filePath, boolean append);
public FileWriter(File fileObj);
字符输出流有一个默认大小为8K的缓冲区(8192KB)。
public class FileReaderWriterDemo {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("f:\\a.txt");
FileWriter fw = new FileWriter("e:\\c.txt");
char[] buff = new char[100];
// 保存实际读到的字符个数
int len = 0;
while((len = fr.read(buff)) != -1) {
fw.write(buff, 0, len);
// 强制刷新缓冲区
fw.flush();
}
fr.close();
// 关闭此流,但要先刷新它
fw.close();
System.out.println("复制完成");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.BufferedReader和BufferedWriter
(1)BufferedReader通过缓冲输入提高性能,两个构造方法:
① BufferedReader(Reader inputStream);
② BufferedReader(Reader inputStream, int bufSize);
(3)BufferedWriter通过缓冲输出提高性能,两个构造方法:
① BufferedWriter(Writer outputStream);
② BufferedWriter(Writer outputStream, int bufSize);
public class BufferedReaderWriterDemo {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("f:\\a.txt");
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter("e:\\e.txt");
BufferedWriter bw = new BufferedWriter(fw);
// 保存读到的字符串
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
bw.write(line);
// 换行
bw.newLine();
// bw.flush();
}
br.close();
bw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Demo {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("f:\\a.txt");
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while(line != null) {
System.out.println(line);
line = br.readLine();
}
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四、其他流
1.ObjectIutputStream/ObjectOutputStream
(1)ObjectInputStream/ObjectOutputStream分别与FileInpputStream/FileOutputStream一起使用时,可以为应用程序提供对对象的持久存储。我们把对象以某种特定的编码格式写入称之为"序列化"。把写入的编码格式内容还原成对象称之为"反序列化"。被序列化的对象必须实现Serializable接口。
public class ObjectInputOutputDemo {
public static void main(String[] args) {
Student student = new Student("zhangsan", "10");
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("e:\\x.txt"));
// 把对象序列化到指定的文件输出流中
oos.writeObject(student);
// 释放资源
oos.close();
// 反序列化对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("e:\\x.txt"));
Student stu = (Student)ois.readObject();
System.out.println(stu);
ois.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Student implements Serializable {
private static final long serialVersionUID = -2970811277559210577L;
private String name = "";
private String age = "";
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return super.toString();
}
}
2.InputStreamReader和OutputStreamWriter
转换流是指字节流与字符流之间的转换。转换流的出现方便了对文件的读写,它在字符流与字节流之间架起了一座桥梁,使原本毫无关联的两种流操作能够进行转化,提高了程序的灵活性。字节流中的数据都是字符时,转成字符流操作更高效。如果使用非默认编码保存文件或读取文件时,需要用到转换流,因为字节流的重载构造方法中有指定编码格式的参数,而FileReader和FileWriter是默认编码的文本文件.
(1)常见的编码表
① ASCII:美国标准信息交换码,用一个字节的7位可以表示。
② ISO8859-1:拉丁码表,欧洲码,用一个字节的8位表示。
③GB2312:中国的中文编码表
④ GBK:中国的中文编码表升级,融合了更多的中文文字符号。
⑤ Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode.
⑥ UTF-8:最多用三个字节来表示一个字符。
InputStreamReader是字节流通向字符流的桥梁,OutputStreamWriter是字符流通向字节流的桥梁。
public class InputStreamWriterReaderDemo {
// 以指定的编码方式来进行文件读写
public static void main(String[] args) {
try {
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("e:\\test.txt"), "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
bw.write("今天是祖国的生日!");
bw.close();
// 读文件(GB2312)
BufferedReader br = new BufferedReader(new FileReader("e:\\x.txt"));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
// 读文件(GBK)
BufferedReader bReader = new BufferedReader(
new InputStreamReader(
new FileInputStream("e:\\a.txt"), "GBK"));
String lineString = null;
while((lineString = bReader.readLine()) != null) {
System.out.println(lineString);
}
bReader.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.RandomAccessFile随机访问文件流
支持对随机访问文件的读取和写入,随机访问文件的行为类似存储在文件系统中的一个大型byte数组。存在指向该隐含数组的光标或索引,称为文件指针。(也就是说RandomAccessFile这个类内部有一个大型byte数组,数据都存放在byte数组中,可以通过数组的文件指针来获取byte数组里面的值也可以通过文件指针来对byte数组的任一位置来写入相应的数据)。输入操作从文件指针开始读取字节,随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,随着对字节的写入而前移此文件指针。写入隐含数组末尾之后的输出操作导致该数组扩展。该文件指针可以通过getFilePointer方法读取,通过seek方法设置。
public class RandomAccessFileDemo {
public static void main(String[] args) {
People[] persons = {new People("test01", 10),
new People("test02", 20),
new People("test03", 30)};
try {
RandomAccessFile randomAccessFile = new RandomAccessFile("e:\\f.txt", "rw");
// 写入数据到RandomAccessFile这个对象中
for (People person : persons) {
randomAccessFile.writeChars(person.getName());
randomAccessFile.writeInt(person.getAge());
}
randomAccessFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class People {
private String name = "";
private int age;
public People(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}