JAVA IO流

目录

IO流

1.IO流是什么

2.IO流的分类:

3.java IO流这块有四大家族:

4.十六个流

5.InputStream和OutputStream

5.1InputStream

5.2FileOutStream

5.3.文件的复制

6.FileReader和FileReader

6.1FileReader

6.2FileWrite

6.3文件拷贝

7.缓冲流

8.转换流

8.1套娃

9.数据流

10.标准输出流

10.1PrintStream

10.2日志

11.File类

11.1常用方法

11.2拷贝目录

12.对象流

12.1序列化和反序列化

12.2注意

12.3序列化

12.4序列化多个对象

12.5transient

12.6序列化版本号

13.IO+Properties联合使用


IO流

  • 补充:‘a’英文字母,在windows操作系统中是一个字节,但是‘a’字符在java中占用两个字节

  • java中所有的流都在java.io.*下。 char在java下是占两字符的

1.IO流是什么

  • I:Input:输入

  • O:Output:输出

2.IO流的分类:

一种是按照流的方向进行分类:

往内存中去叫做输入(Input)。或者叫做读(Read)。

从内存中出来叫做输出(Output)。或者叫做写(Write)。

另一种方式是按照读取数据方式不同进行分类:

  • 有的流是按照字节的方式读取数据,一次读取一个字节byte,等同于一次读取8个二进制,这种流是万能的,什么类型的文件都可以读取。八廓文本文件,图片,声音文件。

  • 有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文件而存在的,这种流不能读取:图片、声音、时评等文件。只能读取纯文本文件(后缀 .txt),连word文件都无法读取

例:
    a中国boy张三
按照字节:
    第一次读'a'(在Windows系统中占一个字节)
    第二次读'中'的一半('中'字符在windows系统中占用2个字节)
    第三次读'中'的另外一半
    第四次读'国'的一半
    第五次读'国'的另外一半
     .
     .
     .
按照字符:(缺点只能读普通的文本文档)
     第一次读'a'字符('a'字符在windows系统中占用1个字节)
     第二次读'中'字符('中'字符在windows系统中占用2个字节)
     第三次读'国'字符
     第四次读'b' 字符
     .
     .
     .
txt只是操作系统中的一个普通的文件

3.java IO流这块有四大家族:

四大家族的首领:

java.io.InputStream 字节输入流

java.io.OutputStream 字节输出流

java.io.Reader 字符输入流

java.io.Writer 字符输出流

注意:在java中只要"类名"以Sream结尾的都是字节流。以”Reader/Writer结尾的都是字符流“

  • 四大家族的首领都是抽象类。(abstract class)

  • 所有的流都实现了:java.io.Closeable接口,都是可关闭的,都有close()方法。

  • 使用完流之后一定要关闭否则会占用资源

所有的输出流OutputStream都实现了:java.io.Flushable接口,都是可刷新的,都有flush()方法。用完输出流的时候,输出流在最终输出之后一定要Flush(刷新一下。这个刷新表示将管道/通道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用是清空管道。

注意:如果不刷新Flush(),可能导致会数据丢失。

4.十六个流

 

5.InputStream和OutputStream

5.1InputStream

文件字节输入流,万能的,任何类型的文件都可以采用这个流来读

字节的方式,完成输入的操作完成读的操作

用byte数组

5.1.1read读取字节

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/18:20
 * @Description:文件字节输入流,万能的,任何类型的文件都可以采用这个流来读
 * 字节的方式,完成输入的操作,完成读的操作
 */
public class inputStream {
    public static void main(String[] args) {
        //创建文件字节输入流对象
        //文件路径:D:\javaTest\temp.txt
        //以下路径都是采用绝对路径
​
        FileInputStream fileInputStream = null;
        try {
            fileInputStream= new FileInputStream("D:\\javaTest\\temp.txt"); //或者:D:/javaTest/temp.txt
            //开始读
            int readDate1 =fileInputStream.read();//97
            System.out.println(readDate1);
            //调用一下read指针就会移动一个位置
            int readDate2 =fileInputStream.read();//98
            System.out.println(readDate2);
            int readDate3 =fileInputStream.read();//99
            System.out.println(readDate3);
            int readDate4 =fileInputStream.read();//100
            System.out.println(readDate4);
            int readDate5 =fileInputStream.read();//101
            System.out.println(readDate5);
            int readDate6 =fileInputStream.read();//102
            System.out.println(readDate6);
            int readDate7 =fileInputStream.read();//-1
            System.out.println(readDate7);//没有元素是就返回-1
​
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //在finally语句块当中确保流一定关闭。
            if(fileInputStream!=null){//避免空指针异常
                //关闭的前提是:流不是空,流是null的时候没必要关闭
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
​
    }
}
​

相对路径

IDEA默认路径是当前工程(project)的根,工程下有很多模块

"chapter23/src/tempfile2"
"tempfile"

绝对路径

D:\\javaTest\\temp.txt

5.1.1改进

package com;
/**
 * 一次读取单个字节
 */
​
import java.io.*;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/17/21:03
 * @Description:
 *
 * once read one byte
 * 缺点:一次读取一个字节,内存和硬盘交互太平凡,基本上时间资源都耗费在交互上面了
 */
public class javase {
    public static void main(String[] args) {
​
        FileInputStream iis =null;
        try {
            iis = new FileInputStream("D:/Test01/text.txt");
       /*    int number= 0;
            while(number!=-1){
                 number = iis.read();
                System.out.println(number);//这里的结果会输出-1
            }*/
            //改进:
            int number =0;
            while((number = iis.read())!=-1){
                System.out.println(number);//不会输出-1
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (iis != null) {
                try {
                    iis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
​
        }
    }
}
​

5.1.2一次读取多个字节

字节(Stream)最终遍历方式

采用byte数组,一次读取多个字节,最多读取"数组.length"个字节。

5.1.2.1错误案例

不应该全部转成字符串,应该是读了多少个就转多少。

全部都转换可能有重复的部分

fis.read(bytes):这个方法返回的值是:读取到的字节数量。(不是字节本身)

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/19:50
 * @Description:
 */
public class InputStreamTest {
    public static void main(String[] args) {
        FileInputStream fis  = null;
        try {
​
            fis = new FileInputStream("SwingTest/src/com/IO/pages.txt");
            byte []bytes = new byte[4];//每次只能读四个长度
​
            //这个方法返回的值是:读取到的字节数量。(不是字节本身)
            int resnum=fis.read(bytes);
            
            System.out.println(resnum);//4
            System.out.println(new String(bytes));//abcd
            /**
             * new String(bytes);将byte数组转成字符串
             */
            
            //但是这里不应该全部转成字符串,应该是读了多少,就转多少。
            
            int resnum1=fis.read(bytes);
            System.out.println(resnum1);//2
            System.out.println(new String(bytes));//efcd 
            //cd还在,只是把ab换掉了(具体看内存图)
​
            int resnum2=fis.read(bytes);
            System.out.println(resnum2);//1个都没读到返回-1
            System.out.println(new String(bytes));
​
       
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

5.1.2.2解决方法

将byte转成String使用 new String(byte)

new String(byte,0,num)

默认从0开始,到num结束

num用read(byte)获得

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/19:50
 * @Description:
 */
public class InputStreamTest {
    public static void main(String[] args) {
        FileInputStream fis  = null;
        try {
​
            fis = new FileInputStream("SwingTest/src/com/IO/pages.txt");
            byte []bytes = new byte[4];//每次只能读四个长度
​
            //这个方法返回的值是:读取到的字节数量。(不是字节本身)
            int resnum=fis.read(bytes);
            /**
             * 读了多少,就转多少。
             * read()会返回一次读取到的字节数量,不包含最后可能重复的部分
             */
            System.out.println(resnum);//4
            System.out.println(new String(bytes,0,resnum));
            //resnum=4
​
            int resnum1=fis.read(bytes);
            System.out.println(resnum1);//2
            System.out.println(new String(bytes,0,resnum1));
            //restum1 = 2
​
            int resnum2=fis.read(bytes);
            System.out.println(resnum2);//1个都没读到返回-1
            //System.out.println(new String(bytes,0,resnum2));
            //restum2 = 0
​
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

5.1.2.3遍历方式

改进while循环

fis.read(byte)方法读到的是字节数量不是字节本身

package com;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/17/22:03
 * @Description:
 */
public class test02 {
    public static void main(String[] args) {
        
        FileInputStream inputStream =null;
        try {
            inputStream=new FileInputStream("tempfile");
            byte []Byte =new byte[4];//一次最多读取四个字节
            
        while(true) {
            //这个方法的返回值是:读取到的字节数量(不是字节本身)
            int readcount = inputStream.read(Byte);
            if (readcount == -1){
                break;
            }
                //把byte数组转化成字符串
            System.out.println(new String(Byte, 0, readcount));//读多少个就是多少个,没读到就返回-1
​
       
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream==null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
                   }
    }
}

5.1.2.4最终遍历方式

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/20:25
 * @Description:
 */
public class InputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("SwingTest/src/com/IO/pages.txt");
            byte []bytes = new byte[50];//创建byte数组
​
             int num=0;
            //没有读完不会返回-1,读完了返回-1,-1赋给m,m==-1就结束循环
             while((num=fis.read(bytes))!=-1){
                System.out.println(new String(bytes,0,num));
            }
​
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

5.1.2.5FileInputStream其他常用方法

//fileInputStraem.availble(); //fileInputStream.skip();

FileInputStream类的其他常用方法:
    int available():返回流当中剩余额度没有读到的字节数量
    long skip(long n):跳过几个字节不读

1.获取字节数量fis.available()

这种方式可以不用循环直接读一次就够了(之前循环读是因为byte数组限定了长度,不能确定一次读多少合适)

但是这种方式不太适合太大的文件,因为byte[]数组不能装太大。

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/22:51
 * @Description:
 */
public class InputTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
​
        try {
            //创建FileInputStream对象
            fis= new FileInputStream("SwingTest/src/com/IO/pages.txt");
            System.out.println("总字节数量"+fis.available());//6
            //读一个
            int res =fis.read();
            System.out.println("剩下"+fis.available()+"个字节没有读");//5
            //创建byte数组,fis.available()可以获得剩下的总字节数
            byte []bytes = new byte[fis.available()];
            fis.read(bytes);
            System.out.println(new String(bytes));//bcdef
            
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//关闭文件
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

文件内容:

2.跳过字符串

fis.skip(n) n为跳过元素的个数

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/15/22:51
 * @Description:
 */
public class InputTest {
    public static void main(String[] args) {
        FileInputStream fis = null;
​
        try {
            fis= new FileInputStream("SwingTest/src/com/IO/pages.txt");
            //跳过三个
            fis.skip(3);
            //得到的是d的字节码
            System.out.println(fis.read());//100
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

5.2FileOutStream

文件字节输出流,负责写

从内存到硬盘

  • 写完之后一定要flush()刷新

  • 该种方式会把文件清空掉再写入,谨慎使用

package com.IO;
​
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/0:10
 * @Description:
 */
public class OutPutStreamTest {
    public static void main(String[] args) {
        FileOutputStream fos =null;
        try {
            fos = new FileOutputStream("pages");//没有文件会创建文件
            byte [] bytes ={ 97,98,99,100,101,102}; //这里是字节码写到文件内的是字符。
            //将byte数组全部写出
            fos.write(bytes);
​
            //写完之后一定要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

写完之后一定要刷新。

byte数组里是数字(Ascall码),写到文件里面就是字符。

输出结果:

  • 追加的方式

ios =new FileOutputStream("myfile",true);
//加上true之后会追加在原文件的末尾
package com.IO;
​
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/0:10
 * @Description:
 */
public class OutPutStreamTest {
    public static void main(String[] args) {
        FileOutputStream fos =null;
        try {
            fos = new FileOutputStream("pages",true);
            byte [] bytes ={ 97,98,99,100,101,102}; //这里是字节码写到文件内的是字符。
            //将byte数组全部写出
            fos.write(bytes);
            fos.write(bytes,0,2);//再写byte数组0开始往后2个数(ab)
​
            String chinese = "我是中国人";
            byte []b =chinese.getBytes();//将字符串转成byte类型
            fos.write(b);
​
            //写完之后一定要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

6.2输出结果

5.3.文件的复制

package com.IO;
​
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/10:02
 * @Description:文件的拷贝(使用FileInputStream,FileOutStream完成文件拷贝。)
 * 拷贝的过程应该是一边读一边写
 * 使用以上的字节流拷贝文件的时候,文件类型随意,万能的
 */
public class IOtest {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos =null;
        try {
            //创建输入输出流对象
            fis = new FileInputStream("pages");
            fos = new FileOutputStream("page_copy");
            byte []bytes = new byte[ fis.available()];
            int num =0;
            //fis.read()将pages文件内容读到bytes数组中
            while((num=fis.read(bytes))!=-1){
                System.out.println(new String(bytes,0,num));
               //将bytes数组中的内容写到page_copy文件内
                fos.write(bytes,0,num);//读多少写多少 
            };
​
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //注意这里要分开处理异常,因为一起处理,前一个发生异常后面那个就关不了了。
            //一起try的时候,其中一个出现异常可能会影响到另一个流的关闭
            if ( fis!= null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
​
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

图列演示

6.FileReader和FileReader

用char数组

文件字符输入流,只能读取普通文本文件

读取文件内容时,比较方便,快捷。

框架都是一样的

6.1FileReader

//FileREAD和FileWrite
package com;
​
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/18/16:09
 * @Description:文件字符输入流
 */
public class test07 {
    public static void main(String[] args) {
        FileReader read =null;
        try {
            //创建文件字符输入流
           read =new FileReader("tempfile");
         
          /*测试:
          //创建char字符
          char[] ch =new char[4];//一次读取四个字符
          read.read(ch);
          for(char num:ch){
              System.out.println(num);
          }*/
            
            int Count =0;
            while((Count =read.read(ch))!= -1){
                System.out.println(new String(ch,0,Count));
            }
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(read != null){
                try {
                    read.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

6.2FileWrite

可以直接写入String字符串,也可以写入char数组

会把文件内容清空再写入

不想清空 new Filewriter("file",true),与OutputStream用法相同

package com;
​
import java.io.FileWriter;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/18/16:26
 * @Description:
 */
public class test08 {
    public static void main(String[] args) {
        FileWriter fileWriter = null;
        try {
            //可以直接写入字符数组和字符串数组
             fileWriter =new FileWriter( "file");
            //写入
            fileWriter.write("我是中国人");
             fileWriter.write("\n");//输入换行
             char []ins = {'我','是','美','人'};
             fileWriter.write(ins,0,2);
​
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
             if(fileWriter !=null){
                 try {
                     fileWriter.close();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
        }
    }
}
​

6.3文件拷贝

用FileReader和FileWriter实现

读多少写多少

package com.IO;
​
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/10:47
 * @Description:使用FileReader和FileWriter拷贝
 */
public class ReaderCopy {
    public static void main(String[] args) {
        FileReader fileReader =null;
        FileWriter fileWriter =null;
​
        try {
            //读
            fileReader = new FileReader("page_copy");
            //写
            fileWriter = new FileWriter("page_copy_plus");
            int num =0;
            char[]chars = new char[1024*1024];//1M
            //一边读一边写
            while((num=fileReader.read(chars))!= -1){//向char数组里面读
                fileWriter.write(chars,0,num);//读多少写多少
            };
​
            fileWriter.flush();
​
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fileReader!=null){
                try {
                    fileReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
​
            if(fileWriter!=null){
                try {
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
​

7.缓冲流

使用这个流的时候不需要自定义char和byte数组,自带缓冲

对于包装流来说,只需要关闭最外层的流就行,里面的节点流回自动关闭。(查源代码)

特色:readLine():已读读一行,读取一个文本行但是不带换行符。

//包装流(处理流)和节点流         BufferedReader
 //关闭只用关闭最外层
package com;
​
import java.io.*;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/19/10:46
 * @Description:
 */
public class test10 {
    public static void main(String[] args) throws Exception {
 
        FileReader reader = new FileReader("javaSE//src//com//javase.java");
​
        //当一个构造方法需要传入流时,这和被传入的流叫做节点流
        BufferedReader bufferedReader = new BufferedReader(reader);//FileReader是Reader的子类,传入子类也认可
        //外部负责包装的叫做包装流(处理流)
        String s = null;
        while((s=bufferedReader.readLine())!=null){
            System.out.println(s);
        }
    }
}
​

8.转换流

将字节流转成字符流

  • InputStreamReader:将InputStream转换成Reader

  • OutputStreamWriter:将OutputStream转换成Writer

8.1套娃

//InputStreamReader
package com;
​
import java.io.*;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/9:09
 * @Description:
 */
public class test11 {
    public static void main(String[] args) throws Exception {
        //创建字节流
        FileInputStream filer= new FileInputStream("javaSE//src//com//javase.java");
        //字节流转换为字符流
        InputStreamReader isr =new InputStreamReader(filer);
        //创建BufferedReader对象,这个构造方法只能传一个字符流,不能传字节流
        BufferedReader bufferedReader =new BufferedReader(isr);
        String  str =null;
        //多合一
        BufferedReader reader =new BufferedReader(new InputStreamReader(new FileInputStream("\"javaSE//src//com//javase.java\"")));
        while((str = bufferedReader.readLine())!=null)
        {
            System.out.println(str);
        }
        //关闭只用关闭最外层
        bufferedReader.close();
    }
}
​

这种方式节点流和包装流是相对的

//OutputStreamWriter
​
package com;
​
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/9:30
 * @Description:合并的写法
 */
public class test12 {
    public static void main(String[] args) throws Exception {
​
    BufferedWriter writer =new BufferedWriter(new OutputStreamWriter(new FileOutputStream("copy",true)));
   //开始写
    writer.write("HelloWorld");
    writer.write("\n");
    writer.write("HelloKity");
    //刷新
    writer.flush();
    //关闭
    writer.close();
    }
}
​

9.数据流

java.io.DataOutputStream:数据专属的流
    这个流可以将数据连同数据的类型一并写入文件
    注意:这个文件不是普通文本文档(这个文件使用记事本打不开)

类似于加密方式

package com;
//DataInputStream:数据字节输入流
//DataoutStream写的文件只能使用DatainputStream去读,并且读的时候必须知道写入是的顺序
//读的顺序要和写的顺序相同,才可以正常取出数据
import java.io.DataOutputStream;
import java.io.FileOutputStream;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/10:00
 * @Description:
 */
public class test13 {
    public static void main(String[] args) throws Exception {
        DataOutputStream das =new DataOutputStream(new FileOutputStream("Data"));
        byte b =127;
        short s =456;
        int i =12;
        long l =7894;
         double d =456.123;
         float f =1.23f;
         boolean bo = true ;
         char c ='a';
        //写入
        das.writeByte(b);//把数据及数据类型一并放入文件当中
        das.writeShort(s);
        das.writeInt(i);
        das.writeLong(l);
        das.writeDouble(d);
        das.writeFloat(f);
        das.writeBoolean(bo);
        das.writeChar(c);
        
        //刷新
         das.flush();
        //关闭
        das.close();
    }
}
​
package com;
​
import java.io.*;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/10:00
 * @Description:
 */
public class test14 {
    public static void main(String[] args) throws IOException {
        //读出
        DataInputStream dataINputStream = new DataInputStream(new FileInputStream("Data"));
        Byte b1=dataINputStream.readByte();
        Short s1= dataINputStream.readShort();
        int i1=dataINputStream.readInt();
        Long l1=dataINputStream.readLong();
        Double d1=dataINputStream.readDouble();
        float f1=dataINputStream.readFloat();
        boolean b2=dataINputStream.readBoolean();
        char c1=dataINputStream.readChar();
        System.out.println(b1);
        System.out.println(s1);
        System.out.println(i1);
        System.out.println(l1);
        System.out.println(d1);
        System.out.println(f1);
        System.out.println(b2);
        System.out.println(c1);
​
    }
}
​

10.标准输出流

10.1PrintStream

PrintStream(new FileOutputStream);

System.setOut(PrintStream)更改输出方向

package com.IO;
​
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/12:16
 * @Description:标准输出流默认输入到控制台
 */
public class printTest {
    public static void main(String[] args) throws FileNotFoundException {
​
        //联合起来写
        PrintStream ps = System.out;
​
        //分开写
        ps.println(2);
        ps.println("sfdaas");
        ps.println('s');
​
        //标准流不需要手动close()
        //标准输出流不在指向控制台,指向"log"文件
        PrintStream printStream = new PrintStream(new FileOutputStream("log"));
        //修改输出方向,将输出方向修改到"log"文件
        System.setOut(printStream);
​
        System.out.println("HelloWord");
        System.out.println("HellotheWord");
​
​
    }
}
​

10.2日志

//更改输出的路径
PrintStream
    
日志实现:
    
package com;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/10:33
 * @Description:
 */
public class logger {
    public static void log(String msg) {
        try {
            //标准输出流指向日志文件
            PrintStream ps = new PrintStream(new FileOutputStream("copy",true));//追加
            //改变输出方向
            System.setOut(ps);
            //日期当前时间格式化
            Date date =new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
            String time =simpleDateFormat.format(date);
​
            System.out.println(time+":"+msg);
​
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
​
​
package com;
import java.util.logging.Logger;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/12:35
 * @Description:
 */
public class test {
    public static void main(String[] args) {
        logger.log("helloworld");
        logger.log("hellokitty");
        logger.log("nihaoshijie");
    }
}
​

11.File类

java.long.Object ----->java.io.File

  • File类不是个流不能完成文件的读和写

  • 只是一个文件路径名的抽象表现形式。

一个file对象有可能对应的是目录,也有可能是文件。

11.1常用方法

f.exist(): 判断是否存在

f.createNewFile(): 创建新文件

f.mkdir(): 创建新目录

f.getParent(): 获取父路径 返回值String类型

f.getParentFile(): 与getParent只是返回值类型不一样,也是返回的父路径 返回值File类型

f.getAbsolutePath():获取绝对路径

f.getname():获取文件名

f.isDirectory():判断是否是一个目录

f.isFile():判断是否是一个文件

f.lastModified获取文件最后一次修改时间 返回值类型long(毫秒)

f.length():获取文件的大小

f.listFiles():获取当前目录下所有子目录 返回值类型是File[]数组

package com;
​
import javax.xml.crypto.Data;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/20/13:05
 * @Description:
 */
public class test15 {
    public static void main(String[] args) throws IOException {
        File f =new File("D:\\Test01");
        System.out.println(f.exists());//判断是否存在文件
​
        //如果不存在以文件形式创建
//        if(!f.exists()){
//            f.createNewFile();
//        }
         //如果不存在以目录的形式创建
//        if(!f.exists()){
//            f.mkdir();
//        }
        //创建多层路径
        File f2 =new File("D:\\a\\b\\c\\d\\e");
        if(!f2.exists()){
            //以多重目录的形式创建
            f.mkdirs();
        }
        
        File f1 =new File("D:\\a\\b");
        if(f1.exists()){
          String parentspath =f.getParent();
          File file =f.getParentFile();
           file.getAbsolutePath();//获取绝对路径
        }
        File f3 = new File("");
        f3.getName();//获取文件名
        /*
        判断是文件还是目录
        */
        System.out.println("是否是文件:"+f3.isDirectory());
        System.out.println("是否是目录:"+f3.isFile());
​
        long haomiao =f3.lastModified();//返回的是毫秒
        //创建日期对象,传入毫秒
        Date times = new Date(haomiao);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        sdf.format(times);
        System.out.println("获取最后一次文件修改时间"+  sdf.format(times));
​
        //获取文件大小
        f3.length();
​
        //获取当前目录下的所有子文件
        File f4  =new File("javaSE");
        File [] file = f4.listFiles();
        for (File files:file) {
            System.out.println(files.getAbsolutePath());
        }
    }
}

11.2拷贝目录

12.对象流

12.1序列化和反序列化

把java对象放在文件上称为序列化

序列化就是排好队,一块一块的给它放到文件当中

反序列化就是把硬盘文件中一块一块的东西拿到内存当中,按顺序组装成一个对象

序列化多个对象

调用 oos.writeObject()方法就是序列化

  • 实现serializable接口(标志性接口)

12.2注意

参与序列化和反序列化的对象,必须要实现Serialzable接口。
    
通过源代码发现,Serialzable接口只是一个标志接口:
    public interface Serialable{
}
   这个接口当中什么代码都没有。
       只是起到标识的作用,java虚拟机看到这个类实现了Serialzable接口可能会对这个类,进行特殊待遇
       这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成一个序列化版本号。
       

12.3序列化

package com.IO;
​
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/17:13
 * @Description:序列化
 */
public class ObjectOutputTest {
    public static void main(String[] args) throws IOException {
        //创建ObjectOutputStream对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Student"));
        //创建Student对象
        Student student = new Student();
        //序列化对象
        oos.writeObject(student);
        //刷新
        oos.flush();
        //关闭
        oos.close();
    }
}
//实现Serializable接口
class Student implements Serializable {
//java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号
//这里没有手动写出来,java虚拟机会默认提供序列化版本号    
}
package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/17:33
 * @Description:反序列化
 */
public class ObjectInputStreamTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建对象
        ObjectInputStream ois = new ObjectInputStream( new FileInputStream("Student"));
        //开始反序列化读
        Object o =ois.readObject();
        //反序列化回来是一个学生对象,所以会调用学生对象的toString方法
        System.out.println(o);
    }
}
​

12.4序列化多个对象

将对象放到集合当中序列化集合

package com.IO;
​
import java.io.*;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/19:57
 * @Description:
 */
public class ObjectTest  {
    public static void main(String[] args) throws IOException {
        //创建Set集合
        Set<Customer> sets = new TreeSet();
        sets.add(new Customer(12));
        sets.add(new Customer(13));
        sets.add(new Customer(18));
        sets.add(new Customer(19));
        //创建对象流
        ObjectOutputStream  oos= new ObjectOutputStream(new FileOutputStream("File_set"));
        //序列化
        oos.writeObject(sets);
        //刷新
        oos.flush();
        //关闭
        oos.close();
    }
}
​
class Customer implements Serializable,Comparable<Customer>{
    private int age;
​
    public Customer(int age) {
        this.age = age;
    }
​
    @Override
    public String toString() {
        return "Customer{" +
                "age=" + age +
                '}';
    }
​
    @Override
    public int compareTo(Customer o) {
        return this.age-o.age;
    }
}
package com.IO;
​
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Set;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/09/16/20:06
 * @Description:
 */
public class ObjectTest_show {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建Object
        ObjectInputStream ois= new ObjectInputStream(new FileInputStream("File_set"));
        //反序列化
        Object obj =ois.readObject();
        //判断是不是属于Set集合
        System.out.println(obj instanceof Set);
        //直接转型成Set集合
        Set<Customer> Customers=(Set)obj;
​
        for(Customer Customer: Customers){
            System.out.println(Customer);
        }
    }
}
​
  • 注意:如果不用集合序列化多个对象,序列化第二个的时候就会报错

  • 所以序列化多个对象最好是用集合

12.5transient

不希望其中某个属性被序列化

//使用transient关键字之后
package com;
​
import java.io.Serializable;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/22/11:22
 * @Description:
 */
public class User implements Serializable {
    private int age;
    private transient String name;//name不参与序列化操作
    //transient表示游离的,不参加序列化
    public User(int age, String name) {
        this.age = age;
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return "User{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

12.6序列化版本号

//java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号。
//这里没有手动写出来,java虚拟机会默认提供这个序列化版本号。
//建议将序列化版本号手动的写出来,不建议自动生成
​
序列化反序列化完成之后。修改代码,再反序会出现异常。序列化版本号发生了变动。
    
/*java语言中是采用什么机制来区分的?
    第一:首先通过对类名进行对比,如果类名不一样肯定不是同一类。
    第二:如果类名一样,就靠序列化版本号进行区分。*/

不是同一个类会报异常

  • 自动生成序列化版本号的缺陷:

不能修改代码,一修改代码就会报错。因为只要修改就会重新编译,此时会生成全新的序列化版本号,这个时候java虚拟机会认为这是一个全新的类。(这样就不好了)

最终结论:凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号。这样即使这个类被修改了,但是版本号不变,java虚拟机会认为是用同一个类

    private static final long serialVersionUID = 1L;
//java虚拟机识别一个累的时候先通过类名,如果类名一致,再通过序列化版本号。

13.IO+Properties联合使用

IO流:文件的读和写

Properties:是一个Map集合,key和value都是String类型。

package test;
​
import java.io.FileInputStream;
import java.io.FileReader;
import java.util.Properties;
​
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Mr.chen
 * @Date: 2022/07/24/17:04
 * @Description:配置文件
 */
​
/**
 *  Properties 可保存在流中或从流中加载。
 *  void load(InputStream inStream)从输入流中读取属性列表(键和元素对)。
 */
public class IoPropertiestests {
    public static void main(String[] args) throws Exception {
        /*
        Properties是一个Map集合,key和value都是String类型。
        想将userinfo文件中的数据加载到Properties对象当中。
         */
​
        //新建一个输入流对象
        //FileReader reader = new FileReader("javase/javaSE/src/userinfo");
        FileInputStream inputStream = new FileInputStream("/Test01/javase/userinfo");
        //新建一个Map集合
        Properties pro = new Properties();
​
        //调用Properties对象的load方法将文件中的数据加载到Map集合中。
        pro.load(inputStream);//文件中的数据顺着管道加载到Map集合中,其中等号左边作key,右边作value
​
        //通过key来回去value呢?
        String username =pro.getProperty("username");
        /**
         *  String getProperty(String key)用指定的键在此属性列表中搜索属性。
         */
        System.out.println(username);
        String password = pro.getProperty("password");
        System.out.println(password);
    }
}
​

注意

属性配置文件重复会覆盖

username=admin
password=123
################属性配置文件中#是注释符号################
#属性配置文件的key重复了value就会被自动覆盖
#最好不要有空格  password    =    456
#key和value之间也可用:隔开
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值