学习心得

字节流和字符流一定要区分开,BufferedIntputStream和BufferedOutputStream感觉比其他的要好用一点

心情

还是关于IO流,也就是输入输出,感觉这几天现在才算了解一下计算机传输文件时候都做了什么,很神奇。

掌握情况:还行

 

IO流:(输入输出流)

File类不能操作文件

1.按照流向分:

输入流:从硬盘上读取数据到内存(读)

输出流:从内存写出数据到硬盘(写)

一个文件在传输过程中,经历了多次拷贝。IO本身效率低

零拷贝!!。Nio附加题!!

2.按照操作单元分

字节流:是一个字节一个字节的操作,二进制操作,操作任意类型的文件,万能。

字符流:一个字符一个字符的操作,一个字符两个字节,主要用来处理文本文件。

.txt/ .java/.py。。。。。。

3.按照角色划分

节点流:直接操作一个特定的IO设备

处理流:在节点流的基础上,做进一步的处理

 

Java中的输入流、输出流常用的流:

 

 

字节输入流

字节输出流

字符输入流

字符输出流

 抽象基类 

InputStream

OutputStream

Reader

Writer

 访问文件 

(节点流)

FileInputStream

FileOutputStream

FileReader

FileWriter

 缓冲流 

(处理流)

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter

 操作对象 

ObjectInputStream

ObjectOutputStream

   

 

字节输入流:

1.创建一个FileInputStream对象

2.定义一个标记,用来控制输入流的读取

3.循环读取,如果读取到了-1,说明读取到了文件末尾,循环结束

4.关闭资源。

注意:我们发现一个流读完了就没有了,不能再读了

当一个流读完之后就会默认调用mark 和 reset 方法来进行记录和重置。这个流就已经重置到上一次读取完的位置。所以不能再读了。并不是关闭了流。

字节输出流:

FileOutputStream构造器:

boolean append 参数:如果传入true,则表示在原有基础上追加,不覆盖。如果传入false,或者不传,覆盖原有内容。

写的操作:目标文件如果不存在,就会新建

字符处理流:  (用的最多)

缓冲流:只能处理纯文本文件:

.txt,.java,.html,.css.........

利用缓冲字符流来写一个文件的复制

import java.io.*;
import java.util.Objects;


public class Ch04 {
    @Test
    public void test01(){
//        File file = new File("D:\\IDEJR\\TryPlay\\aaa.txt");
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
     
        try {
            fileInputStream = new FileInputStream("D:\\IDEJR\\TryPlay\\aaa.txt");
            fileOutputStream = new FileOutputStream("D:\\IDEJR\\TryPlay\\houhou\\aaa.txt");
            byte [] bytes= new byte[1024];
            int len;
            
            while ((len = fileInputStream.read(bytes)) !=-1){
                fileOutputStream.write(bytes,0,len);
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                if (Objects.isNull(fileInputStream)){
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
      
    }

或者

public class Ch01 {


    public static void main(String[] args) {
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;


        try {
            bufferedReader = new BufferedReader(new FileReader("D:\\IDEJR\\TryPlay\\aaa.txt"));
            bufferedWriter = new BufferedWriter(new FileWriter("D:\\IDEJR\\TryPlay\\bbb.txt"));


            String str;
            while((str = bufferedReader.readLine()) != null){
                bufferedWriter.write(str);
                bufferedWriter.newLine();
            }
            System.out.println("文件复制成功!!!");


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtil.closeIO(bufferedReader,bufferedWriter);
        }
    }

可以看出复制成功!!!

 

 

 

序列化和反序列化,操作对象

序列化:将对象写入IO流中,将内存模型的对象变成字节数字。可以进行存储和传输。

反序列化:从IO流中恢复对象,将存储在硬盘上或者从网络上接收的数据恢复成对象模型。

使用场景:所有可在网络上传输的对象都必须是可序列化的。否则会报错,所有保存在硬盘上的对象也必须是可序列化的。

序列化版本号:

反序列化必须拥有 class 文件,但随着项目的升级,class 文件也会升级,序列化保证升级前后的兼容性。

java 序列化提供了一个版本号

版本号是可以自由指定,如果不指定,JVM会根据类信息自己计算一个版本号,所以无法匹配,则报错!!!

不指定版本号,还有一个隐患,不利于JVM的移值,可能 class 文件没有改,但是不同的JVM计算规则不一样,导致无法反序列化。

如果只修改了方法,反序列化不受影响,无需修改版本号。

修改了静态变量 static瞬态变量 transient ,反序列化也不受影响,无需修改版本号。

public class Ch02 {


    @Test
    public void test02() {
        ObjectInputStream objectInputStream = null;
        // 先锁定一个文件
        try {
            objectInputStream = new ObjectInputStream(new FileInputStream("D:/user.txt"));
            User user = (User) objectInputStream.readObject();
            System.out.println("对象读取成功:" + user);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.closeIO(objectInputStream,null);
        }


    }


    @Test
    public void test01() {
        ObjectOutputStream objectOutputStream = null;
        // 先锁定一个文件
        try {
            objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:/user.txt"));
            User user = new User("张三",25,1);
            objectOutputStream.writeObject(user);
            System.out.println("对象写出成功...");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.closeIO(null,objectOutputStream);
        }

总结:

  • 1.所有需要网络传输的对象都需要实现序列化接口
  • 2.对象的类名,实例变量都会被序列化;方法,类变量,transient变量不会被序列化
  • 3.如果想让某个变量不被序列化,可以用transienrt修饰
  • 4.序列化对象引用类型成员变量,也必须是可序列化的,否则会报错
  • 5.反序列化时必须有系列化对象的 class 文件
  • 6.如果同一个对象被序列化多次,只有第一次序列化为二进制流,以后都只是保存系列化的版本号。
  • 7.建议所有的可序列化的类加上版本号,方便项目升级。

我们最终会把所有的.class文件打包,把这个包部署到服务器上

java是程序员写的,程序员看的

. java不会参与打包,不会出现到服务器上

我们的  . properties 属性文件不会参与编译,一旦数据库升级,改变此文件即可,否则要改变源码,耗费资源。

 

 

posted on 2022-08-09 21:24  骐琳  阅读(33)  评论(0)    收藏  举报

你点我就回上面去了ヾ(≧O≦)〃嗷~