IO流三
缓冲流
字节缓冲流和字符缓冲流:可以提高效率。用字节流去读写操作,可以一个字节的去读写,这种效率非常低。用个缓冲字节数组去读写操作,可以很大程度上去提高读写的效率,而且数组的长度越大,效率会越高,一般是1024或者是1024的整数倍;
sun公司也知道缓冲数组可以提高读写效率,所以给我们设计了缓冲流,用来提高读写效率;底层维护了一个长度是8192长度数组。
缓冲流不能真正的去进行读写操作,真正去进行读写的操作的,还是我们的FileReader FileWriter FileInputStream FileOutputStream.
BufferedInputStream
BufferedInputStream bin = new BufferedInputStream(new FileInputStream("1.txt"));
BufferedOutputStream
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("1.txt",true));
BufferedReader
String readLine()
读取一个文本行。
BufferedReader br = new BufferedReader(new FileReader("1.txt"));
br.readLine();
BufferedWriter
void newLine()
写入一个行分隔符
BufferedWriter bw = new BufferedWriter(new FileWriter("1.txt"));
bw.newLine();
转换流
InputStreamReader:字节到字符的桥梁。
OutputStreamWriter:字符到字节的桥梁。
它们有转换作用,而本身又是字符流。所以在构造的时候,需要传入字节流对象进来。
构造函数:
InputStreamReader(InputStream)
通过该构造函数初始化,使用的是本系统默认的编码表GBK。
InputStreamReader(InputStream,String charSet)
通过该构造函数初始化,可以指定编码表。
OutputStreamWriter(OutputStream)
通过该构造函数初始化,使用的是本系统默认的编码表GBK。
OutputStreamWriter(OutputStream,String charSet)
通过该构造函数初始化,可以指定编码表。
注意:
操作文件的字符流对象是转换流的子类。
Reader
|--InputStreamReader
|--FileReader
Writer
|--OutputStreamWriter
|--FileWriter
注意:
在使用FileReader操作文本数据时,该对象使用的是默认的编码表。
如果要使用指定编码表时,必须使用转换流。
InputStreamReader
查看API文档,发现是字节流通向字符流的桥梁。查看构造,可以传递字节流,可以指定编码,该流可以实现什么功能?很显然可以包装我们的字节流,自动的完成节流编码和解码的工作。该流是一个Reader的子类,是字符流的体系。所以将转换流称之为字节流和字符流之间的桥梁。
InputStreamReader 是字节流通向字符流的桥梁
测试InputStreamReader
第一步: 需要专门新建以GBK编码的文本文件。为了便于标识,我们命名为gbk.txt
和以UFT-8编码的文本文件,命名为utf.txt第二步: 分别写入汉字”中国”
-
第三步:编写测试方法,用InputStreamReader 分别使用系统默认编码,GBK,UTF-8编码读取文件.
public class Demo4 { public static void main(String[] args) throws IOException { File file = new File("c:\\a.txt"); File fileGBK = new File("c:\\gbk.txt"); File fileUTF = new File("c:\\utf.txt"); // 默认编码 testReadFile(file); // 传入gbk编码文件,使用gbk解码 testReadFile(fileGBK, "gbk"); // 传入utf-8文件,使用utf-8解码 testReadFile(fileUTF, "utf-8"); } // 该方法中nputStreamReader使用系统默认编码读取文件. private static void testReadFile(File file) throws IOException { FileInputStream fis = new FileInputStream(file); InputStreamReader ins = new InputStreamReader(fis); int len = 0; while ((len = ins.read()) != -1) { System.out.print((char) len); } ins.close(); fis.close(); } // 该方法使用指定编码读取文件 private static void testReadFile(File file, String encod) throws IOException { FileInputStream fis = new FileInputStream(file); InputStreamReader ins = new InputStreamReader(fis, encod); int len = 0; while ((len = ins.read()) != -1) { System.out.print((char) len); } ins.close(); } } 注意:码表不对应 分别测试: 使用系统默认编码读取utf-8编码文件 使用utf-8编码读取gbk编码文件 使用"gbk”编码读取utf-8文件. 发现都会出现乱码的问题. // 使用系统默认编码读取utf-8 testReadFile(fileUTF); // 传入gbk编码文件,使用utf-8解码 testReadFile(fileGBK, "utf-8"); // 传入utf-8文件,使用"gbk解码 testReadFile(fileUTF, "gbk");
类 OutputStreamWriter
OutputStreamWriter
有了InputStreamReader 可以转换InputStream
那么其实还有OutputStreamWriter 可以转换OutputStream
OutputStreamWriter 是字符流通向字节流的桥梁
测试OutputStreamWriter
分别使用OutputStreamWriter使用系统默认编码,GBK,UTF-8相对应的默认编码文件,GBK编码文件,UTF-8编码文件中写出汉字”中国”.
-
在使用上述案例中的readFile方法传入相对应码表读取.
public class TestIo { public class Demo4 { public static void main(String[] args) throws IOException { File file = new File("c:\\a.txt"); File fileGBK = new File("c:\\gbk.txt"); File fileUTF = new File("c:\\utf.txt"); // 写入 // 使用系统默认码表写入 testWriteFile(file); // 使用gbk编码向gbk文件写入信息 testWriteFile(fileGBK, "gbk"); // 使用utf-8向utf-8文件中写入信息 testWriteFile(fileUTF, "utf-8"); // 读取 // 默认编码 testReadFile(file); // 传入gbk编码文件,使用gbk解码 testReadFile(fileGBK, "gbk"); // 传入utf-8文件,使用utf-8解码 testReadFile(fileUTF, "utf-8"); } // 使用系统码表将信息写入到文件中 private static void testWriteFile(File file) throws IOException { FileOutputStream fos = new FileOutputStream(file); OutputStreamWriter ops = new OutputStreamWriter(fos); ops.write("中国"); ops.close(); } // 使用指定码表,将信息写入到文件中 private static void testWriteFile(File file, String encod) throws IOException { FileOutputStream fos = new FileOutputStream(file); OutputStreamWriter ops = new OutputStreamWriter(fos, encod); ops.write("中国"); ops.close(); } // 该方法中nputStreamReader使用系统默认编码读取文件. private static void testReadFile(File file) throws IOException { FileInputStream fis = new FileInputStream(file); InputStreamReader ins = new InputStreamReader(fis); int len = 0; while ((len = ins.read()) != -1) { System.out.print((char) len); } ins.close(); } // 该方法适合用指定编码读取文件 private static void testReadFile(File file, String encod) throws IOException { FileInputStream fis = new FileInputStream(file); InputStreamReader ins = new InputStreamReader(fis, encod); int len = 0; while ((len = ins.read()) != -1) { System.out.print((char) len); } ins.close(); } }
注意: 码表不对应的问题
分别测试:
向GBK文件中写入utf-8编码的信息
向utf文件中写入gbk编码的信息
发现文件都有问题,无法正常的读取了.
对象的序列化
当创建对象时,程序运行时它就会存在,但是程序停止时,对象也就消失了.但是如果希望对象在程序不运行的情况下仍能存在并保存其信息,将会非常有用,对象将被重建并且拥有与程序上次运行时拥有的信息相同。可以使用对象的序列化。
对象的序列化: 将内存中的对象直接写入到文件设备中
对象的反序列化: 将文件设备中持久化的数据转换为内存对象
基本的序列化由两个方法产生:一个方法用于序列化对象并将它们写入一个流,另一个方法用于读取流并反序列化对象。
ObjectOutput
writeObject(Object obj)
将对象写入底层存储或流。
ObjectInput
readObject()
读取并返回对象。
由于上述ObjectOutput和ObjectInput是接口,所以需要使用具体实现类。
ObjectOutputStream
ObjectInputStream
- ObjectOutput
- ObjectOutputStream被写入的对象必须实现一个接口:Serializable
否则会抛出:NotSerializableException
- ObjectOutputStream被写入的对象必须实现一个接口:Serializable
- ObjectInput
- ObjectInputStream 该方法抛出异常:ClassNotFountException
ObjectOutputStream和ObjectInputStream 对象分别需要字节输出流和字节输入流对象来构建对象。也就是这两个流对象需要操作已有对象将对象进行本地持久化存储。
案例:
序列化和反序列化Cat对象。
public class Demo3 {
public static void main(String[] args) throws IOException,
ClassNotFoundException {
Cat cat = new Cat("tom", 3);
FileOutputStream fos = new FileOutputStream(new File("c:\\Cat.txt"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(cat);
System.out.println(cat);
oos.close();
// 反序列化
FileInputStream fis = new FileInputStream(new File("c:\\Cat.txt"));
ObjectInputStream ois = new ObjectInputStream(fis);
Object readObject = ois.readObject();
Cat cat2 = (Cat) readObject;
System.out.println(cat2);
fis.close();
}
class Cat implements Serializable {
public String name;
public int age;
public Cat() {
}
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Cat [name=" + name + ", age=" + age + "]";
}
}
打印流
自定义打印流
public static void main(String[] args) throws FileNotFoundException{
PrintStream ps = new PrintStream(new FileOutputStream("a.txt"));
System.setOut(ps);
for (int i = 1; i <= 100; i++) {
System.out.print(i+"\t");
if(i%10 == 0) {
System.out.println();
}
}
}