转换流、缓冲流
转换流,,,,, 缓冲流,,,,,Properties类,,,,,序列化流与反序列化流
转换流
1. OutputStreamWriter类
它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。
public static void writeCN() throws Exception {
//创建与文件关联的字节输出流对象
FileOutputStream fos = new FileOutputStream("c:\\cn8.txt");
//创建可以把字符转成字节的转换流对象,并指定编码
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
//调用转换流,把文字写出去,其实是写到转换流的缓冲区中
osw.write("你好");//写入缓冲区。
osw.close();
}
2. InputStreamReader类
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的字符编码表读取字节并将其解码为字符。
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//演示字节转字符流的转换流
readCN();
}
public static void readCN() throws IOException{
//创建读取文件的字节流对象
InputStream in = new FileInputStream("c:\\cn8.txt");
//创建转换流对象
//InputStreamReader isr = new InputStreamReader(in);这样创建对象,会用本地默认码表读取,将会发生错误解码的错误
InputStreamReader isr = new InputStreamReader(in,"utf-8");
//使用转换流去读字节流中的字节
int ch = 0;
while((ch = isr.read())!=-1){
System.out.println((char)ch);
}
//关闭流
isr.close();
}
}
缓冲流
1 字节缓冲流
字节缓冲流根据流的方向,共有2个
l 写入数据到流中,字节缓冲输出流 BufferedOutputStream
l 读取流中的数据,字节缓冲输入流 BufferedInputStream
1.1 字节缓冲输出流BufferedOutputStream
1.2 字节缓冲输入流 BufferedInputStream
public static void main(String[] args) throws IOException {
FileInputStream shuru=new FileInputStream("D:\\表约束.wmv");
//创建字节输出缓冲流
BufferedInputStream bis=new BufferedInputStream(shuru);
//创建字节输出流
FileOutputStream shuchu=new FileOutputStream("D:\\io0512\\a\\字符流.wmv");
//创建字节输出
BufferedOutputStream bos=new BufferedOutputStream(shuchu);
//复制
int len=0;
while((len=bis.read())!=-1){
bos.write(len);
}
bis.close();
bos.close();
}
2 字符缓冲流
l 字符缓冲输入流 BufferedReader
l 字符缓冲输出流 BufferedWriter
完成文本数据的高效的写入与读取的操作
字符缓冲输出流 BufferedWriter
l 方法:
void newLine() 根据当前的系统,写入一个换行符
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
//创建流
//基本字符输出流
FileWriter fileOut = new FileWriter("file.txt");
//把基本的流进行包装
BufferedWriter out = new BufferedWriter(fileOut);
//2,写数据
for (int i=0; i<5; i++) {
out.write("hello");
out.newLine();
}
//3,关闭流
out.close();
}
}
字符缓冲输入流 BufferedReader
l 方法
public String readLine() 读取一个文本行,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
//1,创建流
BufferedReader in = new BufferedReader(new FileReader("file.txt"));
//2,读数据
//一次一个字符
//一次一个字符数组
//一次读取文本中一行的字符串内容
String line = null;
while( (line = in.readLine()) != null ){
System.out.println(line);
}
//3,关闭流
in.close();
}
}
文本复制,一个字符数组一个数组读
public class Demo04 {
public static void main(String[] args) throws IOException {
//创建字符输入
FileReader shuru=new FileReader("D:\\io0512\\utf-8.txt");
BufferedReader br=new BufferedReader(shuru);
FileWriter shuchu=new FileWriter("D:\\io0512\\a\\utf-8.txt");
BufferedWriter bw=new BufferedWriter(shuchu);
int len=0;
char[] ch=new char[2];
while((len=br.read(ch))!=-1){
bw.write(ch,0,len);
bw.flush();
}
br.close();
bw.close();
}
}
一个字节一个字节复制
public static void main(String[] args) throws IOException {
FileInputStream shuru=new FileInputStream("D:\\表约束.wmv");
//创建字节输出缓冲流
BufferedInputStream bis=new BufferedInputStream(shuru);
//创建字节输出流
FileOutputStream shuchu=new FileOutputStream("D:\\io0512\\a\\字符流.wmv");
//创建字节输出
BufferedOutputStream bos=new BufferedOutputStream(shuchu);
//复制
int len=0;
while((len=bis.read())!=-1){
bos.write(len);
}
bis.close();
bos.close();
}
}
一行一行的读
public static void main(String[] args) throws IOException {
//chuang减字符输入流
FileReader shuru=new FileReader("D:\\io0512\\utf-8.txt");
BufferedReader br=new BufferedReader(shuru);
FileWriter shuchu=new FileWriter("D:\\io0512\\utf-82.txt");
BufferedWriter bw=new BufferedWriter(shuchu);
//复制
String len=null;
while((len=br.readLine())!=null){//一行一行读
bw.write(len);
bw.newLine();//换行
bw.flush();
}
br.close();
bw.close();
}
流的操作规律
IO流中对象很多,解决问题(处理设备上的数据时)到底该用哪个对象呢?
把IO流进行了规律的总结(四个明确):
l 明确一:要操作的数据是数据源还是数据目的。
源:InputStream Reader
目的:OutputStream Writer
先根据需求明确要读,还是要写。
l 明确二:要操作的数据是字节还是文本呢?
源:
字节:InputStream
文本:Reader
目的:
字节:OutputStream
文本:Writer
已经明确到了具体的体系上。
l 明确三:明确数据所在的具体设备。
源设备:
硬盘:文件 File开头。
内存:数组,字符串。
键盘:System.in;
网络:Socket
目的设备:
硬盘:文件 File开头。
内存:数组,字符串。
屏幕:System.out
网络:Socket
完全可以明确具体要使用哪个流对象。
l 明确四:是否需要额外功能呢?
额外功能:
转换吗?转换流。InputStreamReader OutputStreamWriter
高效吗?缓冲区对象。BufferedXXX
InputStream
FileInputStream
BufferedInputStream
OuputStream
FileOutputStream
BufferedOuputStream
Writer
OutputStreamWriter
FileWriter
BufferedWriter
Reader
InputStreamReader
FileReader
BufferedReader
Properties类
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
特点:
1、Hashtable的子类,map集合中的方法都可以用。
2、该集合没有泛型。键值都是字符串。
3、它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。键值的来源也可以是持久化的设备。
4、有和流技术相结合的方法。
public static void main(String[] args) {
//创建Pro集合
Properties pro=new Properties();
pro.put("a", "18");//存值
pro.put("b", "16");
System.out.println(pro.getProperty("a"));//输出18,取值
System.out.println(pro.getProperty("b"));//输出16
}

public static void main(String[] args) throws IOException {
Properties pro=new Properties();//创建Propertues对象
pro.put("name","Amy");
pro.put("age", "19");
//明确properties的路径
FileOutputStream fos=new FileOutputStream("src/com/oracle/demo02/pro.properties",true);
pro.store(fos, "");//注释,注释不写显示当前时间
}
l load(InputStream) 把指定流所对应的文件中的数据,读取出来,保存到Propertie集合中
l load(Reader)
l store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数commonts代表对描述信息
l stroe(Writer,comments);
load读取

序列化流与反序列化流

创建对象的方式:一种是new,一种是对象序列化
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。
序列化:将一个对象封装到文件中(ObjectOutputStream )
//序列化
public class Demo01 {//将一个对象封存到文件中
public static void main(String[] args) throws IOException {
//明确目的地
FileOutputStream fos=new FileOutputStream("D:\\io0512\\person.txt");
//创建序列化流
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(new Person("张三",20));
oos.close();
}
}
反序列化:将封装好的文件读出来(ObjectInputStream)
用于从流中读取对象的
//反序列化
public class Demo02 {//将封存的对向读回来
public static void main(String[] args) throws ClassNotFoundException, IOException {
//明确数据源
FileInputStream fis=new FileInputStream("D:\\io0512\\person.txt");
//创建反序列化流对象
ObjectInputStream ois=new ObjectInputStream(fis);
//读取对象
Person p=(Person)ois.readObject();
System.out.println(p);//打印存好的信息,Person【name=张三,age=18】
ois.close();
}
}
Person类
public class Person implements Serializable{//序列化接口
public static String name;//静态修饰不属于对象,属于类,不被序列化(序列化是对象)
private transient int age;//不需要被序列化的属性可以加transient,就不被序列化,写的值就不能被读出来
//定死uid的序列化号,保证txt和person里的序列号一致
private static final long serialVersionUID=123L;//序列化号
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person() {
super();
}
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;
}
}
序列化接口
当一个对象要能被序列化,这个对象所属的类必须实现Serializable接口。否则会发生异常NotSerializableException异常。
同时当反序列化对象时,如果对象所属的class文件在序列化之后进行的修改,那么进行反序列化也会发生异常InvalidClassException。发生这个异常的原因如下:
l 该类的序列版本号与从流中读取的类描述符的版本号不匹配
l 该类包含未知数据类型
l 该类没有可访问的无参数构造方法
Serializable标记接口。该接口给需要序列化的类,提供了一个序列版本号。serialVersionUID. 该版本号的目的在于验证序列化的对象和对应类是否版本匹配。

瞬态关键字transient
当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字transient修饰。只要被transient修饰了,序列化时这个属性就不会序列化了。
同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

不被序列化就无法写入数据,读取到的是默认值


浙公网安备 33010602011771号