转换流、缓冲流

转换流,,,,, 缓冲流,,,,,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修饰了,序列化时这个属性就不会序列化了。

同时静态修饰也不会被序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。

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

原文地址:https://www.cnblogs.com/marswenze/p/13426090.html