第12章 文件与流

目标

  • 文件与目录管理
  • 文件读写(字节流 字符流)
  • 对象序列化

文件与目录管理

前置任务

前置需要了解的知识
1、持久化-永久保存有两种方式

  • 1、存数据库里 --关系型数据库--方便多表连接查询 连接数限制 高并发慢 jdbc
  • 2、存文件 --没有关系 简单的数据 高并发 读写快
    2、windows和linux下目录有什么不同
    windows d:/java24/file \
    linux:/root/java24

通用方式 "d:"+File.separator+"io"

目录操作

构造方法:File(String pathname)
判断目录或文件是否存在的方法:exists()
创建目录的方法:mkdir() 一次创建一级目录
mkdirs() 一次创建多级目录

@Test
public void test01(){
    //目录或文件实例化
    File path=new File("e:/java24/io");
    //1、判断文件或目录是否存在
    boolean result1=path.exists();//判断目录或者文件是否存在
    System.out.println("目录是否存在"+result1);
    if(result1){//3、如果存在,就打印目录已存在
        System.out.println("目录已存在");
    }else{//2、如果不存在,创建目录
        //path.mkdir();
           path.mkdirs();
    }
}

文件操作

文件创建:
构造方法:File(File path,String filename)
File(String 完整路径)
新建文件: createNewFile()

createNewFile()+File(File path,String filename)示例

@Test
public void test02(){
    //存放一些东西到指定目录下的指定文件里
    //1、文件实例化  (path,filename)
    File path=new File("d:/java24/io");//目录
    String filename="text01.txt";
    File f=new File(path,filename);
    //2、首先判断目录path是否存在
    //2-2如果目录不存在
    if(!path.exists()){
        System.out.println("目录不存在,开始创建目录");
         //2-2-1先创建目录  注意:mkdir一次只能创建一个    mkdirs可以一次创建多级目录(目录及父目录)
        //path.mkdir();
           path.mkdirs();
    }
    System.out.println("目录肯定创建出来");  
    //-----目录一定存在
          //2-1-1-1 目录已存在情况下,判断文件是否存在
    if(f.exists()){ //如果文件存在  打印文件已存在
        System.out.println("文件已存在,可以进行后续操作了");
    }else{//如果文件不存在  就需要创建文件
        try {
            boolean result=f.createNewFile();
            if(result){//result==true
                System.out.println("文件创建成功");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

//上面演示和目录和文件的创建过程,以下程序假定文件已经存在  d:/java24/text01.txt
//文件的属性


@Test
public void test04(){
    //目录和文件都已经存在情况下,查看文件属性
    //如果目录和文件都已经存在的存在下,我们可以用
    File f=new File("d:/java24/text01.txt");
    if(f.exists()){
        //可以通过get方法获取一些属性
        System.out.println("可读属性:"+f.canRead());
        System.out.println("可写属性:"+f.canWrite());
        System.out.println("文件路径:"+f.getPath());
        System.out.println("文件名字:"+f.getName());
        System.out.println("绝对路径:"+f.getAbsolutePath());
        System.out.println("是否隐藏:"+f.isHidden());
        System.out.println("文件大小"+f.length());
        System.out.println("最后一次修改时间:"+f.lastModified());
    }
}

getPath和getAbsolutePath区别

new File("")时,路径为空时,getPath返回空值,getAbsolutePath可以返回当前绝对路径
new File("d:/file/mydata") 路径不为空时,两者都返回路径名。

@Test
public void test02() throws IOException{
    File path = new File("");
    System.out.println("==>"+path.getPath());
    String cur_path=path.getAbsolutePath();//FILE为空字符串时,可以获取当前路径;如果路径不是空串时,就返回真实路径 
    System.out.println(cur_path);
    File file1=new File(cur_path,"b.txt");
    if(!file1.exists()){
        file1.createNewFile();
    }
    
}





// 列出目录下的所有文件.listFiles 
    //d:/java24/text01.txt 02.txt
// 1kb=1024byte
@Test
public void test05() {
    File path = new File("d:/java24");
    if (path.exists()) {// 目录存在
        // 列出目录下的所有文件
        File[] files = path.listFiles();
        // 循环打印各文件情况 用for循环
        for (File f : files) {
            // 可以通过get方法获取一些属性
            System.out.println("可读属性:" + f.canRead());
            System.out.println("可写属性:" + f.canWrite());
            System.out.println("文件路径:" + f.getPath());
            System.out.println("文件名字:" + f.getName());
            System.out.println("绝对路径:" + f.getAbsolutePath());
            System.out.println("是否隐藏:" + f.isHidden());
            System.out.println("文件大小" + f.length());
            System.out.println("最后一次修改时间:" + f.lastModified());
            System.out.println("-----------------------------------------");
        }

    }
}
image.png

从流向上分:
输入流: 从文件---》内存或程序 (in.read )
输出流:从程序或内存-文件 (out.write)
按处理数据的单位不同
字节流(以字节形式byte[]读取的 音频视频word excel)
字符流(char String 文本类型文件)

按功能不同
节点流(直接跟文件交互的 低级流)
处理流(缓冲流 高级流)
高级流要用到低级流的功能
Java语言中,控制数据流的类都放在java.io包中

image.png

1、操作字符流

读字符类文件

注意:存文件时要用utf-8编码,否则与我们的工作区编码方式 不匹配,出现乱码


image.png
// 字符流(可以用文本编辑器打开,可以正常看的 )
@Test
public void test07() throws IOException {
    //文本文件的编码方式改为utf-8
    // BufferedReader(Reader in) Reader我们选的是FileReader--->FileReader(File
    // file)
    File file = new File("d:/java24/text01.txt");//3
    FileReader fr = new FileReader(file);//2
    // 理解为是一个工具类,他专门用来读文本文件内容
    BufferedReader br = new BufferedReader(fr);//1
    while(true) {//4
        String str = br.readLine();// 一次读取一行文本
        if (str != null) {
            System.out.println(str);
        } else {
            break;
        }
    }
}

text01.txt的内容:

wang-qj王秋菊
wang-hz
yin-ss

控制台输出:

image.png

写字符类文件

//字符流写操作 step2 向文本文件里写入内容
@Test
public void test08() throws IOException  {
    //确认文件是utf-8编码
    File file=new File("d:/java24/text02.txt");
    FileWriter fileWriter=null;
    //第一个参数是为是否append
    BufferedWriter bw=null;
    try {
        fileWriter = new FileWriter(file,true);//第二个参数是表示是否向文件中追加内容
        bw=new BufferedWriter(fileWriter);
        bw.write("问:没声音吗1111111111");//写文本
        bw.newLine();//换行
        //bw.flush();//冲下去
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }finally{//记着关闭流
        //如果调用了关闭流的方法,就不用手动调bw.flush()
        bw.close();
        fileWriter.close();
    }
}

//step3 文本文件copy
//从d:/java24/text01.txt每次读一行,写入到d:/java24/text02.txt
@Test
public void test09() throws IOException{
    //从d:/java24/text01.txt读
    //每读到一行,向d:/java24/text02.txt写入
    //step1 初始化输入输出流
    FileReader fr=null;
    BufferedReader br=null;
    FileWriter fw=null;
    BufferedWriter bw=null;
    try {
        System.out.println("开始初始化输入输出流");
        //初始化输入流
        File inputFile=new File("d:/java24/text01.txt");
        fr=new FileReader(inputFile);
        br=new BufferedReader(fr);
        //初始化输出流
        fw=new FileWriter("d:/java24/text02.txt",true);
        bw=new BufferedWriter(fw);
        //step2 死循环从输入流(也就是text01.txt)一行一行读
        while(true){
            //一次读取一行
            String content=br.readLine();
            if(content!=null){//如果读到的内容不为null
                System.out.println("读到了一行,开始写入");
                bw.write(content);
                bw.newLine();
            }else{
                System.out.println("拷贝完成");
                break;
            }
        }
    } catch (Exception e) {
        // 打印异常
        e.printStackTrace();
    }finally{
        //关闭流
        bw.close();
        fw.close();
        br.close();
        fr.close();
    }
}

//字节流操作 mytest01.docx mytest02.docx
@Test
public void test10() throws IOException{
    //高级字节流BufferedInputStream(BufferedOutpoutStream) 低节流FileInputStream (FileOutputStream )
    //注意节流得按节读
    //step1 初始化输入输出流
    
    FileInputStream fis=null;
    BufferedInputStream bis=null;
    
    FileOutputStream fos=null;
    BufferedOutputStream bos=null;
    
    try{
        System.out.println("初始化输入输出流");
        File input=new File("d:/java24/mytest01.docx");
        //初始化低级输入流
        fis=new FileInputStream(input);
        //初始化高级输入流
        bis=new BufferedInputStream(fis);
        
        
        File output =new File("d:/java24/mytest02.docx");
        //初始化低级输出流
        fos=new FileOutputStream(output);
        //初始化高级输入流
        bos=new BufferedOutputStream(fos);
        System.out.println("准备工作已完成,开始从输入流读取");
        
        System.out.println("开始预估文件大小");
        int length=bis.available();
        System.out.println("文件大小为:"+length);
        //新建一个同样大小的byte数组用于临时缓存读到
        byte[] b=new byte[length];
        //调用
        int read_len=bis.read(b);//把读到的数据临时放到byte数组中,这个方法返回值为读取到的字节大小,如果读完,返回-1
        System.out.println("读到的文件长度"+read_len);
        //把byte数组里的东西存到mytest02.docx里
        if(read_len!=-1){
            System.out.println("将读到的内容写入到新的文件里");
            bos.write(b, 0, read_len);
        }
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        //从下向上关闭流
        bos.close();
        fos.close();
        bis.close();
        fis.close();
        
    }
}

改善的写法:

//字节流拷贝
@Test
public void test07(){
    //FileInputStream BufferedInputStream
    //FileOutputStream BufferedOutputStream
    File file=new File("E:" + File.separator + "java6" + File.separator + "filestudy", "01.png");
    FileInputStream in=null;
    BufferedInputStream bis=null;
    
    File file2=new File("E:" + File.separator + "java6" + File.separator + "filestudy", "10.png");
    FileOutputStream out=null;
    BufferedOutputStream bos=null;
    try {
        in=new FileInputStream(file);
        bis=new BufferedInputStream(in);
        out = new FileOutputStream(file2);
        bos=new BufferedOutputStream(out);
        //读取到的字节的长度
        int b;
        //7936  1024....791   -1
        //bis.read() 每次读取到的字节数
        while((b=bis.read())!=-1){
        //把b长度的字节写入到bos里
        bos.write(b);
        }
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }finally{
        try {
            bos.close();
            out.close();
            bis.close();
            in.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

作业:1、练习上面的字符流和字节流拷贝
2、预习对象序列化和反序列化

对象的序列化和反序列化

image.png

step1 新建一个可序列化的对象

Dept.java
1)implements Serializable
2)自动生成一个id:
private static final long serialVersionUID = 5321630967988198440L;

    public class Dept implements Serializable{
    
        /**
         * 为他指定一个id
         */
        private static final long serialVersionUID = -6773472139020270906L;
        //部门编号
        private int deptNo;
        //部门名称
        private String dname;
        //部门所在地
        private String loc;
    
        public int getDeptNo() {
            return deptNo;
        }
    
        public void setDeptNo(int deptNo) {
            this.deptNo = deptNo;
        }
    
        public String getDname() {
            return dname;
        }
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        public String getLoc() {
            return loc;
        }
    
        public void setLoc(String loc) {
            this.loc = loc;
        }
    
    }

step2 新建一个文本文件

d:/java24/dept01.txt

序列化程序

也是文件操作
序列化涉及的流
低级流:FileOutputStream FileInputStream
高级流:ObjectOutputStream ObjectInputStream

把对象写入到--->txt文件里,用到的是FileOutputStream ObjectOutputStream
ObjectOutputStream.writeObject(Object o)
样例代码

@Test
public void test01() throws IOException{
    //ObjectOutputStream  writeObject(Object obj) 
    //为ObjectOutputStream准备一个低级流  FileOutputStream
    FileOutputStream fos=null;
    //step1 实例化一个工具ObjectOutputStream
    ObjectOutputStream oos=null;
    try {
        System.out.println("开始实例化输出流对象");
        File file=new File("d:/java24/dept01.txt");
        fos=new FileOutputStream(file);
        oos=new ObjectOutputStream(fos);
        System.out.println("实例化输出流对象结束");
        //--把dept对象存到dept01.txt
        //step 2 准备一个dept01对象
        System.out.println("准备一个dept对象");
        Dept dept10=new Dept();
        dept10.setDeptNo(10);
        dept10.setDname("部门10");
        dept10.setLoc("沈阳");
        //step 3把对象持久化到文件里
        if(dept10!=null){
            System.out.println("开始序列化对象");
            oos.writeObject(dept10);
            System.out.println("序列化对象结束");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally{
        oos.close();
    }
}


//对象反序列化其实是 txt-->Object  解密
//ObjectInputStream.readObject()
@Test
public void test02() throws IOException{
    FileInputStream fis=null;
    //step1 实例化一个工具ObjectInputStream
    ObjectInputStream ois=null;
    
    try {
        System.out.println("开始准备工具类");
        File file=new File("d:/java24/dept01.txt");
        fis=new FileInputStream(file);
        ois=new ObjectInputStream(fis);
        System.out.println("开始反序列化对象");
        Dept dept=(Dept) ois.readObject();
        if(dept!=null){
            System.out.println(dept.getDname());
        }
    } catch (Exception e) {
        // TODO: handle exception
    }finally{
        ois.close();
    }
}

你可能感兴趣的:(第12章 文件与流)