2022-08-09 第五组 张明敏 学习笔记

目录

一、IO流

2.路径分隔符

3.常用方法

二、IO流原理

三、流的分类

1. 按操作数据单位不同分为:字节流,字符流

2. 按数据流的流向不同分为:输入流,输出流

3. 按流的角色的不同分为:节点流,处理流

4. IO 流体系

5. 作用

字节输入流:

字节输出流

文件的复制、字节型

文件的复制、字符型

缓冲流

二、序列化

 序列化与反序列化:操作对象


一、IO流

一、File类的使用

  • File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。

    如果需要访问文件内容本身,则需要使用输入/输出流。

  • 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。

  • File对象可以作为参数传递给流的构造器

1.常用构造器

  • public File(String pathname)

    以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。

    绝对路径:是一个固定的路径,从盘符开始

    相对路径:是相对于某个位置开始

  • public File(String parent,String child)

    以parent为父路径,child为子路径创建File对象。

  • public File(File parent,String child)

    根据一个父File对象和子文件路径创建File对象

举例说明:

@Test
public void test1(){
    //构造器1
    File file1 = new File("hello.txt");//相对于当前module
    File file2 =  new File("E:\\Me\\src\\study1\\he.txt");

    System.out.println(file1);
    System.out.println(file2);

    //构造器2:
    File file3 = new File("D:\\workspace_idea1","JavaSenior");
    System.out.println(file3);

    //构造器3:
    File file4 = new File(file3,"hi.txt");
    System.out.println(file4);
}

 

2.路径分隔符

  • 路径中的每级目录之间用一个路径分隔符隔开。

  • 路径分隔符和系统有关:

     windows和DOS系统默认使用“\”来表示

    UNIX和URL使用“/”来表示

  • Java程序支持跨平台运行,因此路径分隔符要慎用。

  • 为了解决这个隐患,File类提供了一个常量:

    public static final String separator。根据操作系统,动态的提供分隔符。

File file1 = new File("d:\\wushen\\info.txt");
File file2 = new File("d:" + File.separator + "wushen" + File.separator + "info.txt")
File file3 = new File("d:/wushen");

 

3.常用方法

  • File类的获取功能

public String getAbsolutePath():获取绝对路径

public String getPath() :获取路径

public String getName() :获取名称

public String getParent():获取上层文件目录路径。若无,返回null

public long length() :获取文件长度(即:字节数)。不能获取目录的长度。

public long lastModified() :获取最后一次的修改时间,毫秒值

public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组

public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组

  • File类的重命名功能

public boolean renameTo(File dest):把文件重命名为指定的文件路径
  • File类的判断功能

    public boolean isDirectory():判断是否是文件目录
    
    public boolean isFile() :判断是否是文件
    
    public boolean exists() :判断是否存在
    
    public boolean canRead() :判断是否可读
    
    public boolean canWrite() :判断是否可写
    
    public boolean isHidden() :判断是否隐藏
  • File类的创建功能

    public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
    
    public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。
    如果此文件目录的上层目录不存在,也不创建。
    
    public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建
    注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目路径下。

  • File类的删除功能

    public boolean delete():删除文件或者文件夹
    
    删除注意事项:
    Java中的删除不走回收站。
    要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录

二、IO流原理

  • 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。

  • 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

三、流的分类

1. 按操作数据单位不同分为:字节流,字符流

  • 字节流(8 bit):是一个字节一个字节的操作。二进制操作。操作任意类型的文件。
    直接从数据源或目的地读写数据
  • 字符流(16 bit):是一个字符一个字符的操作。一个字符两个字节,主要用来处理文本文件。.txt,.java,.py,.xml,.properties,.html,.css,.js,  不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

 

2. 按数据流的流向不同分为:输入流,输出流

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

一个文件在传输过程中经历了多次拷贝,IO性能本身就很低。
零拷贝、Nio附加题!!!

 

3. 按流的角色的不同分为:节点流,处理流

  • 节点流:直接操作一个特定的IO设备。
  • 处理流:在节点流的基础上,做进一步的处理。

 

4. IO 流体系

字节输入流  
字节输出流  
字符输入流 
字符输出流
抽象基类 
InputStream
InputStream
Reader 
Writer
访问文件
(节点流)
 FileInputStream
FileOutputStream 
FileReader 
 FileWriter
缓冲流
(处理流)
BufferedInputStream
BufferedOutputStream
 BufferedReader
BufferedWriter
操作对象
 ObjectInputStream
  ObjectOutputStream

5. 作用

输入流:就是一点一点的往内存中读数据!

 

字节输入流:

1.创建一个FileInputStream对象
2.定义一个标记,用来控制输入流的读取
3.循环读取,如果读取到了-1,说明读取到了文件的末尾,循环结束
4.关闭资源。*****

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

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

public class Ch02 {

    @Test
    public void test02() {
        
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("e:/aaa.txt");
            int read;
            byte [] buf = new byte[1024];
            while((read = inputStream.read(buf)) != -1) {
                System.out.println(new String(buf));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.closeIO(inputStream,null);
    }

    @Test
    public void test01() {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream("e:/aaa.txt");
            // 开始读的操作,read方法,返回值是int,当返回值为-1时,说明文件读取到了末尾
            // 读取文件是否结束的标记
            int read;
            // 字节流读数据的时候一个字节一个字节去读
            // 循环读取
            while((read = inputStream.read()) != -1) {
                System.out.print(read + " ");
            }
            System.out.println();
            System.out.println("读取完毕,再读一次。。。。");
            // 字节流读数据的时候一个字节一个字节去读
            // 循环读取
            while((read = inputStream.read()) != -1) {
                System.out.print(read + " ");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                // 关闭流
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

字节输出流

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

写的操作,目标文件如果不存在,会自动新建。

public class Ch03 {
    @Test
    public void test03(){
        System.out.println(Objects.nonNull("null"));
    }

    @Test
    public void test02() {
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream("e:/aaa.txt",true);
            // 一个字节一个字节的写
            outputStream.write("\r\n".getBytes());
            outputStream.write("八月正午的阳光都没你耀眼".getBytes());
            System.out.println("数据写出成功...");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.closeIO(null,outputStream);
        }
    }

    @Test
    public void test01() {
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream("e:/aaa.txt", true);
            // 一个字节一个字节的写
            outputStream.write(98);
            System.out.println("数据写出成功...");
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
 }

在jdk1.7之后,很多资源类实现了AutoCloseable接口

包括我们常见的流,FileInputStream,FileOutputStream....
可以在try中定义资源,并会主动释放资源
了解即可!!

public class Ch04 {

    public static void main(String[] args) throws FileNotFoundException {
        try(InputStream inputStream = new FileInputStream("e:/aaa.txt");
            OutputStream outputStream = new FileOutputStream("e:/bbb.txt",true)){

            byte [] buf = new byte[3];

            int len;

            while((len = inputStream.read(buf))!= -1){
                outputStream.write(buf,0,len);
            }
            System.out.println("文件复制完成...");
        }catch (IOException e){
            e.printStackTrace();
        }

    }

}

文件的复制、字节型

两个流:
FileInputStream:把对应文件的内容读取出来
FileOutputStream:把读到的内容写出去
read(byte[])
write(byte[])

public class Exam {

    @Test
    public void test01() throws IOException {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream =null;
        int len;
        int write;
        byte[] buf = new byte[1024];
        try {
            fileInputStream = new FileInputStream("D:\\aaa.txt");
            fileOutputStream =new FileOutputStream("D:\\bbb.txt");
            while ((len=fileInputStream.read(buf))!=-1) {
                fileOutputStream.write(buf);
            }
            System.out.println("文件复制完毕");
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        }
    }

文件的复制、字符型

public class Examm {

    @Test
    public void testReaderFileWriter() {
        Reader reader = null;
        Writer writer = null;
        try {
            //创建File类的对象,指明读入和写出的文件
            reader = new FileReader("D:/aaa.txt");
            writer = new FileWriter("D:/aaa.txt");

            //数据的读入和写出操作
            char[] cbuf = new char[5];
            int len;//记录每次读入到cbuf数组中的字符的个数
            while((len = reader.read(cbuf)) != -1){
                //每次写出len个字符
                writer.write(cbuf,0,len);

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭流资源
            try {
                if(writer != null)
                    writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if(reader != null)
                    reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

缓冲流

字符处理流(用的最多)

只能处理纯文本文件:
.txt,.java,.html,.css.........

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

public class Ch06 {

    @Test
    public void test02() {
        BufferedWriter bufferedWriter = null;
        try {
            bufferedWriter = new BufferedWriter(new FileWriter("e:/xxx.txt"));
            bufferedWriter.write("今天是星期二,天气凉爽!");
            System.out.println("数据写出成功!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.closeIO(null,bufferedWriter);
        }
    }

    @Test
    public void test01() {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader("e:/aaa.txt"));
            String str;
            while((str = bufferedReader.readLine()) != null) {
                System.out.println(str);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            IOUtil.closeIO(bufferedReader,null);
        }
    }

}

二、序列化

 序列化与反序列化:操作对象

  • 序列化:将对象写入到IO流中,将内存模型的对象变成字节数字,可以进行存储和传输。
  • 反序列化:从IO流中恢复对象,将存储在硬盘上或者从网络中接收的数据恢复成对象模型

  1. 使用场景:所有可在网络上传输的对象都必须是可序列化的,否则会报错,所有保存在硬盘上的对象也必须要可序列化。
  2. 序列化版本号:
  •     反序列化必须拥有class文件,但随着项目的升级,class文件也会升级
  •     序列化保证升级前后的兼容性。
  •     java序列化提供了一个版本号
  1. 版本号是可以自由指定,如果不指定,JVM会根据类信息自己计算一个版本号,所以无法匹配,则报错!!!
  2.  不指定版本号,还有一个隐患,不利于JVM的移植,可能class文件没有改,但是不同的jvm计算规则不一样,导致无法反序列化
  3.  如果只修改了方法,反序列化是不受影响,无需修改版本号
  4. 修改了静态变量static,瞬态变量transient,反序列化也不受影响,无需修改版本号

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

public class Ch01 {
    @Test
    public void test02() {
        ObjectInputStream objectInputStream = null;
        // 先锁定一个文件
        try {
            objectInputStream = new ObjectInputStream(new FileInputStream("e:/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("e:/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);
        }

    }

}

我们最终会把所有的.class文件打包,把这个包部署到服务器上。
从始至终,.java仅仅是我们程序员写的,给程序员看的。
.java甚至不会参与到打包中,不会出现在服务器上。

运维人员去服务器部署项目,部署的就是一堆的.class。
我们的.properties属性文件是不参与编译的。

public class Ch02 {
    public static void main(String[] args) throws IOException {

        File file = new File("db.properties");
        Properties properties = new Properties();
        properties.load(new FileInputStream(file));

        System.out.println(properties.getProperty("username"));
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值