Java=File类,递归,输入输出IO

一。File类:

File类可以表示文件或者文件夹

public File(String path);

public File(String parent,String child);

public File(File parent,String child);

public class FileDemo01 {
    public static void main(String[] args) {
        //1.构造方法1
        File f1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
        System.out.println(f1);
        //2.构造方法2
        File f2 = new File("C:\\Users\\Administrator","Desktop\\temp\\aaa");
        System.out.println(f2);

        //2.构造方法3
        File parent = new File("C:\\Users\\Administrator");
        File f3 = new File(parent,"Desktop\\temp\\aaa");
        System.out.println(f3);
    }
}

File类的获取方法

public String getAbsolutePath(); 获取该File对象的绝对路径
  
public String getPath(); 获取该File对象构造时,传入的路径    
    
public String getName(); 获取该File对象的代表的文件或者文件夹的名字
    
public long length(); 获取该File对象的大小(单位为字节)    

public class FileDemo02 {
    public static void main(String[] args) {
        //File类的获取方法
        File ff = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.txt");
        //1.getAbsolutePath
        String absolutePath = ff.getAbsolutePath();
        System.out.println(absolutePath);

        //2.getPath
        String path = ff.getPath();
        System.out.println(path);

        //3.getName
        String name = ff.getName();
        System.out.println(name);

        //4.length
        long len = ff.length();
        System.out.println(len+"字节");
    }
}

注意:length方法只能获取文件的大小,不能获取文件夹的大小

相对路径和绝对路径

绝对路径: 是指以盘符开头的路径
    比如: "C:\Users\Administrator\Desktop\temp\aaa\1.txt"
相对路径: 以当前项目的根目录为起始的路径   
	比如: "1.txt"  "aa\\1.txt"
public class FileDemo03 {
    public static void main(String[] args) {
        //1.绝对路径
        File ff1 = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa\\1.txt");
        //2.相对路径
        File ff2 = new File("1.txt"); //表示当前项目根目录下的1.txt
        File ff3 = new File("aa\\1.txt"); //表示当前项目根目录下的aa文件夹里的1.txt
    }
}

.File类的判断方法

public boolean exists(); 判断该File对象代表文件和文件夹是否存在
public boolean isDirectory(); 判断该File对象说代表是否是文件夹
public boolean isFile(); 判断该File对象说代表是否是文件
    
public class FileDemo04 {
    public static void main(String[] args) {
        //1.创建一个File对象
        File ff = new File("1.txt");//相对路径
        //2.判断是否存在
        boolean b = ff.exists();
        System.out.println("是否存在:" + b);

        //3.判断是文件呢??还是文件夹呢???
        boolean directory = ff.isDirectory();
        System.out.println("是文件夹吗?"+directory);
        boolean file = ff.isFile();
        System.out.println("是文件吗?"+file);
    }
}    

File类的创建删除方法

public boolean mkdir();创建单级文件夹,返回值表示是否创建成功   
public boolean mkdirs();创建多级文件夹,返回值表示是否创建成功        
public boolean createNewFile();创建文件,返回值表示是否创建成功  
public boolean delete();删除该File对象代表的文件或者空文件夹,返回值表示是否删除成功      
public class FileDemo05 {
    public static void main(String[] args) throws IOException {
        //1.创建一个File对象
        File ff = new File("2.txt");
        //2.创建文件
        boolean b1 = ff.createNewFile();
        System.out.println("是否创建成功呢??"+b1);
        //3.创建文件夹
        boolean b2 = ff.mkdir();
        System.out.println("是否创建成功呢??"+b2);

        //4.再创建一个File对象
        File ff2 = new File("aaa\\bbb\\ccc\\ddd");
        boolean b3 = ff2.mkdir();
        System.out.println("是否创建成功呢??"+b3);

        boolean b4 = ff2.mkdirs();
        System.out.println("是否创建成功呢??"+b4);

        //5.再创建File对象
        File ff3 = new File("2.txt");
        boolean b5 = ff3.delete();
        System.out.println("是否删除成功呢??"+b5);
    }
}    
    
注意: a.mkdir和mkdirs的区别
      b.delete方法要么删除文件,要么删除空文件夹,不能删除非空文件夹    

File类遍历目录的方法

public String[] list(); 列出当前文件夹下所有直接的文件和文件夹的名字
public File[] listFiles();列出当前文件夹下所有直接的文件和文件夹的File对象
    
public class FileDemo06 {
    public static void main(String[] args) {
        //1.创建一个File对象,必须是一个文件夹
        File ff = new File("C:\\Users\\Administrator\\Desktop\\temp\\aaa");
        //2.list
        String[] filenames = ff.list();
        for (String filename : filenames) {
            System.out.println(filename);
        }
        //3.listFiles
        File[] files = ff.listFiles();
        for (File file : files) {
            System.out.println(file);
        }
    }
}
注意: list和listFiles只能列直接的子文件或者子文件夹    

二。递归

递归不是Java语言独有的,(基本上很多语言都可以递归)
递归就是:在方法中调用该方法本身(自己调自己)
public class RecursionDemo01 {
    public static void main(String[] args) {
        method();
    }

    public static void method(){
        System.out.println("method....");
        //调用Method自己,这里称为递归
        method();
    }
}

无限递归(死递归)出现这个错误: StackOverflowError 栈溢出错误!!!

如果要使用递归,必须保证递归有出口(结束的条件)
    public static void main(String[] args) {
        method1(10);
    }

    //正常递归(有出口)
    public static void method1(int n){
        //判断
        if (n == 0){
            return; //这里就是递归的出口
        }
        System.out.println("method1...."+n);
        //调用Method自己
        method1(n-1);
    }
注意: 就算递归有出口,还要保证递归在运行到出口之前次数不能太多(太多也会栈内存溢出)

递归求和

需求: 使用递归求1-n的和(开发中不要用)

使用递归三大步骤:
	a.先定义一个方法(求和)
    b.找规律,调用自己
    c.让递归有出口(结束的条件)       
public class RecursionDemo02 {
    public static void main(String[] args) {
        //需求: 使用递归求1-n的和(开发中不要用递归求和)
        int sum = getSum(100);
        System.out.println(sum);
    }
    //使用递归
    //a.先定义一个方法(求和)
    public static int getSum(int n){
        //c.让递归有出口(结束的条件)
        if (n == 1){
            return 1;
        }
        //b.找规律,调用自己
        // 1+2+3..n = (1+2+3..+n-1) + n
        // getSum(n) = getSum(n-1) + n
        return getSum(n-1) + n;
    }


    //使用循环
    public static int getSum1(int n){
        //求和
        int sum = 0;
        for (int i = 1; i < n+1; i++) {
            sum+=i;
        }
        return sum;
    }
}    

递归求阶乘

需求: 使用递归求n的阶乘(就是求1-n的积)(开发中不要用)

使用递归三大步骤:
	a.先定义一个方法(求积)
    b.找规律,调用自己
    c.让递归有出口(结束的条件) 
        
public class RecursionDemo03 {
    public static void main(String[] args) {
        //需求: 使用递归求n的阶乘(就是求1-n的积)(开发中不要用递归求和)
        int ji = getJi(4);
        System.out.println(ji);
    }
    //使用递归三大步骤:
    //a.先定义一个方法(求积)
    public static int getJi(int n){
        //c.让递归有出口(结束的条件)
        if (n == 1) {
            return 1;
        }
        //b.找规律,调用自己
        // 1*2*3..*n = (1*2*3..n-1)*n
        // getJi(n) = getJi(n-1)*n
        return getJi(n-1)*n;
    }
    //使用循环
    public static int getJi1(int n){
        int ji = 1;
        for (int i = 1; i < n+1; i++) {
            ji *= i;
        }
        return ji;
    }
}        

文件搜索

需求:
	在某个目录中找出所有的.txt文件
    某个目录:C:\Users\Administrator\Desktop\temp\aa

public class RecursionDemo04 {
    public static void main(String[] args) {
//        需求:
//        在某个目录中找出所有的.txt文件
//        某个目录:C:\Users\Administrator\Desktop\temp\aaa
        File fileDir = new File("C:\\Users\\Administrator\\Desktop\\temp\\aa");
        //调用
        findTxtFile(fileDir);
    }

    //从指定的目录中搜索txt文件
    public static void findTxtFile(File file) {
        //1.列出该文件夹下所有的File对象
        File[] files = file.listFiles();
        //2.遍历列出的数组
        for (File f : files) {
            //3.判断是否为txt文件
            if (f.getName().endsWith(".txt") && f.isFile()) {
                System.out.println(f);
            }else if (f.isDirectory()){
                //那么列出这个f文件夹下的所有.txt文件即可
                findTxtFile(f); // 递归!!!
            }
        }
    }
}               

三,IO流

I: Input 输入流, 数据从外部设备到程序中,读数据的流
O: Output 输出流, 数据从程序到外部设备,写数据的流
流: 一种比喻,数据传输的过程比喻成流

分类

a.根据流的方向分类:
    输入流
    输出流
b.根据流中操作的数据类型分类:
    字节流 byte
    字符流 char  
以上两种分类我们可以综合一下:
    字节输入流
    字节输出流
        
    字符输入流
    字符输出流     

Java中的IO流

字节输入流: InputStream(顶层父类,抽象类)
    
字节输出流: OutputStream(顶层父类,抽象类)
    
字符输入流: Reader(顶层父类,抽象类)
    
字符输出流 :Writer(顶层父类,抽象类)   
    
技巧: Java中所有的流都会是以上四个流中某一个的子类
        而且具体的流的命名是非常有规范的!!
            规范: 功能名 +父类名
                
      比如:FileWriter 向文件中写出字符为单位的数据  
      比如:FileInputStream 从文件读取以字节为单位的数据   

1.字节流

输出流:

顶层父类: OutputStream(抽象类)
共性方法:
	public void close(); 关闭此流,释放资源
    public void flush(); 刷新缓冲区(目前没有!!)
       
    public void write(int b); //一次写一个字节  
	public void write(byte[] bs);//一次写一个字节数组
	public void write(byte[] bs,int startIndex,int len);//一次写一个字节数组的一部分

FileOutputStream类:文件的字节输出流(向文件中写字节数据的)

构造方法

public FileOutputStream(String path);//必须传入文件的路径
public FileOutputStream(File file);//必须传入文件的File对象

public class FileOutputStreamDemo03 {
    public static void main(String[] args) throws FileNotFoundException {
        //1.创建一个FileOutputStream
        FileOutputStream fos = new FileOutputStream("1.txt");
//        FileOutputStream fos = new FileOutputStream(new File("1.txt"));
        /**
         * 构造方法干了三件事!!!
         * a.创建对象fos
         * b.判断文件是否存在
         *      如果存在,会清空文件的内容
         *      如果不存在,会自动创建该文件
         * c.让对象fos和1.txt绑定     
         */
    }
}

 写字节流数据的三种方法

public class FileOutputStreamDemo02 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileOutputStream
        FileOutputStream fos = new FileOutputStream("1.txt");
        //2.向文件中写数据
        //a.写一个字节
        fos.write(97); // a
        //思考:我想要打开之后看到97,怎么办???
//        fos.write(57); // 9
//        fos.write(55); // 7
        //b.写一个字节数组
        byte[] bs = {97,98,99,100};
        fos.write(bs);
        //思考:我想要打开之后看到HelloWorldJavafghjktyuivnm
//        byte[] bs1 = "HelloWorldJavafghjktyuivnm".getBytes();
//        fos.write(bs1);
        //c.写一个字节数组的一部分
        byte[] bs2 = {97,98,99,100};
        fos.write(bs2,1,2);
    }
}

追加续写

只要使用以下构造即可
    public FileOutputStream(String path,boolean append);//append表示是否追加
	public FileOutputStream(File file,boolean append);//append表示是否追加

public class FileOutputStreamDemo03 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileOutputStream
        FileOutputStream fos = new FileOutputStream("1.txt",true);
        //2.写数据
        fos.write(97);
    }
}

如何换行

只要写文件中写一个代表换行的符号即可
    windows \r\n
    Linux   \n
    MacOS	\r   (MacOSX 也是 \n)

public class FileOutputStreamDemo04 {
    public static void main(String[] args) throws IOException {
        //1.创建一个FileOutputStream
        FileOutputStream fos = new FileOutputStream("1.txt");

        //2.写数据
        for (int i = 0; i < 10; i++) {
            fos.write("java\r\n".getBytes());
//            fos.write("\r\n".getBytes());
        }
    }
}    

close 和 flush

public void flush(); 目前我们没用!!(对于字节流输出流没用!!)
    
public void close(); 关闭流,释放资源
    流一旦使用完毕,及时释放资源,别的程序就可以使用该资源了!!!

字节输入流

顶层父类: InputStream(抽象类)
共性方法:
	public void close();// 关闭流,释放资源

	public int read(); //一次读一个字节
	public int read(byte[] bs);//一次读取一个字节数组,返回值表示实际读取的字节个数

FileInputStream类

文件的字节输入流(从文件中读取以字节为单位的数据)

public FileInputStream(String path);//传入文件的路径
public FileInputStream(File file);//传入文件的File对象

public class FileInputStreamDemo01 {
    public static void main(String[] args) throws Exception {
        //1.创建FileInputStream对象
        FileInputStream fis = new FileInputStream("1.txt");
//        FileInputStream fis = new FileInputStream(new File("1.txt"));
        /**
         * 以上构造方法干了三件事!!!
         * a.创建对象fis
         * b.判断文件是否存在
         *      如果存在,什么不干(不清空!!!)
         *      如果不存在,会直接抛出异常FileNotFoundException
         * c.让fis和1.txt绑定
         */
    }
}

读取一个字节

public class FileInputStreamDemo02 {
    public static void main(String[] args) throws Exception {
        //1.创建FileInputStream对象
        FileInputStream fis = new FileInputStream("1.txt");
        //2.读数据
        //a.一次读取一个字节
        //int b = fis.read();
        //System.out.println((char) b);
        //==============一次读取一个字节的标准循环代码==================
        int b = 0;//保存读取到字节
        /**
         * (b = fis.read()) != -1
         * 这句代码干了三件事!!!
         * a.先读  fis.read()
         * b.赋值  b = 读取字节
         * c.判断  b != -1
         */
        while ((b = fis.read()) != -1) {
            System.out.println((char) b);
        }
        //4.释放资源
        fis.close();
    }
}

读取一个字节数组

public class FileInputStreamDemo03 {
    public static void main(String[] args) throws Exception {
        //1.创建FileInputStream对象
        FileInputStream fis = new FileInputStream("1.txt");
        //2.读数据
        //b.一次读取一个字节数组
        //byte[] bs = new byte[4]; //实际开发中 一般1024 或者 其整数倍
        //int len = fis.read(bs);
        //System.out.println("实际读取到"+len+"个字节");
        //System.out.println(new String(bs,0,len));
        //===============一次读取一个字节数组的标准循环代码===============
        byte[] bs = new byte[4];
        int len = 0;
        /**
         * (len = fis.read(bs)) != -1
         * 以上代码干了三件事
         * a.先读  fis.read(bs)
         * b.赋值  len = 实际读取的个数
         * c.判断  len != -1
         */
        while ((len = fis.read(bs)) != -1) {
            System.out.println(new String(bs,0,len));
        }
        //3.释放资源
        fis.close();
    }
}

字节流练习:复制图片

public class CopyFileDemo {
    public static void main(String[] args) throws Exception {
        //复制文件
        //1.源文件G:\uplaod\1.png
        FileInputStream fis = new FileInputStream("G:\\upload\\1.png");
        //2.目标文件
        FileOutputStream fos = new FileOutputStream("copy.png");
        //3.复制文件(一次赋值一个字节数组)
        byte[] bs = new byte[1024]; // 1KB
        int len = 0;
        while ((len = fis.read(bs)) != -1) {
            fos.write(bs,0,len); // 为了防止最后一次读取时 写入多余的数据
        }
        //4.释放资源(先开后关)
        fos.close();
        fis.close();
    }
}

一个一个字节复制,一个一个字节数组复制

一次读取一个字节数组的底层原理

发布了117 篇原创文章 · 获赞 20 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u010581811/article/details/104998652
今日推荐