IO流学习

本文详细介绍了Java中File类的使用,包括文件和目录的操作,如创建、删除、读写属性等。深入探讨了IO流的各种类型,如字节流、字符流、缓冲流、数据流和对象流,并展示了如何高效地进行文件复制。此外,还讨论了装饰模式和适配器模式的概念及其在代码实现中的应用。
摘要由CSDN通过智能技术生成

File类

file操作文件

 public static void main(String[] args) throws IOException {
        //创建一个File类对象
        //File f = new File("F:\java学习\常用类、集合和IO\test.txt");错误的 里面会误识别转义字符
        //File f = new File("F:\\java学习\\常用类、集合和IO\\test.txt");可以
        File f = new File("F:/java学习/常用类、集合和IO/test.txt");//可以
        //File f = new File("F:"+ File.separator+"java学习"+File.separator+"常用类、集合和IO"+File.separator+"test.txt");// File.separator 系统的分隔符 在不同的系统上不一样 用这个扩展性好
        //System.out.println(f.exists());
//        if(f.exists()){//如果存在  就删除文件
//            f.delete();
//        }else{//如果不存在  就新建
//            f.createNewFile();
//        }

//        System.out.println(f.isDirectory());//是否是目录(文件夹)  false
//        System.out.println(f.isFile());//是否是文件  true
//        System.out.println(f.isHidden());//是否隐藏  false
//        System.out.println(f.getName());//文件名  test.txt
//        System.out.println(f.getParent());//在哪个目录下  F:\java学习\常用类、集合和IO
//        System.out.println(f.canRead());//可读  true
//        System.out.println(f.canWrite());//可写  true

        System.out.println("-----------------");
        File d=new File("aaa.txt");
        if (d.exists()==false){
            d.createNewFile();
        }

        System.out.println("绝对路径"+d.getAbsolutePath());//绝对路径F:\JAVAcode\test\aaa.txt
        System.out.println("相对(当前路径)路径"+d.getPath());//相对(当前路径)路径aaa.txt

    }

file操作目录

public static void main(String[] args) {
        File f=new File("F:/java学习/常用类、集合和IO");
//        if (f.exists()){
//            f.delete();
//        }else{
//            //f.mkdir();创建一个目录
//            f.mkdirs();//创建多层目录
//        }

        File[] listfiles=f.listFiles();//获取目录下的所有文件
        for (File ff:listfiles){
            System.out.println(ff.getName()+"--"+ff.length()+"--"+ff.isDirectory());
        }


    }

递归遍历目录

public static void main(String[] args) {
    File f=new File("F:/java学习/常用类、集合和IO");
    bianli(f,1);

}
public static void bianli(File f,int level){
    File[] files=f.listFiles();
    for (File file:files){//可能是文件  也可能是文件夹
        for (int i = 0; i < level; i++) {
            System.out.print("-");
        }
        System.out.println(file.getName());
        if (file.isDirectory()){
            bianli(file,level+1);
        }

    }

}

在这里插入图片描述

IO流

文件字节流–FileInputStream,FileOutputStream

文件---->程序

public static void main(String[] args) throws IOException {
    //文件---->程序

    //1、确定一个文件
    File f=new File("F:/java学习/常用类、集合和IO/a.txt");
    //2、将一个管怼到源文件中去
    FileInputStream fis=new FileInputStream(f);
    //3、开始读
    int n = fis.read();
    while (n!=-1){
        System.out.println((char)n);
        n=fis.read();
    }
    //4、关闭流
    fis.close();


}

效率更高

public static void main(String[] args) throws IOException {
    //文件---->程序

    //1、确定一个文件
    File f=new File("F:/java学习/常用类、集合和IO/a.txt");
    //2、将一个管怼到源文件中去
    FileInputStream fis=new FileInputStream(f);
    //System.out.println(fis.available());//对文件大小进行预估
    //3、开始读
    byte[] b=new byte[8];
    int n = fis.read(b);
    while (n!=-1){
        for (int i = 0; i < n; i++) {
            System.out.println(b[i]);
        }
        n= fis.read(b);
    }
    //4、关闭流
    fis.close();


}

程序----->文件

public static void main(String[] args) throws IOException {
    //1、确定一个文件:目标文件
    File f=new File("F:/java学习/常用类、集合和IO/b.txt");
    //2、将一个管怼到目标文件
    FileOutputStream fos=new FileOutputStream(f,true);
    //如果用的是空构造器,那么文件被覆盖。如果用两个构造器,设置为true,那么是追加

    //3、给一个字符串
    String str="aaa";
    //4、开始动作
    byte[] bytes = str.getBytes();
    for (byte b : bytes) {
        fos.write(b);

    }
    //5、关闭流
    fos.close();


}

效率更高

public static void main(String[] args) throws IOException {
    //1、确定一个文件:目标文件
    File f=new File("F:/java学习/常用类、集合和IO/b.txt");
    //2、将一个管怼到目标文件
    FileOutputStream fos=new FileOutputStream(f,true);
    //如果用的是空构造器,那么文件被覆盖。如果用两个构造器,设置为true,那么是追加

    //3、给一个字符串
    String str="iii";
    //4、开始动作
    byte[] bytes = str.getBytes();
    fos.write(bytes);
    //5、关闭流
    fos.close();


}

文件的复制

public static void main(String[] args) throws IOException {
    //1.确定源文件
    File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
    //2.确定目标文件
    File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
    //3.将一根管怼到源文件
    FileInputStream fis=new FileInputStream(f1);
    //4.将一根管怼到目标文件
    FileOutputStream fos=new FileOutputStream(f2);
    //5.开始动作
    int n = fis.read();
    while (n!=-1){
        fos.write(n);
        n=fis.read();
    }
    //6.关闭流(倒着关)
    fos.close();
    fis.close();

}

效率更高

public static void main(String[] args) throws IOException {
    //1.确定源文件
    File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
    //2.确定目标文件
    File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
    //3.将一根管怼到源文件
    FileInputStream fis=new FileInputStream(f1);
    //4.将一根管怼到目标文件
    FileOutputStream fos=new FileOutputStream(f2);
    //5.开始动作
    byte[] b=new byte[5];
    int len = fis.read(b);
    while (len!=-1){
        fos.write(b,0,len);//把长度为5的数组中 从下标[0,len)这个位置写出去
        len = fis.read(b);
    }

    //6.关闭流(倒着关)
    fos.close();
    fis.close();

}

文件字符流–FileReader,FileWriter

文件的复制

public static void main(String[] args) throws IOException {
    //1.确定源文件
    File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
    //2.确定目标文件
    File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
    //3.将一根管怼到源文件
    FileReader fr = new FileReader(f1);
    //4.将一根管怼到目标文件
    FileWriter fw = new FileWriter(f2);
    //5.开始动作
    int n = fr.read();
    while (n!=-1){
        fw.write(n);
        System.out.println((char)n);
        n=fr.read();
    }
    //6.关闭流(倒着关) 字符流必须进行刷新 如果写的是关闭流 那么底层直接做了flush动作
    //fw.flush();
    fw.close();
    fr.close();
}

效率更高(缓冲数组)

public static void main(String[] args) throws IOException {
    //1.确定源文件
    File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
    //2.确定目标文件
    File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
    //3.将一根管怼到源文件
    FileReader fr = new FileReader(f1);
    //4.将一根管怼到目标文件
    FileWriter fw = new FileWriter(f2);
    //5.开始动作
    char[] ch=new char[4];
    int len = fr.read(ch);
    while (len!=-1){
        fw.write(ch,0,len );
        len=fr.read(ch);
    }

    //6.关闭流(倒着关) 字符流必须进行刷新 如果写的是关闭流 那么底层直接做了flush动作
    //fw.flush();
    fw.close();
    fr.close();
}

缓冲字节流–BufferedInputstream,BufferedOutputstream

在程序里建立的缓冲区,减少了对磁盘的访问,速度更快

public static void main(String[] args) throws IOException {
        //确定源文件
        File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
        //确定目标文件
        File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
        //直接接触的是字节流,字节流站在工作第一线,直接跟源文件,目标文件接触
        FileInputStream fis = new FileInputStream(f1);
        FileOutputStream fos = new FileOutputStream(f2);
        //字节流外面包着缓冲字节流
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        //开始动作
        byte[] b=new byte[4];
        int n = bis.read(b);
        while (n!=-1){
            bos.write(b,0,n);
            n = bis.read(b);
        }
       
        //关闭流:只关闭高级流就可以了
        bos.close();
        bis.close();
        fos.close();
        fis.close();

}

缓冲字符流–BufferedReader,BufferedWriter

在程序里建立的缓冲区,减少了对磁盘的访问,速度更快

public static void main(String[] args) throws IOException {
        //确定源文件
        File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
        //确定目标文件
        File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
        //字符流
        FileReader fis = new FileReader(f1);
        FileWriter fos = new FileWriter(f2);
        //字符流外面包着缓冲字符流
        BufferedReader bis = new BufferedReader(fis);
        BufferedWriter bos = new BufferedWriter(fos);

        //开始动作
        char[] b=new char[4];
        int n = bis.read(b);
        while (n!=-1){
            bos.write(b,0,n);
            n = bis.read(b);
        }

        //关闭流:只关闭高级流就可以了
        bos.close();
        bis.close();
        fos.close();
        fis.close();
        
}

效率是上面几个中最高的

public static void main(String[] args) throws IOException {
        //确定源文件
        File f1=new File("F:/java学习/常用类、集合和IO/a.txt");
        //确定目标文件
        File f2=new File("F:/java学习/常用类、集合和IO/b.txt");
        //z
        FileReader fis = new FileReader(f1);
        FileWriter fos = new FileWriter(f2);
        //字符流外面包着缓冲字符流
        BufferedReader bis = new BufferedReader(fis);
        BufferedWriter bos = new BufferedWriter(fos);

        //开始动作
        String str = bis.readLine();//一行一行的读
        while (str!=null){
            bos.write(str);
            bos.write("\r\n");//换行 等价于bos.newLine();
            str=bis.readLine();
        }
        //关闭流:只关闭高级流就可以了
        bos.close();
        bis.close();
        fos.close();
        fis.close();

}

System类对IO流的支持

public static void main(String[] args) throws IOException {
//        Scanner sc = new Scanner(System.in);
//        System.out.println("请输入一个数");
//        int num = sc.nextInt();
//        System.out.println(num);

        //键盘录入是字节流控制
//        InputStream in = System.in;
//        int n= in.read();//键盘录入  在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞

        PrintStream ps = System.out;//PrintStream--打印流  出来的数据是失去原本的数据类型 都变成了String类型
        ps.println("java");
        ps.println("oracle");
        ps.println("19");
        ps.println(new Date());
        


    }
//扫描硬盘上的文件
Scanner sc=new Scanner(new FileInputStream(new File("F:/java学习/常用类、集合和IO/a.txt")));
while (sc.hasNext()){
    System.out.println(sc.next());
}

转换流

将字节流转换成字符流

public static void main(String[] args) throws IOException {
    //将键盘录入的东西输出到硬盘上的文件中去  用效率最高的方式

    //字符----缓冲-----一行一行的读
    InputStream in = System.in;//这句返回的是字节流

    //字节流转字符流(转换流)  只能单向转换
    InputStreamReader isr = new InputStreamReader(in);
    //转入字符流
    BufferedReader br = new BufferedReader(isr);
    BufferedWriter bw = new BufferedWriter(new FileWriter(new File("F:/java学习/常用类、集合和IO/c.txt")));
    //开始动作
    String str = br.readLine();
    while (str!=null){
        if (str.equals("over")){
            break;
        }
        bw.write(str);
        bw.newLine();//换行
        str = br.readLine();
    }
    //关闭流
    bw.close();
    br.close();
    isr.close();
    in.close();


}

数据流–操纵基本数据类型

往文件里写数据流

public static void main(String[] args) throws IOException {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("F:/java学习/常用类、集合和IO/d.txt")));
    dos.writeInt(90);
    dos.writeBoolean(true);
    dos.writeDouble(9.7);
    dos.writeUTF("java");

    dos.close();
}

从文件里读数据流

public static void main(String[] args) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream("F:/java学习/常用类、集合和IO/d.txt"));
    int readInt = dis.readInt();
    System.out.println(readInt);
    System.out.println(dis.readBoolean());
    System.out.println(dis.readDouble());
    System.out.println(dis.readUTF());

    dis.close();
}

对象流–操纵引用数据类型

序列化:程序–》硬盘

public static void main(String[] args) throws IOException {
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("F:/java学习/常用类、集合和IO/b.txt")));
    oos.writeObject(new Student(18,"lili"));
    oos.close();

}

反序列化:硬盘–》程序

public static void main(String[] args) throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("F:/java学习/常用类、集合和IO/b.txt")));
    Object o = ois.readObject();
    System.out.println(o);
    ois.close();


}

序列化版本号serialVersionUID

//Serializable查看源码,发现什么方法常量都没有。原因:这是一个标识
public class Student implements Serializable {
    //序列化版本号serialVersionUID
    private static final long serialVersionUID = 1001L;//版本号
    private int age;
    private String name;


    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    public Student(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;
    }
}

使用了序列化版本号 可以在序列化后对该类进行修改,而不用修改了再序列化

idea的序列化版本号

idea使用序列化版本号,首先需要在file–setting–plugins里下载generateserialVersionUID

在这里插入图片描述

下载完后到这个界面检查是否勾上

在这里插入图片描述

然后art+insert里就会有序列化版本号

在这里插入图片描述

使变量不序列化的方法

transient关键字的主要作用就是让某些被transient关键字修饰的成员属性变量不被序列化

静态变量 和 transient 修饰的变量不会参与到序列化中

//Serializable查看源码,发现什么方法常量都没有。原因:这是一个标识
public class Student implements Serializable {
    //序列化版本号serialVersionUID
    private static final long serialVersionUID = 1001L;//版本号
    private int age;
    private String name;
    static String school;//学校
    transient String password;//密码

    public Student(int age, String name, String password) {
        this.age = age;
        this.name = name;
        this.password = password;
    }

    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' + ",school='" + school + '\'' +
                '}';
    }

    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;
    }
}

在这里插入图片描述

文件夹的复制

使用缓冲字节流 字符流不能使用 因为字符流不能复制照片等特殊文件

public static void main(String[] args) throws IOException {
    //复制文件夹  只能用字节流  不能用字符流 因为字符流不能复制照片等
    File f1=new File("F:/java学习/常用类、集合和IO");
    File f2=new File("F:/java学习/常用类、集合和IO2");
    copyDir(f1,f2);
}
public static void copyDir(File srcFile,File targerFile) throws IOException {
    //如果不存在这个目标文件夹,就要创建一个新的文件夹
    if (!targerFile.exists()){
        targerFile.mkdirs();
    }
    //开始对源文件进行遍历,然后复制
    File[] lf=srcFile.listFiles();
    for (File f:lf){
        if (f.isFile()){//遍历的是文件,操作如下
            copyfile(new File(srcFile+"/"+f.getName()),new File(targerFile+"/"+f.getName()));
        }else{//遍历出来是一个目录,操作如下
            copyDir(new File(srcFile+"/"+f.getName()),new File(targerFile+"/"+f.getName()));
        }
    }

}

public static void copyfile(File srcFile,File targerFile) throws IOException {
    FileInputStream fis=new FileInputStream(srcFile);
    BufferedInputStream bis = new BufferedInputStream(fis);

    FileOutputStream fos = new FileOutputStream(targerFile);
    BufferedOutputStream bos = new BufferedOutputStream(fos);

    //开始动作
    byte[] b= new byte[1024];
    int n = bis.read(b);
    while (n!=-1){
        bos.write(b,0,n);
        n=bis.read(b);

    }
    //关闭流
    bos.close();
    bis.close();
    fos.close();
    fis.close();
}

设计模式

有23种设计模式

装饰模式

概念:指再不必改变原类文件和使用继承的情况下,动态地扩展一个对象地功能。动态地为一个对象增加一个新的功能。装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。

在这里插入图片描述

public interface MakeCake {//制作蛋糕的接口
    void make();//抽象方法 做蛋糕

}
//父类:蛋糕
abstract class Cake implements MakeCake{
    @Override
    public abstract void make();

}
//子类:巧克力蛋糕
class ChocoCake extends Cake{

    @Override
    public void make() {
        System.out.println("制作巧克力蛋糕");
    }
}
//子类:抹茶蛋糕
class MoChaCake extends Cake{

    @Override
    public void make() {
        System.out.println("制作抹茶蛋糕");
    }
}
//修饰的父类
class Decorater implements MakeCake{
    //修饰谁?
    private MakeCake mc;
    public Decorater(MakeCake mc){
        this.mc = mc;
    }

    @Override
    public void make() {
        mc.make();
    }
}
//子类:加口红来修饰
class DecKouHong extends Decorater{


    public DecKouHong(MakeCake mc) {
        super(mc);
    }

    @Override
    public void make() {
        super.make();
        add();
    }
    public void add(){
        System.out.println("在蛋糕中塞入一个口红");

    }

}
//子类:加钻戒修饰
class DecZuanJie extends Decorater {
    public DecZuanJie(MakeCake mc) {
        super(mc);
    }

    @Override
    public void make() {
        super.make();
        add();
    }
    public void add(){
        System.out.println("在蛋糕中加入一个钻戒");
    }
}
//测试类
class Test{
    public static void main(String[] args) {
        //买一个巧克力蛋糕
        ChocoCake cc=new ChocoCake();
        cc.make();
        System.out.println("-------");
        //在巧克力蛋糕的基础上加一个口红
        DecKouHong dkh = new DecKouHong(cc);
        dkh.make();
        System.out.println("-------");
        //再加入一个钻戒
        DecZuanJie dzj = new DecZuanJie(dkh);
        dzj.make();
        System.out.println("-------");
        //定制一个带钻戒、口红的抹茶蛋糕
        new DecKouHong(new DecZuanJie(new MoChaCake())).make();
        

    }
}

适配器模式

优点:更好的复用性,更好的扩展性

缺点:过多的使用适配器,会让系统非常零乱,不易整体进行把握

类适配器

//被适配的类
public class Adaptee {
    public void surf(){
        System.out.println("提供上网的功能");
    }

}
//客户的目的就是为了能上网
interface Target{
    void toSurf();
}
class Client{
    public void want(Target t){
        t.toSurf();
    }

}
//进行适配工作
class Adapter extends Adaptee implements Target{

    @Override
    public void toSurf() {
        System.out.println("转换。。");
        super.surf();
    }
}
class Test{
    public static void main(String[] args) {
        new Client().want(new Adapter());

    }
}

对象适配器

//被适配的类
public class Adaptee {
    public void surf(){
        System.out.println("提供上网的功能");
    }

}
//客户的目的就是为了能上网
interface Target{
    void toSurf();
}
class Client{
    public void want(Target t){
        t.toSurf();
    }

}
//进行适配工作
class Adapter  implements Target{
    Adaptee ae;
    public Adapter(Adaptee ae){
        this.ae = ae;
    }
    @Override
    public void toSurf() {

        System.out.println("转换。。");
        ae.surf();
    }
}
class Test{
    public static void main(String[] args) {
        new Client().want(new Adapter(new Adaptee()));
        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值