JavaSE进阶——Day11

1-IO流字符流


  • 读取纯文本文件的内容字符流

  • 文件拷贝用字节流

1.1-组成

字节流+编码表

1.2-分类

FileWriter(字符输出流)

字符输出流写出数据

输出流关联文件,文件不存在,自动创建

package com.lyl.writer;
​
import java.io.FileWriter;
import java.io.IOException;
​
public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
        //创建字符输出流
        FileWriter fw = new FileWriter("day11\\a.txt");
        //1.单个写出
        fw.write(97);
        //2.字符数组写出
        char[] chars = {'b','c','d'};
        fw.write(chars);
        //3.写出数组一部分
        fw.write(chars,1,1);
        //4.写出字符串
        fw.write("测试测试");
        //5.写出字符串一部分
        fw.write("我这句话还没写完呢",0,5);
        //关流
        fw.close();
    }
}

输出结果:

练习:用字符流完成文件拷贝

package com.lyl.test;
​
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
​
public class FileWriterTest1 {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("day11\\a.txt");
             FileWriter fw = new FileWriter("day11\\b.txt");) {
            char[] chars = new char[1024];
            int len;
            while ((len = fr.read(chars)) != -1) {
                fw.write(chars, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
} 

输出结果:

注意:字符流拷贝只能拷贝纯文本文件

建议:如果需求只是拷贝文件,一定要用字节流!!!

以上练习只是熟悉字符流的读写操作,拷贝还得是字节流

  • 字符流写出数据,一定要关流,不然数据写不进去

  • 不关流也可以用flush方法(刷新),flush后可以继续写出数据,最后还得关流

  • flush:将缓冲区(内置的小数组)的数据刷出到文件,刷出后可以继续调用write方法写出数据 

  • close:其主要功能是关闭流释放资源,关闭之前会检查缓冲区是否还有数据,有的话,顺带进行刷出操作

  • flush现在的感触可能不是很深,但在之后的网络编程学习中会很有用

FileReader(字符输入流)

1.3-字符缓冲流

缓冲流不具备读写操作,是用来包装输入输出流的

缓冲输入流:BufferedReader

缓冲输出流:BufferedWriter

特有方法

public String readLine();:一次读取一整行字符串,没有读到数据则返回null的结束标记

public void newLine():写出换行符,这个方法具有跨平台性

package com.lyl.buffered;
​
import java.io.*;
​
public class BufferedStream {
    public static void main(String[] args) throws IOException {
        //创建缓冲流对象
        BufferedReader br = new BufferedReader(new FileReader("day11\\a.txt"));
        BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\b.txt"));
        //line用来接受一整行数据
        String line;
        //将read读到的一整行字符串赋给line
        while ((line = br.readLine()) != null) {
            //写出字符串
            bw.write(line);
            //换行
            bw.newLine();
        }
        //关流
        br.close();
        bw.close();
    }
}

输出结果:

注意:如果要开启追加写入操作,应在new FileWriter("day11\\b.txt")参数中给出,例如:BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\b.txt",true)); 

案例:文本排序

3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
9.今当远离,临表涕零,不知所言。
6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。
package com.lyl.test;
​
import java.io.*;
import java.util.TreeSet;
​
public class BufferedTest {
    public static void main(String[] args) throws IOException {
        //1.创建输入流对象,关联要读取的文件
        BufferedReader br = new BufferedReader(new FileReader("day11\\出师表.txt"));
        //2.创建TreeSet集合,准备存储读取到的每一行字符串(排序)
        TreeSet<String> treeSet = new TreeSet<>();
        //3.循环读取,将读取到的内容存入TreeSet集合
        String line;
        while ((line = br.readLine())!=null){
            treeSet.add(line);
        }
        //4.关闭输入流
        br.close();
        //5,创建输出流对象,关联要写出的文件
        BufferedWriter bw = new BufferedWriter(new FileWriter("day11\\出师表.txt"));
        //6.遍历集合
        for (String s : treeSet) {
            //7.将集合中的数据写出到文件
            bw.write(s);
            bw.newLine();
        }
        //8.关闭输出流
        bw.close();
    }
}

输出结果:

1.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
2.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
3.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
4.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
5.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。
6.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
7.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
8.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
9.今当远离,临表涕零,不知所言。

2-转换流


作用:1.将字节流转换为字符流进行使用(延后理解)

  • 问题:为什么不直接创建字符流使用呢?

  • 回答:今后有些流对象,不是我们自己创建,而是通过方法获取到的,返回的是字节流,而我想要按照字符流思想去使用,就需要用到转换流

作用:2.可以按照指定的编码表,进行读写操作

场景:我要读取一个文件,这个文件的编码表是GBK码表,而平台默认读取方式,是按照UTF-8的形式去读取,为了避免乱码问题,就需要让程序按照GBK码表进行读取

2.1-分类

2.1.1-输入流:按照指定码表读取

InputstreamReader

前面学习的FileReader是它的子类,只能按平台的码表进行读取

package com.lyl.change;
​
import java.io.*;
​
public class ChangeStreamDemo {
    public static void main(String[] args) throws IOException {
        //缓冲流(字符流(转换流(字节流),编码表))
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:\\a.txt"),"GBK"));
        System.out.println(br.readLine());
    }
}

输出结果:

 

构造方法

InputStreamReader(InputStream in) : 创建一个使用默认字符集InputStreamReader

InputStreamReader(InputStream in, String charsetName) : 创建一个使用指定命名字符集InputStreamReader

2.1.2-输出流:按照指定码表写出

OutputstreamWriter

package com.lyl.change;
​
​
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
​
public class ChangeStreamDemo2 {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\a.txt"),"GBK");
        osw.write("你好哈哈哈哈");
        osw.close();
    }
}

输出结果:

 

构造方法

OutputStreamWriter(OutputStream out) : 创建一个使用默认字符编码的OutputStreamWriter

OutputStreamWriter(OutputStream out, String charsetName) :创建一个使用命名字符集的OutputStreamWriter

3-序列化流(对象流)


  1. ObjectOutputstream:写出对象

    • 方法:writeObject

  2. ObjectInputStream:读取对象

    • 方法:readObject

  • 对象如果要被序列化,需要实现接口Serializable

    修改了对象所属的Javabean类 , 会抛出InvalidClassException异常

    解决 : 给对象所属的类加一个 serialVersionUID

    private static final long serialVersionUID = ?L

  • 实现好了接口之后,最好手动加入一个序列化版本号

    private static final long serialVersionUID 1L;

  • 给该成员变量加 transient (瞬态) 关键字修饰,该关键字标记的成员变量不参与序列化过程(被隐藏

  • 建议:写出数据只写一次,读取数据也只读取一次

package com.lyl.object_stream;
​
import com.lyl.domain.Student;
​
import java.io.*;
import java.util.ArrayList;
​
public class Demo1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        writeObject();
        readObject();
    }
​
    private static void readObject() throws IOException, ClassNotFoundException {
        //创建对象输入流
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day11\\stu.txt"));
        //集合收取
        ArrayList<Student> list = (ArrayList<Student>) ois.readObject();
        for (Student stu : list) {
            //打印
            System.out.println(stu);
        }
        //关流
        ois.close();
    }
​
    private static void writeObject() throws IOException {
        //集合存储学生对象
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("张三",23));
        list.add(new Student("李四",24));
        list.add(new Student("王五",25));
        //创建对象输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day11\\stu.txt"));
        //写出对象
        oos.writeObject(list);
        //关流
        oos.close();
    }
}

输出结果:

Student{name = 张三, age = 23}

Student{name = 李四, age = 24}

Student{name = 王五, age = 25}

4-打印流


package com.lyl.test;
​
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.Scanner;
​
public class PrintStreamTest {
    //886停止写入
    public static void main(String[] args) throws FileNotFoundException {
        Scanner sc = new Scanner(System.in);
        PrintStream ps = new PrintStream("day11\\test.txt");
        while (true){
            System.out.println("请输入:");
            String msg = sc.nextLine();
            if ("886".equals(msg)){
                ps.close();
                break;
            }else {
                ps.println(msg);
            }
        }
    }
} 

输出结果:

请输入:

123

请输入:

哈哈哈哈

请输入:

abc

请输入:

886

 

平时控制台打印输出,是调用 print 方法和 println 方法完成的

这两个方法都来自于 java.io.PrintStream 

  • 优势:打印流可以自动刷新,自动换行

5-Properties-重点


介绍:java.util.Properties 继承于 Hashtable,来表示一个持久的属性集。

它使用键值结构存储数据,每个键及其对应值都是一个字符串。

HashMap 和 Hashtable 的区别

1. HashMap允许存储 null 键 null 值,  Hashtable不行

2. HashMap线程不安全,  Hashtable 线程安全

5.1-作为集合的使用(了解)

package com.lyl.prop;
​
import java.util.Enumeration;
import java.util.Properties;
​
public class PropertiesDemo {
    /*
    Properties作为集合的使用
     */
    public static void main(String[] args) {
        //创建Properties对象
        Properties p = new Properties();
        //setProperty方法添加数据
        p.setProperty("username","admin");
        p.setProperty("password","123456");
        //获取集合中所有键(enumeration : 迭代器)
        Enumeration<?> enumeration = p.propertyNames();
        //循环判断是否还有下一个元素
        while (enumeration.hasMoreElements()){
            //获取元素(键)
            Object o = enumeration.nextElement();
            //打印  键+---+值
            System.out.println(o+"---"+p.getProperty(o.toString()));
        }
    }
}

输出结果:

password---123456

username---admin

5.2-和IO相关方法

Properties:用来加载配置文件

配置文件:程序中一些灵活多变的信息,放在了文件中存储

从流中加载数据到集合

package com.lyl.prop;
​
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
​
public class PropertiesDemo2 {
    public static void main(String[] args) throws IOException {
        //1.创建空集合
        Properties p = new Properties();
        //2.创建输入流,关联要读取的文件
        FileInputStream fis = new FileInputStream("day11\\config.properties");
        //3.从流中加载数据(键值对)
        p.load(fis);
        fis.close();
        //4.根据键找值(将配置文件中,键对对应的值取出来进行使用)(这一步操作最为重要,以后常用!)
        String username = p.getProperty("username");
        String password = p.getProperty("password");
​
        System.out.println(username);
        System.out.println(password);
    }
}

 

输出结果:

admin

123456

将集合中的数据保存到流中

void store(OutputStream out,String comments):将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流

package com.lyl.prop;
​
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
​
public class PropertiesDemo3 {
    public static void main(String[] args) throws IOException {
        //创建空集合
        Properties prop = new Properties();
        //将数据塞进集合
        prop.setProperty("username", "root");
        prop.setProperty("password", "123456");
        //创建输出流对象
        FileOutputStream fos = new FileOutputStream("day11\\info.properties");
        //集合调用store方法将数据写入流中
        prop.store(fos, null);
        //关闭流
        fos.close();
    }
}

输出结果:

更改null为其他值后:

//集合调用store方法将数据写入流中
prop.store(fos, "看看是什么");

 

注:并不是乱码,而是按照Unicode码表编码的中文汉字,properties配置文件对中文不支持,今后也不会向里面写中文,所以第二个参数即为注释,可写也可不写,不写就设置为null

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值