一、IO流概要

1.概念

开发中经常要进行输入输出操作,掌握Java中的IO流显得非常必要。

流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。

一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。

流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。

实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。

形象的比喻——水流 ,文件======程序,文件和程序之间连接一个管道,水流就在之间形成了,自然也就出现了方向:可以流进,也可以流出。便于理解,这么定义流: 流就是一个管道里面有流水,这个管道连接了文件和程序。

Java流操作有关的类或接口:

 

 

 

 Java IO流的结构图:

 

 

 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

2.IO流的分类

根据处理数据类型的不同分为:字符流和字节流

根据数据流向不同分为:输入流和输出流

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

输入流和输出流

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。

 

 

 

 二、File类

1.简介

File类是io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建、删除、重命名文件等。File类的对象主要用来获取文件本身的一些信息,如文件所在目录、文件的长度、文件读写权限等。数据流可以将数据写入到文件中,而文件也是数据流最常用的数据媒体。

提供定位本地文件系统、描述文件和目录的功能

是 java.io 包中引用实际磁盘文件的唯一对象

File类对象描述文件路径、名字、长度、可否读写等属性,可用来命名文件、查询文件属性和处理目录,但不读写文件。

解决程序与文件系统的沟通

各种文件系统提供的基本服务一样,但实现细节互不兼容

构造函数

File(String pathname);
File(String dir, String subpath);
File(File dir, String subpath);

 

File(String path)
文件(相对路径),移植性较好: File f1 = new File(“mydir\\myfile.txt”);
目录(绝对路径): File f2 = new File(“d:\\mydir\\dir1”);
File(String parent, String child )
文件路径以及文件名: File f3 = new File(“d:\\d1” , “a.java”)
File(File dir, String name)
文件对象与文件名:File f4 = new File(f2 , “myfile.txt”);

 

常用方法
canRead()、canWrite()、delete()、equals(object)、exists() getAbsolutePath() 和 length()

 

方法 描述
String   getName() 获取文件的名称
boolean  canRead() 判断文件是否是可读的
boolean  canWrite() 品判断文件是否可被写入
boolean  exits() 判断文件长度是否存在
int  length() 获取文件的长度(以字节为单位)
String  getAbsolutePath() 获取文件的绝对路径
String  getParent() 获取文件的父路径
boolean  isFile() 判断此抽象路径名表示的文件是否为普通文件
boolean  isDirectory() 判断此抽象路径名表示的是否是一个目录
boolean  isHidden 判断文件是否是隐藏文件
long  lastModified() 获取文件最后修改时间
Boolean  canExecute()
测试应用程序是否可以执行此抽象路径名表示的文件。 
boolean  createNewFile() 当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。
boolean  delete() 删除由此抽象路径名表示的文件或目录。
File[]  listFiles()  返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。
String[]  list() 返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。
boolean  mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。可创建多层文件包
boolean  mkdir() 创建由此抽象路径名命名的目录。只能创建一层文件包
boolean  reNameTo(File dest) 重命名由此抽象路径名表示的文件。
boolean  setReadOnly()
标记由此抽象路径名命名的文件或目录,以便只允许读取操作。 
boolean  setWritable(boolean  writable)
一种方便的方法来设置所有者对此抽象路径名的写入权限。

2.文件操作示例

创建与删除文件

public static void main(String[] args) throws IOException {
        File file = new File("e:"+File.separator,"file1.txt");
        if(file.exists()) {
            file.delete();
            System.out.println("删除成功");
        }else {
            file.createNewFile();
            System.out.println("创建成功");
        }
    }

 

基本操作:

public static void main(String[] args) throws IOException {
        File file = new File("E:\\IOTestDemo.txt");
        System.out.println("创建成功了吗?"+file.createNewFile());
        System.out.println("单级文件夹创建成功了吗?"+file.mkdir());
        System.out.println("多级文件夹创建成功了吗?"+file.mkdirs());
        File dest = new File("F:\\电影\\c.txt");
        System.out.println("重命名成功了吗?"+file.renameTo(dest));
        
        System.out.println("********************");
        
        System.out.println("文件或者文件夹存在吗?"+file.exists());
        System.out.println("是一个文件吗?"+file.isFile());
        System.out.println("是一个文件夹吗?"+file.isDirectory());
        System.out.println("是隐藏文件吗?"+file.isHidden());
        System.out.println("此路径是绝对路径名?"+file.isAbsolute());
        System.out.println("********************");
        System.out.println("文件或者文件夹的名称是:"+file.getName());
        System.out.println("相对路径是:"+file.getPath());
        System.out.println("绝对路径是是:"+file.getAbsolutePath());
        System.out.println("文件大小是(以字节为单位):"+file.length());
        System.out.println("文件父路径是:"+file.getParent());
        //使用日期类与日期格式化类进行获取规定的时间
        long lastModified = file.lastModified();
        Date date = new Date(lastModified);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YY年MM月DD日 HH:mm:ss");
        System.out.println("最后一次修改的时间是:"+simpleDateFormat.format(date));
        System.out.println("***********************");
        //文件或者文件夹的方法
        File[] files = File.listRoots();
        System.out.println("所有的盘符是:");
        for (File item : files) {
            System.out.println("\t"+item);
        }
        File file2 = new File("F:\\mongoDB");
        String[] list = file2.list();
        System.out.println("指定文件夹下的文件或者文件夹有:");
        for (String item : list) {
            System.out.println("\t"+item);
        }
        File[] f = file2.listFiles();
        System.out.println("获得该路径下的文件或文件夹是:");
        for(File item : f){
            System.out.println("\t"+item.getName());
            }
    }
打印输出:
创建成功了吗?false
单级文件夹创建成功了吗?false
多级文件夹创建成功了吗?false
重命名成功了吗?false
********************
文件或者文件夹存在吗?true
是一个文件吗?true
是一个文件夹吗?false
是隐藏文件吗?false
此路径是绝对路径名?true
********************
文件或者文件夹的名称是:IOTestDemo.txt
相对路径是:E:\IOTestDemo.txt
绝对路径是是:E:\IOTestDemo.txt
文件大小是(以字节为单位):0
文件父路径是:E:\
最后一次修改的时间是:21年01月07日 14:51:43
***********************
所有的盘符是:
    C:\
    E:\
    F:\
指定文件夹下的文件或者文件夹有:
    data
    log
    mongodb.config
获得该路径下的文件或文件夹是:
    data
    log
    mongodb.config

递归获得所有文件与文件夹:

public static void main(String[] args) {
        File file = new File("E:\\360安全浏览器下载");
        ListFile(file);
    }
    
    public static void ListFile(File f) {
        if(f.isDirectory()) {
            //获取当前文件夹下的所有的文件
            File[] listFiles = f.listFiles();
            System.out.println(f.getPath()+"下的文件是:");
            for (File file : listFiles) {
                System.out.println("\t"+file.getName());
                ListFile(file);
            }
        }
    }
    
打印输出:
E:\360安全浏览器下载下的文件是:
    200_m光纤氘气处理工艺的优化_刘晓玮.caj
    CAJViewer_7.2.113.0.exe
    CN107445470A.caj
    CN108793724A.caj
    CN108873156A.caj
    defrag.dat
    G.657光纤的弯曲损耗性能及机械可靠性1.pdf
    G652_D光纤在长波段的传输损耗研究_秦钰.caj
    G652光纤喇曼增益谱的实验研究.pdf
    pdf转word---点右边的(下载19.1M).zip
    SFF-03-J-生产科-814 NEXTROM筛选作业标准.doc

 

 

三、字节流操作

字节流和字符流的区别:

  • 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
  • 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

1.字节输出流

输出字节流OutputStream

IO 中输出字节流的继承图可见上图,可以看出:

OutputStream 是所有的输出字节流的父类,它是一个抽象类。

ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。

字节输出流的常用方法:

 

 示例1:

public static void main(String[] args) throws IOException {
        File file = new File("E:\\streamTest.txt");//声明file对象
        OutputStream out = null;//声明输出流的对象
        out = new FileOutputStream(file);//实例化
        String str = "hello world,my friends  ";
        byte[] bytes = str.getBytes();//字符串转换成字节数组
        out.write(bytes);//执行写操作
        out.close();//关闭流对象
        
        //创建html文件示例
        File file2 = new File("E:\\streamTest.html");//声明file对象
        OutputStream out2 = null;//声明输出流的对象
        out2 = new FileOutputStream(file2);//实例化
        String str2 = "<marquee><h1>Hello OutputStream!</h1></marquee>";
        out2.write(str2.getBytes());
        out2.close();
    }

 

结果:

 

 2.字节输入流

InputStream 是所有的输入字节流的父类,它是一个抽象类。

ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。

ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。

字节输入流的常用方法:

 

 示例:

public static void main(String[] args) throws IOException {
        File file = new File("E:\\\\streamTest.txt");
        InputStream in = null;
        in = new FileInputStream(file);
        //声明一个byte数组,将FileInputStream的流放入其中,类似于缓存作用
        //byte数组可以自己指定大小,也可以根据文件大小指定,byte[1024]
        byte[] b = new byte[(int)file.length()];
        in.read(b);//执行读的方法,将数据读到内存中
        in.close();//关闭流
        System.out.println("类容为:"+new String(b));//将byte数组转换成字符串输出
    }

打印输出:
类容为:hello world,my friends  
hello world,my friends  
hello world,my friends  hello world,my friends  hello world,my friends  
hello world,my friends  hello world,my friends  hello world,my friends  

 

 

四、字符流操作

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 

程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

1、字符输出流

在Java中IO操作也是有相应步骤的,以文件操作为例,主要的操作流程如下:

1 使用File类打开一个文件

2 通过字节流或字符流的子类,指定输出的位置

3 进行读/写操作

4 关闭输入/输出

IO操作属于资源操作,一定要记得关闭

输出流: OutputStream 写出 就是将数据从程序写入到外部文件。

对应 Writer;

public static void main(String[] args) throws IOException {
        File file = new File("E:\\StringTest.txt");
        Writer writer = null;
        writer = new FileWriter(file);
        String str = "hello world";
        writer.write(str);
        writer.flush();
        writer.close();
    }

 

2、字符流输入

输入流:InputStream 读入 就是从外部文件中读取数据到程序。

对应 Reader;

public static void main(String[] args) throws IOException {
        File file = new File("E:\\StringTest.txt");
        Reader reader = null;
        reader = new FileReader(file);
        char[] c = new char[(int)file.length()];
        reader.read(c);
        System.out.println("内容为:"+new String(c));
    }

 

posted on 2021-01-07 08:46  二十二画生的执著  阅读(82)  评论(0编辑  收藏  举报