打怪升级之小白的大数据之旅(二十三)<Java面向对象进阶之IO流一 概述>

打怪升级之小白的大数据之旅(二十三)

Java面向对象进阶之IO流的概述

上次回顾

上一章,我们学习了泛型,所谓泛型就是对我们对将来未知的情况做一个限制,提高了代码的安全性同时,也简化了代码量,之前我们的程序都是在本机上进行编码,当我们关闭程序或者关机后,本次程序的运行结果就随之消失了,因此本章我将为大家带来IO流,让我们可以对数据进行持久化存储,IO内容比较多,我用三章进行讲解哈…

File类与IO流

讲到IO流之前,我们首先要提一下File类,有了它,才能进行IO的操作

File类(java.io.File)

概述

  • File类是java.io包下代表与平台无关的文件和目录
  • 通俗一点的来说,File类就是操作我们系统中的文件和文件夹的
  • File类可以对文件和目录进行新建、删除、重命名等操作
  • 在现实中,我们创建了文件夹/文件后,主要目的就是对文件中的内容进行操作,但是File类并不能这样做,因为它仅仅只是对文件/文件夹进行操作,
  • 这就相当于一个解耦操作,File只是对文件/文件夹操作,IO专门针对文件内容本身操作

File类的路径

  • 介绍File类,就不得不提一个知识点:路径,在API中File的解释是文件和目录路径名的抽象表示形式,即File类是文件或目录的路径
  • File类可以使用文件路径字符串来创建File实例,该文件路径字符串既可以是绝对路径,也可以是相对路径
  • 默认情况下,系统总是依据用户的工作路径来解释相对路径,这个路径由系统属性“user.dir”指定,通常也就是运行Java虚拟机时所作的路径
  • 绝对路径:从盘符开始的路径,这是一个完整的路径。
  • 相对路径:相对于项目目录的路径,这是一个便捷的路径,开发中经常使用。
  • 规范路径:所谓规范路径名,即对路径中的“…”等进行解析后的路径名

File类与IO的关系

在这里插入图片描述
在图中,File对象就好比是到水库的地址路线
要存取里面的水到家中,就需要管道(IO)

构造方法

  • public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
  • public File(String parent, String child) :从父路径名字符串和子路径名字符串创建新的 File实例。
  • public File(File parent, String child) :从父抽象路径名和子路径名字符串创建新的 File实例。
  • 示例代码:
    // 文件路径名
    String pathname = "D:\\aaa.txt";
    File file1 = new File(pathname); 
    
    // 文件路径名
    String pathname2 = "D:\\aaa\\bbb.txt";
    File file2 = new File(pathname2); 
    
    // 通过父路径和子路径字符串
     String parent = "d:\\aaa";
     String child = "bbb.txt";
     File file3 = new File(parent, child);
    
    // 通过父级File对象和子路径字符串
    File parentDir = new File("d:\\aaa");
    String child = "bbb.txt";
    File file4 = new File(parentDir, child);
    
  • 注:
    • 一个FIle对象代表硬盘中实际存在的一个文件或目录
    • 无论该路径下是否存在该文件或目录,都不影响File对象的创建

常用方法

获取文件和目录的基本信息
  • public String getName() :返回由此File表示的文件或目录的名称。
  • public long length() :返回由此File表示的文件的长度。
  • public String getPath() :将此File转换为路径名字符串。
  • public long lastModified():返回File对象对应的文件或目录的最后修改时间(毫秒值)
  • 示例代码:
    import java.io.File;
    import java.time.Instant;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    
    public class TestFile {
        public static void main(String[] args) {
            File f = new File("d:/aaa/bbb.txt");     
            System.out.println("文件构造路径:"+f.getPath());
            System.out.println("文件名称:"+f.getName());
            System.out.println("文件长度:"+f.length()+"字节");
            System.out.println("文件最后修改时间:" + LocalDateTime.ofInstant(Instant.ofEpochMilli(f.lastModified()),ZoneId.of("Asia/Shanghai")));
    
            File f2 = new File("d:/aaa");     
            System.out.println("目录构造路径:"+f2.getPath());
            System.out.println("目录名称:"+f2.getName());
            System.out.println("目录长度:"+f2.length()+"字节");
            System.out.println("文件最后修改时间:" + LocalDateTime.ofInstant(Instant.ofEpochMilli(f.lastModified()),ZoneId.of("Asia/Shanghai")));
        }
    }
    
各种路径的相关操作
  • 前面已经介绍了什么是路径,接下来,就为大家带来File对路径操作的相关方法
  • public String getPath() :将此File转换为路径名字符串。
  • public String getAbsolutePath() :返回此File的绝对路径名字符串。
  • String getCanonicalPath():返回此File对象所对应的规范路径名。
  • 示例代码:
    @Test
    	public void test1() throws IOException{
    		File f1 = new File("d:\\test\\javase\\HelloIO.java");
    		System.out.println("文件/目录的名称:" + f1.getName());
    		System.out.println("文件/目录的构造路径名:" + f1.getPath());
    		System.out.println("文件/目录的绝对路径名:" + f1.getAbsolutePath());
    		System.out.println("文件/目录的规范路径名:" + f1.getCanonicalPath());
    		System.out.println("文件/目录的父目录名:" + f1.getParent());
    	}
    	@Test
    	public void test2() throws IOException{
    		File f2 = new File("HelloIO.java");
    		System.out.println("user.dir =" + System.getProperty("user.dir"));
    		System.out.println("文件/目录的名称:" + f2.getName());
    		System.out.println("文件/目录的构造路径名:" + f2.getPath());
    		System.out.println("文件/目录的绝对路径名:" + f2.getAbsolutePath());
    		System.out.println("文件/目录的规范路径名:" + f2.getCanonicalPath());
    		System.out.println("文件/目录的父目录名:" + f2.getParent());
    	}
    		@Test
    	public void test3() throws IOException{
    		File f3 = new File("../../HelloIO.java");
    		System.out.println("user.dir =" + System.getProperty("user.dir"));
    		System.out.println("文件/目录的名称:" + f3.getName());
    		System.out.println("文件/目录的构造路径名:" + f3.getPath());
    		System.out.println("文件/目录的绝对路径名:" + f3.getAbsolutePath());
    		System.out.println("文件/目录的规范路径名:" + f3.getCanonicalPath());
    		System.out.println("文件/目录的父目录名:" + f3.getParent());
    	}
    
  • 在Window中,它的路径是\,而在java中\是转义字符,因此,它的路径应该是\\
  • 把构造File对象指定的文件或目录的路径名,称为构造路径,它可以是绝对路径,也可以是相对路径
  • 当构造路径是绝对路径时,那么getPath和getAbsolutePath结果一样
  • 当构造路径是相对路径时,那么getAbsolutePath的路径 = user.dir的路径 + 构造路径
  • 当路径中不包含"…“和”/开头"等形式的路径,那么规范路径和绝对路径一样,否则会将…等进行解析。路径中如果出现“…”表示上一级目录,路径名如果以“/”开头,表示从“根目录”下开始导航
判断功能的方法
  • public boolean exists() :此File表示的文件或目录是否实际存在。
  • public boolean isDirectory() :此File表示的是否为目录。
  • public boolean isFile() :此File表示的是否为文件。
  • 示例代码:
    public class FileIs {
           public static void main(String[] args) {
               File f = new File("d:\\aaa\\bbb.java");
               File f2 = new File("d:\\aaa");
             	// 判断是否存在
               System.out.println("d:\\aaa\\bbb.java 是否存在:"+f.exists());
               System.out.println("d:\\aaa 是否存在:"+f2.exists());
             	// 判断是文件还是目录
               System.out.println("d:\\aaa 文件?:"+f2.isFile());
               System.out.println("d:\\aaa 目录?:"+f2.isDirectory());
           }
       }
    
  • 如果文件或目录存在,那么exists()、isFile()和isDirectory()都是返回true
创建与删除
  • public boolean createNewFile():当且仅当具有该名称的文件尚不存在时,创建一个新的空文件。
  • public boolean delete() :删除由此File表示的文件或目录。 只能删除空目录。
  • public boolean mkdir() :创建由此File表示的目录。
  • public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录
  • 示例代码:
    public class FileCreateDelete {
        public static void main(String[] args) throws IOException {
            // 文件的创建
            File f = new File("aaa.txt");
            System.out.println("是否存在:"+f.exists()); // false
            System.out.println("是否创建:"+f.createNewFile()); // true
            System.out.println("是否存在:"+f.exists()); // true
    		
         	// 目录的创建
          	File f2= new File("newDir");	
            System.out.println("是否存在:"+f2.exists());// false
            System.out.println("是否创建:"+f2.mkdir());	// true
            System.out.println("是否存在:"+f2.exists());// true
    
    		// 创建多级目录
          	File f3= new File("newDira\\newDirb");
            System.out.println(f3.mkdir());// false
            File f4= new File("newDira\\newDirb");
            System.out.println(f4.mkdirs());// true
          
          	// 文件的删除
           	System.out.println(f.delete());// true
          
          	// 目录的删除
            System.out.println(f2.delete());// true
            System.out.println(f4.delete());// false
        }
    }
    
  • 注:delete方法,如果此File表示目录,则目录必须为空才能删除
目录操作
  • public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。

  • public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。

  • public File[] listFiles(FileFilter filter):返回所有满足指定过滤器的文件和目录。如果给定 filter 为 null,则接受所有路径名。否则,当且仅当在路径名上调用过滤器的 FileFilter.accept(java.io.File) 方法返回 true 时,该路径名才满足过滤器。如果当前File对象不表示一个目录,或者发生 I/O 错误,则返回 null

  • 示例代码一:递归打印多级目录

    @Test
       	public void test3() {
       		 File dir = new File("d:/目录名称");
       		 listSubFiles(dir);
       	}
       
       	public void listSubFiles(File dir) {
       		if (dir != null && dir.isDirectory()) {
       			File[] listFiles = dir.listFiles();
       			if (listFiles != null) {
       				for (File sub : listFiles) {
       					listSubFiles(sub);//递归调用
       				}
       			}
       		}
       		System.out.println(dir);
       	}
    
  • 示例代码二:递归打印某目录下(包括子目录)中所有满足条件的文件

    Test
       	public void test5() {
       		 File dir = new File("D:/目录名称");
       		 listByFileFilter(dir);
       	}
       	
       	public void listByFileFilter(File file) {
       		if (file != null && file.isDirectory()) {
       			File[] listFiles = file.listFiles(new FilenameFilter() {
       
       				@Override
       				public boolean accept(File dir, String name) {
       					return name.endsWith(".java") || new File(dir,name).isDirectory();
       				}
       			});
       			if (listFiles != null) {
       				for (File sub : listFiles) {
       					if(sub.isFile()){
       						System.out.println(sub);
       					}
       					listByFileFilter(sub);
       				}
       			}
       		}
       	}
    
  • 示例代码三:递归求目录总大小

    @Test
       	public void test4() {
       		 File dir = new File("D:/目录名称");
       		 long length = getLength(dir);
       		 System.out.println("大小:" + length);
       	}
       	
       	public long getLength(File dir){
       		if (dir != null && dir.isDirectory()) {
       			File[] listFiles = dir.listFiles();
       			if(listFiles!=null){
       				long sum = 0;
       				for (File sub : listFiles) {
       					sum += getLength(sub);
       				}
       				return sum;
       			}
       		}else if(dir != null && dir.isFile()){
       			return dir.length();
       		}
       		return 0;
       	}
    
  • 示例代码四:递归删除非空目录,如果目录非空,连同目录下的文件和文件夹一起删除

    	@Test
       	public void test6() {
       		 File dir = new File("D:/atguigu/javase");
       		 forceDeleteDir(dir);
       	}
       	public void forceDeleteDir(File dir) {
       		if (dir != null && dir.isDirectory()) {
       			File[] listFiles = dir.listFiles();
       			if(listFiles!=null){
       				for (File sub : listFiles) {
       					forceDeleteDir(sub);
       				}
       			}
       		}
       		dir.delete();
       	}
    

IO流

  • 在开篇介绍File与IO关系那幅图中,已经告诉大家了,IO流就是存取文件数据的管道

概述

  • 我们可以把数据传输看做是一种数据的流动,按照流动的方向,以内存为基准,这个管道的流动方向就分为输入Input和Output,数据流向内存的就是输入流,流出内存的就是输出流
  • Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据

IO的分类

根据数据的流向分为:输入流和输出流。

  • 输入流 :把数据从其他设备上读取到内存中的流。
    • 以InputStream,Reader结尾
  • 输出流 :把数据从内存 中写出到其他设备上的流。
    • 以OutputStream、Writer结尾

根据数据的类型分为:字节流和字符流。

  • 字节流 :以字节为单位,读写数据的流。
    • 以InputStream和OutputStream结尾
  • 字符流 :以字符为单位,读写数据的流。
    • 以Reader和Writer结尾

根据IO流的角色不同分为:节点流和处理流。

  • 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader.
  • 处理流:是对一个已存在的流进行连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接

常用的节点流:

  • 文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流。
  • 字符串 StringReader StringWriter 对字符串进行处理的节点流。
  • 数 组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)。
  • 管 道 PipedInputStream、PipedOutputStream、PipedReader、PipedWriter对管道进行处理的节点流。

常用处理流:

  • 缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter—增加缓冲功能,避免频繁读写硬盘。
  • 转换流:InputStreamReader、OutputStreamReader—实现字节流和字符流之间的转换。
  • 数据流:DataInputStream、DataOutputStream -提供读写Java基础数据类型功能
  • 对象流:ObjectInputStream、ObjectOutputStream–提供直接读写Java对象功能

IO的基类

就如同前面我们学习集合一样,IO也是有基类的,如下:

数据类型/数据流向输入流输出流
字节流字节输入流InputStream字节输出流OutputStream
字符流字符输入流Reader字符输出流Writer
  • 下一章,我会对会用到的几个流进行讲解,在后面的示例代码中因为IO操作需要进行异常捕获,举例比较麻烦,所以后面的示例我全部主动抛出异常,我会单独举例如何使用异常捕获来完成示例

总结

  • 本章,我们学习了File类与IO流中的字符流,一句话来总结今天的内容:File类用于定位文件位置,然后使用IO对文件中的数据进行增删改查操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值