Java基础第七天

该文档是:Luo学习Java笔记...

博客连接:https://www.loveuluo.cn

日期:2020-11-3

1. IO流概述

通过IO可以完成硬盘文件的读和写。

image-20201103093231239

image-20201103094136888

image-20201103094257542

image-20201103094731133

image-20201103095831887

需要掌握的流:

image-20201104134426785

2. FileInputStream*

image-20201103133028261

2.1 一次读一个字节方法:(不建议使用)

这里使用的是绝对路径

缺点:一次读取一个字节byte,这样内存和硬盘交互太频繁,基本上时间/资源都耗费在交互上面了。

第一个例子:

public static void main(String[] args) {
    FileInputStream inp = null; //在外边先定义,不然的话是局部变量没法close
    {
        try {                      //这是一个绝对路径
            inp = new FileInputStream("G:\\我是被读取的.txt"); //假设文件里的内容是abc
            int read = inp.read();//这个方法的返回值是读取到的“字节”本身
            int read1 = inp.read();//像指针一样读取,第一次执行读取第一个 (返回)
            int read2 = inp.read();
            int read3 = inp.read();//读到文件的末尾,再读取的话读取不到任何数据返回-1
            System.out.println(read);//97
            System.out.println(read1);//98
            System.out.println(read2);//99
            System.out.println(read3);//-1
        } catch (FileNotFoundException e) { //如果抓取到这个报错,说明是文件没找到
            e.printStackTrace();
        } catch (IOException e) { //read方法也有个报错,处理read报错走这里
            e.printStackTrace();
        } finally {
            if (inp!= null) { //关闭的前提是:流不是空。流是null的时候没必要关闭(避免空指针异常)
                try {
                    inp.close(); //用完得关闭掉
                } catch (IOException e) {
                    e.printStackTrace();}}}}}

用while循环优化上边的例子:

public static void main(String[] args) {
    FileInputStream inp = null; //在外边先定义,不然的话是局部变量没法close
    try {                      //这是一个绝对路径
        inp = new FileInputStream("G:\\我是被读取的.txt");
        int readTxt=0; 
        while ((readTxt=inp.read())!=-1){ //当读取到的范围值不为-1时循环继续
            System.out.println(readTxt);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (inp!=null) {
            try {
                inp.close();
            } catch (IOException e) {
                e.printStackTrace();}}}}

2.2 一次读一个字节数组方法(往byte数组中读):

使用相对路劲

image-20201103142837849

fil = new FileInputStream("基础语法/src/IO流/filetest"); //相对路劲

当文本是abcdef:

image-20201103150230145

image-20201103144023578

2.3 用while循环优化上边的代码(最终版,需要掌握*):

public static void main(String[] args) {
    FileInputStream file=null;
    byte[] bytes=new byte[4]; //定义一个byte数组,每次读取4个
    try {
        file = new FileInputStream("基础语法/src/IO流/filetest");
        int read = 0 ;
        while ((read = file.read(bytes))!=-1){/*读取一个数组, 读取到的内容会被放入数组,
        返回的是读取的数量,如果读的时候没有任何一个值,会返回-1,返回-1时结束循环。*/
            System.out.print(new String(bytes,0,read)); //将数组的内容转换为字符串 起始值0,转换的数量为read也就是读取到的数量
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (file!=null){
            try {
                file.close();
            } catch (IOException e) {
                e.printStackTrace();}}}}

2.4 FileInputStream的其他常用方法

image-20201103155854602

available方法:可以返回剩下还没读的字节数量,这样的话数组里可以直接传available,也就是一次性读完,不过不适合大文件。

image-20201103160408245

skip方法:跳过几个字节不读取,这个方法也可能以后会用!

image-20201103170516503

3. FileOutPutStream*

3.1 写入方法,会覆盖原文件

image-20201103190918537

3.2 写入方法,不会覆盖原文件,会添加到末尾

image-20201103190859630

4. 文件复制

image-20201103191500967

image-20201103191622484

public static void main(String[] args) {
    FileInputStream filein=null;
    FileOutputStream fileout=null;
    try {
        //创建一个输入流对象 (把内容输入进内存)
        filein=new FileInputStream("G:\\网易云下载\\Akon,The Notorious B.I.G.,Tupac - Ghetto Rmx.mp3");
        //创建一个输出流对象 (把内容从内存输出到磁盘)
        fileout=new FileOutputStream("C:\\Users\\Administrator\\Desktop\\123.mp3");
        //核心 一边读一边写(文件太大不可能一次性读写完成)
        byte[] bytes=new byte[1024 * 1024];//创建一个byte数组 代表一次性读写1mb字节
        int readReturn = 0;
        while ( (readReturn = filein.read(bytes))!=-1 ){//不停地读取1mb,返回读取到的字节数量
            fileout.write(bytes,0,readReturn);  } //写到磁盘中,写入数组中0到读到的字节数量
        fileout.flush();  //输出流需要刷新一下
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally { //输入流和输出流最好分开try,不然可能会导致一个出错 两个都停止关闭。
        if (fileout != null) {
            try {
                fileout.close();
            } catch (IOException e) {
                e.printStackTrace();}}
        if (filein != null) {
            try {
                filein.close();
            } catch (IOException e) {
                e.printStackTrace();}}}}

5. FileReader(不常用)

image-20201104105312128

6. FileWriter(不常用)

image-20201104110325568

7. 普通文本拷贝

image-20201104110713814

8. BufferedReader(不常用)

image-20201104111723425

用while循环优化:

public static void main(String[] args) {
    FileReader file = null;
    BufferedReader buff=null;
    try {
        file=new FileReader("基础语法/src/IO流/BufferedReaderTest01.java"); //节点流
        buff=new BufferedReader(file);  //处理流
        String s = null;
        //readLine不会读取到换行符,是println换的行
        while ((s=buff.readLine())!=null){ //当读不到的时候返回null
            System.out.println(s);}
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            buff.close();
        } catch (IOException e) {
            e.printStackTrace();}}}

9. BufferedWriter(不常用)

image-20201104133246653

10. 转换流(不常用)

可以把字节流转换为字符流,因为BufferedReader/BufferedWriter只能传入字符流

image-20201104132934744

11. 数据流(不常用)

DataOutputStream能把数据用加密的形式写到文本中,无法直接打开,得用他的兄弟DataInputStream去读,并且读的时候需要提前知道写入的顺序,

读的顺序需要和写入的顺序一致,才可以正常取出数据。

写:

image-20201104135146121

image-20201104135226155

读:

image-20201104135454869

12. PrintStream*

标准的字节输出流。默认输出到控制台

image-20201104141644746

image-20201104141701584

可以用来记录日志的方法:

image-20201104140644373

image-20201104141615272

image-20201104141622142

13. File类

File类和常用方法:

image-20201104143208500

创建一个文件:

image-20201104143554718

创建一个目录:

image-20201104143544997

创建多重目录:

image-20201104143506926

获取父路径和绝对路径:

image-20201104143842834

获取文件名,判断是否是一个目录,判断是否是一个文件:

image-20201104144051426

获取文件最后一次修改时间:

image-20201104144312910

获取文件大小:

image-20201104144430863

获取当前目录下的所有子文件:

image-20201104145153491

14. 文件夹拷贝

public class 文件夹拷贝 {
public static void main(String[] args) {
    //需要一个从哪拷贝的file
    File Infile = new File("G:\\文件夹拷贝测试");
    //需要一个拷贝到的目标地
    File OutFile = new File("F:\\");
    //需要一个方法用来拷贝文件,需要传入的值是从哪拷贝和拷贝到哪
    文件夹拷贝.kaobei(Infile,OutFile);
}
private static void kaobei(File infile, File outFile) {
    if (infile.isFile()){ //如果infile是一个文件的话 那么进行复制操作
        FileInputStream input = null;
        FileOutputStream out = null;
        try { //进来这个判断的肯定是文件,所以文件的绝对路径例子:G:\文件夹拷贝测试\12前端框架Vue\第二层\测试.txt
            input=new FileInputStream(infile);//infile就是要复制的文件
            //下边要复制到的地址应该是 文件的决对路径去掉前三个字符(G:\)并改成outFile(也就是上边要传入的)的路径
            String infileDir = infile.getAbsolutePath().substring(3);
       //判断是不是是\\结尾的 因为如果F:\\这样会有\\为结尾 如果是 F:\\再加一个目录\\ 那么后边的\\会消失 所以如果不是就给他加上\\ 末尾加上目的地
       String path = (outFile.getAbsolutePath().endsWith("\\") ? outFile.getAbsolutePath():outFile.getAbsolutePath() + "\\")+infileDir;
            out=new FileOutputStream(path); //写入到这个path路径下
            //进行边读边写
            byte[] bytes=new byte[1024 * 1024];//一次复制1mb
            int readCount= 0 ;//读取到的数量
            while ((readCount=input.read(bytes))!=-1){
            out.write(bytes,0,readCount);
            }
            out.flush(); //需要刷新一下
        } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace();
        } finally {
            if (infile == null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } }
            if (outFile == null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } }
        return;
    }
    //返回一个文件数组
    File[] files = infile.listFiles();
    for (File file : files) { //遍历files数组
        if (file.isDirectory()) {//如果是文件夹才会执行创建操作
            //要把每个要复制的文件夹目录新建出来
            //要把要创建的多重目录改成你要传入的多重目录
            String srcDir= file.getAbsolutePath();//获得每一个文件夹的绝对路径
            //将srcDic的前三个字符去掉后赋值给substring
            String substring = srcDir.substring(3);//不算要前三个G:/字符 要改成目的地
            //判断是不是是\\结尾的 因为如果F:\\这样会有\\为结尾 如果是 F:\\再加一个目录\\ 那么后边的\\会消失 所以如果不是就给他加上\\ 末尾加上目的地
            String destDir = (outFile.getAbsolutePath().endsWith("\\") ? outFile.getAbsolutePath() : outFile.getAbsolutePath() + "\\")+substring;
            //创建多重目录 传入要出创建的目录
            File file1=new File(destDir);//将路径转化成file对象
            if (!file1.exists()){ //如果不存在才创建
                file1.mkdirs();//用mkdirs方法创建出多重目录
            }            System.out.println(file);        }
        //这里的file是每一个文件夹或者文件
        //所以再调用kaobei方法进行递归,infile的值就是每一个文件夹
        kaobei(file,outFile);    }}}

15.序列化和反序列化(ObjectOutputStream/ObjectInputStream)

image-20201105143839508

image-20201105151040908

image-20201105151057152

得让这个类实现Serializable接口才能进行序列化,否则会报错(NotSerializableException)。

(Java虚拟机看到继承Serializable接口的类 ,会自动生成一个序列化版本号)

image-20201105151121371

序列化对象:

image-20201105151133205

反序列化:

image-20201105152338076

序列化多个对象:

image-20201105154120069

image-20201105154054918

反序列化集合:

image-20201105154233413

关键字 transient(表示被 transien修饰的不参加序列化):

image-20201105154507386

序列化版本号的作用:

image-20201105164702792

image-20201105164801448

最终结论建议手动写出来序列化版本号,不建议自动生成:

image-20201105164819799

image-20201105165747212

16. IO流和Properties联合使用

小提示:如果经常变化的东西写到java程序里,将来改变的时候,需要重新编译,就得重新部署服务器重启服务器,非常的麻烦,经常变化的

信息可以写到文件中,只要改动配置文件,可以动态的获取这个信息(如果key重复了,value会覆盖。)。

配置文件:

image-20201106091012737

读取配置文件代码操作:

image-20201106090710321

image-20201106090532134

image-20201106090445724

最后修改:2020 年 11 月 28 日 09 : 54 AM
如果觉得我的文章对你有用,请随意赞赏