【java基础】15-IO流(3)

  • Post author:
  • Post category:java




1.转换流-概念


字符流中和编码解码问题相关的两个类

  • InputStreamReader: 是从字节流到字符流的桥梁,父类是Reader

    它读取字节,并使用指定的编码将其解码为字符

    它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集

  • OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer

​ 是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节

​ 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集


转换流读写数据

  • 构造方法
方法名 说明
InputStreamReader(InputStream in) 使用默认字符编码创建InputStreamReader对象
InputStreamReader(InputStream in,String chatset) 使用指定的字符编码创建InputStreamReader对象
OutputStreamWriter(OutputStream out) 使用默认字符编码创建OutputStreamWriter对象
OutputStreamWriter(OutputStream out,String charset) 使用指定的字符编码创建OutputStreamWriter对象


要点

转换流 : 
	字节流--------->字符流, 桥梁
		InputStreamReader(InputStream in);
	字符流---------->字节流  桥梁  
		OutputStreamWriter(OutputStream out)
===========================================================
读取
​		读取字符,一般使用 FileReader,BufferedReader
    
    	 InputStream  byte
​        读取 char,来源的字节输入流 InputStream 已确定!  new InputStreamReader(InputStream)
        
        
======================================
写入
​		写入字符,字符串,一般使用 FileWriterBufferedWriter
    		
    	OutputStream, byte,byte[]   
​		写入 char,String, 目标地的字节输出流 OutputStream 已确定!  new OutputStreamWriter(OutputStream)

转换流



2.转换流-指定编码读写

public class ConvertedDemo1 {
    public static void main(String[] args) throws IOException {
        //method1();
        //method2();

        //在JDK11之后,字符流新推出了一个构造,也可以指定编码表
        FileReader fr = new FileReader("C:\\Users\\apple\\Desktop\\a.txt", Charset.forName("gbk"));
        int ch;
        while ((ch = fr.read())!=-1){
            System.out.println((char) ch);
        }
        fr.close();
    }

    private static void method2() throws IOException {
        //如何解决乱码现象
        //文件是什么码表,那么咱们就必须使用什么码表去读取.
        //我们就要指定使用GBK码表去读取文件.
        InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\apple\\Desktop\\a.txt"),"gbk");
        int ch;
        while((ch = isr.read())!=-1){
            System.out.println((char) ch);
        }
        isr.close();

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("C:\\Users\\apple\\Desktop\\b.txt"),"UTF-8");
        osw.write("我爱学习,谁也别打扰我");
        osw.close();
    }


}


要点

1. FileReader,FileWriter可以指定编码读写(注意编译器版本,jdk11)    
    		FileReader fr = new FileReader("a.txt",Charset.forName("gbk"));           
        	FileWriter fw = new FileWriter("b.txt",Charset.forName("utf-8"));

2. OutputStreamWriter  InputStreamReader 转换流,字节流---通往--字符流的桥梁
   如果已经存在 InputStream,想读取字符,可以使用 InputStreamReader(InputStream)
   如果已经存在 OutputStream,想写入字符,字符串,可以使用 OutputStreamWriter(OutputStream)   
   
   //代码示例:  
    //关联到键盘输入的字节输入流
     InputStream in = System.in;
//        int c = in.read(); //只能读字节
//        System.out.println((char) c);

        InputStreamReader isr = new InputStreamReader(in);
        int c = isr.read(); //可以读取字符
        System.out.println((char) c);

需求:使用BufferedReader,读取键盘录入,一次读取一行,并打印
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s ;
while ((s = br.readLine()) != null {    

    if ("end".equals(s)) {
        break;
    }
    System.out.println(s);
}
-----------------------------------------------------------------------------
         //字节输出流已存在
        FileOutputStream fos = new FileOutputStream("c:\\1.txt");
        //我想写入字符,字符串,可以使用转换流
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        osw.write("hello中国");
        osw.close();



3.对象操作流-基本特点

可以把对象以字节的形式写到本地文件,直接打开文件,显示的是乱码,需要再次用对象操作流读到内存中。


要点

序列化:将对象转成字节序列, 可以保存到磁盘,也可以发送到网络
反序列化:读取字节序列,返回一个对象(字节序列可以来自文件,也可以来自网络)



4.对象操作流-序列化

  • 对象序列化介绍

    • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
    • 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
    • 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
    • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
  • 对象序列化流: ObjectOutputStream

    • 将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
  • 构造方法
方法名 说明
ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream
  • 序列化对象的方法
方法名 说明
void writeObject(Object obj) 将指定的对象写入ObjectOutputStream
  • 示例代码

    学生类
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试类

public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myOtherStream\\oos.txt"));

        //创建对象
        Student s = new Student("bibabo",30);

        //void writeObject(Object obj):将指定的对象写入ObjectOutputStream
        oos.writeObject(s);

        //释放资源
        oos.close();
    }
}

注意事项

  • 一个对象要想被序列化,该对象所属的类必须必须实现Serializable 接口
  • Serializable是一个标记接口,实现该接口,不需要重写任何方法

要点

掌握概念
对象序列化:
		将对象转成字节序列 (保存在磁盘中,或通过网络传输)
         ObjectOutputStream(OutputStream)
对象反序列化:
		读取字节序列,返回一个对象(字节序列可以来自于文件,也可以来自于网络)
序列化的步骤
    1.创建 ObjectOutputStream(OutputStream)
    2.创建对象(学生对象)
    3.writeObject(stu);
    4.关闭流	
注意:
	1.被序列化的对象所在的类必须实现 Serializable



5.对象操作流-反序列化

  • 对象反序列化流: ObjectInputStream

    • ObjectInputStream反序列化先前使用

      ObjectOutputStream编写的原始数据和对象
  • 构造方法
方法名 说明
ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream
  • 反序列化对象的方法
方法名 说明
Object readObject() 从ObjectInputStream读取一个对象
  • 示例代码
public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myOtherStream\\oos.txt"));

        //Object readObject():从ObjectInputStream读取一个对象
        Object obj = ois.readObject();

        Student s = (Student) obj;
        System.out.println(s.getName() + "," + s.getAge());

        ois.close();
    }
}



6.对象操作流-两个注意点

对象操作流-问题解决



7.序列化小结:


//序列化流(将对象---二进制)
ObjectOutputStream(OutputStream)
void writeObject(Object)

//反序列化流(读取二进制---->返回对象)
ObjectInputStream(InputStream)
Object readObject()

注意:
1.要序列化的类必须实现Serializable接口
2.private static final long serialVersionUID = 13212312L;
3.private transient int chinese; //瞬时状态,不会保存到文件,比较安全


问题:如何序列化多个对象,并反序列化?
1. 死循环,try catch(EOFException ex) {barak;}
2. 添加元素到集合,序列化集合(推荐)



8.Properties-概述

Properties概述



9.Properties-作为Map集合的基本使用

  • Properties介绍

    • 是一个Map体系的集合类
    • Properties可以保存到流中或者从流中加载
    • 属性列表中的每个键及其对应的值都是一个字符串
  • Properties基本使用
public class PropertiesDemo01 {
    public static void main(String[] args) {
        //创建集合对象
//        Properties<String,String> prop = new Properties<String,String>(); //错误
        Properties prop = new Properties();

        //存储元素
        prop.put("001", "bibabo");
        prop.put("002", "bibowen");
        prop.put("003", "simade");

        //遍历集合
        Set<Object> keySet = prop.keySet();
        for (Object key : keySet) {
            Object value = prop.get(key);
            System.out.println(key + "," + value);
        }
    }
}



10.Properties-特有方法

  • 特有方法
方法名 说明
Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
  • 代码示例
public class PropertiesDemo02 {
    public static void main(String[] args) {
        //创建集合对象
        Properties prop = new Properties();

        //Object setProperty(String key, String value):设置集合的键和值,都是String类型
        prop.setProperty("001", "bibabo");
        prop.setProperty("002", "bibowen");
        prop.setProperty("003", "simade");

        //String getProperty(String key):使用此属性列表中指定的键搜索属性
//        System.out.println(prop.getProperty("001"));
//        System.out.println(prop.getProperty("0011"));

//        System.out.println(prop);

        //Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
        Set<String> names = prop.stringPropertyNames();
        for (String key : names) {
//            System.out.println(key);
            String value = prop.getProperty(key);
            System.out.println(key + "," + value);
        }
    }
}



11.Properties-load

  • 和IO流结合的方法
方法名 说明
void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流
  • 代码示例
public class PropertiesDemo03 {
    public static void main(String[] args) throws IOException {
        //把集合中的数据保存到文件
//        myStore();

        //把文件中的数据加载到集合
        myLoad();

    }

    private static void myLoad() throws IOException {
        Properties prop = new Properties();

        //void load(Reader reader):
        FileReader fr = new FileReader("myOtherStream\\fw.txt");
        prop.load(fr);
        fr.close();

        System.out.println(prop);
    }

    
}



12.Properties-store

Properties-store

代码示例

private static void myStore() throws IOException {
        Properties prop = new Properties();

        prop.setProperty("001", "bibabo");
        prop.setProperty("002", "bibowen");
        prop.setProperty("003", "simade");
        
        //void store(Writer writer, String comments);
        FileWriter fw = new FileWriter("myOtherStream\\fw.txt");
        prop.store(fw,null);
        fw.close();
    }


要点

void  store(Writer/OutputStream,"注释说明"):  保存内容到文件


注:load方法使用更多。 一般很少写入文件,都是读取properties文件。



13.IO流小结

1.体系
2.构造
3.步骤(1.创建流, 2.操作流, 3.关闭流)
    
字节流
    InputStream(抽象)
    	FileInputStream(String/File)
    	BufferedInputStream(InputStream): 缓冲流= 基础流+缓冲区
    
    int read()
    int read(byte[])
    
    OutputStream(抽象)
    	FileOutputStream(String/File)
    	BufferedOutputStream(OutputStream)缓冲流= 基础流+缓冲区
    
    write(int)
    write(byte[])
    write(byte[],index,len)
 =======================================================================================   
    
字符流=字节流+编码表
    Reader(抽象)
    	FileReader(String/File,CharSet.forName("gbk"))
    	BufferedReader(Reader)
    			String readLine():一次读取一行,读取不到返回null
    	InputStreamReader(InputStream):转换流,把字节流转成字符流
    
    int read() 读一个字符
    int read(char[])读一个字符数组
    
    Writer(抽象)
    	FileWriter(String/File,CharSet.forName("gbk"))
    	BufferedWriter(Writer)
    			void newLine(); 写入换行符
    	OutputStreamWriter(OutputStream):转换流,把字符流转成字节流
    
    write(int)
    write(char[])
    write(String)
    
   3种复制(1.字节流复制,一次一个字节, 2.字节流复制,一次一个字节数组 3. 高效字符流复制文本文件,一次一行)



14.序列化流

序列化: 将对象转成字节序列,保存到磁盘或发送到网络
反序列化: 读取字节序列,返回一个对象
    
序列化流
	ObjectOutputStream(OutputStream)
    	writeObject(Object)
反序列化流
    ObjectInputStream(InputStream)
    	Object readObject()
注意事项:
	1.要被序列化的对象所在类必须实现 Serializable接口(标记型接口)
    2. 防止反序列化时,修改类导致的异常,可以添加序列化版本号
        	private static final long serialVersionUID = 42L;
    3.不想被序列化的字段可以使用transient关键字



15.Properties小结

作用: 最常用来读取key=value格式的properties配置文件
构造:
	Properties()
添加
	setProperty(String,String)
获取
	String getProperty(Stirng key)
遍历
	Set<String> stringPropertyNames()
保存集合到文件
	store(OutputSteam/Writer, ”说明信息”);
从文件中加载内容到集合
	load(InputStream/Reader);

有了HashMap,Properties集合的意义?
Properties主要是用来读取/写入properties配置文件的.
Properties还可直接从流中加载, HashMap不行.



版权声明:本文为Nusret原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。