文件操作学习(三)文件读写之标准流、打印流及序列化流

标准流和打印流

标准流和打印流虽然在日常生活中比较少见,但是这两个与底层的源码息息相关,所以为了深入聊节I/O操作,需要学习这两个流。

标准流

1、我们与ide交换信息时也需要输入流操作,而我们平时都没有见过直接用流来直接输入,而会用到一个类,这个类是什么?它的底层原理是什么?
__针对问题一:__通常情况下我们使用scanner类与ide实现信息输入,scanner底层实现了对输入流的一种包装盒加强。
标准流包含标准输出流和标准输入流,小猿将这连个流结合使用入一个例子中。

案例一

不利用scanner 实现从键盘上的输入。

public class StandardStream {
    public static void main(String[] args) throws IOException {
        //InputStream in = System.in;
//        int by;
//        while ((by=in.read())!=-1){
//            System.out.println((char)by);
//        }
        //InputStreamReader isr = new InputStreamReader(in);
        //BufferedReader br = new BufferedReader(isr);
        System.out.println("------------------------------------------------");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        System.out.println("请出入字符串:");
        while ((line = br.readLine())!=null){
            System.out.println("你输入的字符串是: "+line);
            if(line.equals("null")){
                break;
            }
        }
        System.out.println("请输入一个整数:");
        int i = Integer.parseInt(br.readLine());
        System.out.println("您输入的整数是:"+i);
        br.close();

        System.out.println("--------------------标准输出流练习--------------------");
        PrintStream ps =System.out;
        ps.print("hello");
        ps.print("world");
        System.out.println("hello");
        System.out.println("world");
        System.out.println("----------------------------");
    }
}

运行结果:
在这里插入图片描述
结论:输出语句的本质是一个标准的输出流。

打印流

1、打印流和字符输出流之间的区别是什么?
__针对问题一:__打印流写文件和字符输出流写文件的有不同操作方法。
字符输出流写文件
在构造函数中可以看到有另外一个参数autoFlush。

while ((line=br.readLine())!=null) {
      bw.write(line);
      bw.newLine();
      bw.flush();
}

打印流写文件

while ((line = br.readLine())!=null){
            pw.println(line);
        }

由上面两种代码对比可知打印流是autoflush的,而字符流则必须自己将flush加上。

案例二

public class PrintDemo {
    public static void main(String[] args) throws IOException {
        printStream();
        printWriter();
        copyFiles();
    }
    public static void  printWriter() throws IOException {
        System.out.println("-----------字符打印流---------------");
//        PrintWriter pw = new PrintWriter("reader&writer\\PrintWriter.txt");
//        pw.write("hello");
//        pw.write("\r\n");
//        pw.flush();
//        //pw.write("world");
//        pw.println("world");
//        pw.flush();
        PrintWriter pw = new PrintWriter(new FileWriter("reader&writer\\PrintWriter.txt"),true);
         pw.println("hello");
//       pw.write("hello");
//       pw.write("\r\n");
//       pw.flush();
         pw.println("world");
         pw.close();
    }
    public static void printStream() throws FileNotFoundException {
        System.out.println("----------字节流打印流------------");
        PrintStream ps = new PrintStream("reader&writer\\PrintStream.txt");
        ps.println(97);
        ps.println(98);
        ps.println(99);
        ps.close();
        System.out.println("--------------------------------");
    }
    public static void  copyFiles() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("reader&writer\\src\\charbuffer\\PrintDemo.java"));
        PrintWriter pw = new PrintWriter(new FileWriter("reader&writer\\copy.java"),true);
        String line;
        while ((line = br.readLine())!=null){
            pw.println(line);
            System.out.println(line);
        }
        br.close();
        pw.close();
    }
}

运行结果达到预期效果
在这里插入图片描述
这两种方法其效果都是一样的,至于效率如何,小猿目前不是太清楚。

序列化流

1、为什么需要序列化流?
2、序列化流中需要注意中出现“java.io.NotSerializeableException”是什么问题引发的?若果要继承接口,为什么该接口没有实现的方法?
3、用对象序列化流序列化了一个对象后,假如修改了对象所属类的文件,读数据会不会出现问题呢?如果出问题了,如何解决呢?
4、若果一个对象中的某一个成员变量不想被序列化,有该如何实现呢?

__针对问题一:__作为对象在网络传输中存在着诸多问题,对象直接在网络中传输或者存储在硬盘中不是很不方便,至于为什么不方便,请参考为什么要序列化所以就引入序列化流。
__针对问题二:__需要实现Serializable接口,Serializable接口是标识性接口,所以不需要实现其他的方法之类的。
__针对问题三:__会出现问题,序列化流在序列化对象之前需要生成一个序列化版本号,方便在反序列化是实现版本匹配,当发对象文件被修改时,则会抛出异常。这是后我们就需要修改默认规则,修改方法是加入如下代码,使得序列化版本一致即可 。

private static final long serialVersionUID =xxxx;

__针对问题四:__如果不想一个成员变量序列化,则需要提价申明加入关键字transient;

案例一

序列化读写person 类,必须实现Serializable接口。

public class Person implements Serializable {

    private static final long serialVersionUID =400;

    private String name;
    private int  age;
   private transient String  phoneNum;

    public Person() {
    }

    public Person(String name, int age, String phoneNum) {
        this.name = name;
        this.age = age;
        this.phoneNum = phoneNum;
    }

    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;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

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

测试类

public class SerilizableStream {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        write();
        read();
    }

    public static void write() throws IOException {
        //序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("reader&writer\\SerializableOutStream.txt"));
        Person p1 = new Person("唐建秀", 31, "13883073323");
        oos.writeObject(p1);
        oos.close();
    }

    public static void read() throws IOException, ClassNotFoundException {
        //反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("reader&writer\\SerializableOutStream.txt"));
        Object o = ois.readObject();
        Person p=(Person)o;
        System.out.println(p);
        ois.close();
    }
}

测试结果
在这里插入图片描述
测试结果符合预期。

猜你喜欢

转载自blog.csdn.net/xueshanfeitian/article/details/108844965