IO流

文章目录

  • 1. Java流操作有关的类或接口
  • 2.流的概念和作用
    • IO流的分类
  • 3.File类
    • 1. File 类的概述和构造方法
    • 2. File 类的创建功能
    • 3.File类的删除功能
    • 4.File类的判断功能
    • 5.File类的重命名功能
    • 6.File 类的基本获取功能
    • 7.File类的高级获取功能
  • 4.Java IO流对象
  • 5.输出字节流OutputStream
    • 1. 字节流的输入流(InputStream)
    • 2. 字节流的输出流(OutputStream)
  • 6.字符输入流Reader
  • 7.字符输出流Writer
  • 8.字符流与字节流转换
  • 10..RandomAccessFile类

1. Java流操作有关的类或接口

IO流_第1张图片

  1. InputStream/OutputStream
    字节流的抽象类。
  2. Reader/Writer
    字符流的抽象类。
  3. FileInputStream/FileOutputStream
    节点流:以字节为单位直接操作“文件”。
  4. ByteArrayInputStream/ByteArrayOutputStream
    节点流:以字节为单位直接操作“字节数组对象”。
  5. ObjectInputStream/ObjectOutputStream
    处理流:以字节为单位直接操作“对象”。
  6. DataInputStream/DataOutputStream
    处理流:以字节为单位直接操作“基本数据类型与字符串类型”。
  7. FileReader/FileWriter
    节点流:以字符为单位直接操作“文本文件”(注意:只能读写文本文件)。
  8. BufferedReader/BufferedWriter
    处理流:将Reader/Writer对象进行包装,增加缓存功能,提高读写效率。
  9. BufferedInputStream/BufferedOutputStream
    处理流:将InputStream/OutputStream对象进行包装,增加缓存功能,提高 读写效率。
  10. InputStreamReader/OutputStreamWriter
    处理流:将字节流对象转化成字符流对象。
  11. PrintStream
    处理流:将OutputStream进行包装,可以方便地输出字符,更加灵活。

2.流的概念和作用

流是一个抽象、动态的概念,是一连串连续动态的数据集合。
对于输入流而言,数据源就像水箱,流(stream)就像水管中流动着的水流,程序就是我们最终的用户。我们通过流(A Stream)将数据源(Source)中的数据(information)输送到程序(Program)中。
对于输出流而言,目标数据源就是目的地(dest),我们通过流(A Stream)将程序(Program)中的数据(information)输送到目的数据源(dest)中。
IO流_第2张图片
输入/输出流的划分是相对程序而言的,并不是相对数据源。

IO流的分类

1.按流的方向分类:

  1. 输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。
  2. 输出流:数据流向是程序到目的地(以OutPutStream、Writer结尾的流)。
    IO流_第3张图片
  3. 按处理的数据单元分类:
    1. 字节流:以字节为单位获取数据,命名上以Stream结尾的流一般是字节流,如FileInputStream、FileOutputStream。
    2. 字符流:以字符为单位获取数据,命名上以Reader/Writer结尾的流一般是字符流,如FileReader、FileWriter。
    3. 按处理对象不同分类:
      1. 节点流:可以直接从数据源或目的地读写数据,如FileInputStream、FileReader、DataInputStream等。
      2. 处理流:不直接连接到数据源或目的地,是”处理流的流”。通过对其他流的处理提高程序的性能,如BufferedInputStream、BufferedReader等。处理流也叫包装流。

节点流处于IO操作的第一线,所有操作必须通过它们进行;处理流可以对节点流进行包装,提高性能或提高程序的灵活性
IO流_第4张图片

3.File类

File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

1. File 类的概述和构造方法

要想实现IO的操作,就必须知道硬盘上文件的表现形式,而java中就提供了一个File类。
构造方法:

public File(String pathname):根据一个路径得到一个File对象
File(String parent, String child) : 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(File parent, String child) : 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
方式一:File file1 = new File(“e:\\demo\\test.txt”);
方式二:File file2 = new File(“e:\\demo”,”test.txt”);
方式三:File file3 = new File(“e:\\demo”);
File file4 = new File(file3,”test.txt”);

注意:以上三种方式其实效果一样

2. File 类的创建功能

创建功能: boolean mkdir():创建文件夹,如果存在此文件夹,则不创建,返回结果为falseboolean createNewFile():创建文件,如果此文件存在,则不创建,返回结果为false;
注意:如果需要在某个文件夹下创建文件,则此文件依赖的文件夹必须存在,否则会出现IO异常,系统找不到指定路径。
如果创建文件或文件夹时忘记写盘符路径,默认在项目路径下。
boolean mkdirs():用于创建文件夹,如果父文件夹不存在时,其可以自动创建父文件夹,即用于创建多级文件的。
例如: 
File file = new File(“e:\\test\\test.txt”);
System.out.println(“mkdir:+file.mkdirs());
以上两行代码执行正确。

3.File类的删除功能

public boolean delete();此方法可以删除文件或文件夹。
注意:java中的删除不走回收站;
被删除文件夹中不能包含子文件或文件夹

4.File类的判断功能

public boolean isDirectory();判断是否是目录
public boolean isFile();判断是否是文件
public boolean exists();判断是否存在
public boolean canWrite();判断是否可写
public boolean canRead();判断是否可读
public boolean isHidden();判断是否隐藏

5.File类的重命名功能

public boolean renameTo(File file);
如果路径名相同,改名,如果路径名不同,相当于改名并剪切
注意:路径以盘符开始:绝对路径
路径不以盘符开始:相对路径
需求:使用程序修改某个文件的名称。

File file = new File(“xxx.txt”);
File newFile = new File(“test.txt”);
System.out.println(“renameTo:”+ file.renameTo(newFile));
File file2 = new File(“xxx.txt”);
File newFile2 = new File(“e:\\test.txt”);
System.out.println(“renameTo:”+ file2.renameTo(newFile2));

6.File 类的基本获取功能

获取功能:

public String getAbsolutePath();获取绝对路径
public String getPath();获取相对路径
public String getName();获取名称
public long length();获取长度,字节数
public long lastModified();获取最后一次的修改时间,毫秒值

7.File类的高级获取功能

public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
public file[] listFiles(): 获取指定目录下的所有文件或者文件夹的File数组

4.Java IO流对象

  1. 输入字节流InputStreamio 中输入字节流的继承图可见上图,可以看出:

InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、StringBufferInputStream、FileInputStream
是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream
是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。 ObjectInputStream
和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
为了保证出现异常后流的正常关闭,通常要将流的关闭语句要放到finally语句块中,并且要判断流是不是null

5.输出字节流OutputStream

OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte
数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据, ObjectOutputStream
和所有FilterOutputStream 的子类都是装饰流。
3.字节流的输入与输出的对应

1. 字节流的输入流(InputStream)

IO流_第5张图片

构造方法: FileInputStream​(File file) FileInputStream​(String name) 成员方法:
int read​()从该输入流读取一个字节的数据。 int
read​(byte[]b)从该输入流读取最多b.length个字节的数据到一个字节数组。 int
read​(byte[]b,intoff,intlen)从该输入流读取最多len个字节的数据到字节数组。

 //需求:使用字节输入流将文件中的内容读取并在控制台输出     
 //目标文件对象
        File file = new File("d:\\test.txt");
//        //创建输入流对象
        FileInputStream fis=new FileInputStream(file);
        //
//        FileInputStream fis =new FileInputStream("d:\\test.txt");
        byte [] b =new byte[(int)file.length()];
        //读取内容
        System.out.println( fis.read(b));
        for (int i=0;i<b.length;i++){
     
            System.out.print((char)b[i]);
        }
        //释放资源
        fis.close();
    }

2. 字节流的输出流(OutputStream)

IO流_第6张图片

FileOutputStream 的构造方法

public FileOutputSteam(File file);

public FileOutputSteam(String name);

public FileOutputSteam(String name,boolean append);

成员方法:

void write​(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。

void write​(byte[] b, int off, int len) 从指定的字节数组写入 len字节,从偏移量
off开始输出到此输出流。

void write​(int b) 将指定的字节写入此输出流。

void close​() 关闭此输出流并释放与此流相关联的任何系统资源。

//指定输出内容的文件
//        File file = new File("d:\\test.txt");
        //创建输出流的对象
//        OutputStream os=new FileOutputStream(file);
        /**
         * A;创建File对象
         * B:新建文件
         * C:写出内容
         */
        OutputStream os =new FileOutputStream("d:\\test.txt");
        //准备输出的内容
        String str = "Hello io";
        //将输出内容按字节方式进行输出
//        os.write(str.getBytes());
        os.write(str.getBytes(),0,4);//0表示起始
        os.close();

6.字符输入流Reader

在上面的继承关系图中可以看出:
Reader 是所有的输入字符流的父类,它是一个抽象类。
CharReader、StringReader是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。
BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
FilterReader是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。
FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader的方法。我们可以从这个类中得到一定的技巧。
Reader 中各个类的用途和使用方法基本和InputStream中的类使用一致。后面会有Reader 与InputStream 的对应关系。

基类:Reader 抽象类

子类:InputStreamReder

构造方法:

按系统默认字符集进行文件内容的读取

InputStreamReader​(InputStream in) 创建一个使用默认字符集的InputStreamReader。

按指定字符集进行文件内容的读取

InputStreamReader​(InputStream in, String charsetName) 创建一个使用命名字符集的
 File file =new File("d:\\\\test.txt");
	        //构造InputStream对象
	        InputStream is  = new FileInputStream("d:\\\\test.txt");
	        //创建字符输入流对象
	        InputStreamReader isr= new InputStreamReader(is);
	        //读取内容
	//        int b = -1;
	//        while ((b=isr.read())!=-1){
     
	//            System.out.print((char)b);
	//        }
	        //创建存储的缓冲区
	        char [] chs = new char [(int)file.length()];
	        //将文件内容读取到缓冲区chs
	        isr.read(chs);
	        for (char c:chs
	             ) {
     
	            System.out.print(c);
	        }
	        //释放资源
	        isr.close();
	        is.close();

7.字符输出流Writer

在上面的关系图中可以看出:

Writer 是所有的输出字符流的父类,它是一个抽象类。 CharArrayWriter、StringWriter
是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,
BufferedWriter 是一个装饰器为Writer 提供缓冲功能。 PrintWriter 和PrintStream
极其类似,功能和使用也非常相似。

OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。
字符输出流:Writer抽象类

子类:OutputStreamWriter
构造方法
OutputStreamWriter​(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter​(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。
成员方法:
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write​(int c) 写一个字符
void write​(String str, int off, int len) 写一个字符串的一部分
//创建字符输出流对象,并指定转储文件
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\\\pet.template"),"utf-8");
        String info = "您好,我的名字是{name},我是一只{type},我的主人{master}";
        //写出操作
        osw.write(info);
        osw.close();

FileWriter:字符输出流的便捷类,也是OutputStreamWriter的子类

构造方法:
FileWriter​(File file) 给一个File对象构造一个FileWriter对象。
FileWriter​(File file, boolean append) 给一个File对象构造一个FileWriter对象。
FileWriter​(String fileName) 构造一个给定文件名的FileWriter对象。
FileWriter​(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
成员方法:
public void flush();
public void close();
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write​(int c) 写一个字符
void write​(String str, int off, int len) 写一个字符串的一部分

IO流_第7张图片

8.字符流与字节流转换

转换流的特点:

  • 其是字符流和字节流之间的桥梁
  • 可对读取到的字节数据经过指定编码转换成字符
  • 可对读取到的字符数据经过指定编码转换成字节

何时使用转换流?

  • 当字节和字符之间有转换动作时;
  • 流操作的数据需要编码或解码时。

具体的对象体现:

  • InputStreamReader:字节到字符的桥梁
  • OutputStreamWriter:字符到字节的桥梁
  • 这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

10…RandomAccessFile类

该对象并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。 该对象特点:

  • 该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。
  • 该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)

注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。
可以用于多线程下载或多个线程同时写数据到文件。

经典代码:
1.使用流读取文件内容(经典代码,一定要掌握)
import java.io.*;
public class TestIO2 {
     
    public static void main(String[] args) {
     
        FileInputStream fis = null;
        try {
     
            fis = new FileInputStream("d:/a.txt"); // 内容是:abc
            StringBuilder sb = new StringBuilder();
            int temp = 0;
            //当temp等于-1时,表示已经到了文件结尾,停止读取
            while ((temp = fis.read()) != -1) {
     
                sb.append((char) temp);
            }
            System.out.println(sb);
        } catch (Exception e) {
     
            e.printStackTrace();
        } finally {
     
            try {
     
                //这种写法,保证了即使遇到异常情况,也会关闭流对象。
                if (fis != null) {
     
                    fis.close();
                }
            } catch (IOException e) {
     
                e.printStackTrace();
            }
        }
    }
}
为了保证出现异常后流的正常关闭,通常要将流的关闭语句要放到finally语句块中,并且要判断流是不是null。
2.利用文件流实现文件的复制
package d804_2;
import java.io.*;
public class IoDemo2 {
     
    public static void main(String[] args) {
     
        copyFile("d:\\p.txt","d:\\u2.txt");
    }
 
    static void copyFile(String src, String dec) {
     
        FileInputStream fis = null;
        FileOutputStream fos = null;
        //为了提高效率,设置缓存数组!(读取的字节数据会暂存放到该字节数组)
        byte[] buffer = new byte[1024];
        int temp = 0;
        try {
     
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dec);
            //边读边写
            //temp指的是本次读取的真实长度,temp等于-1时表示读取结束
            while ((temp = fis.read(buffer)) != -1) {
     
                /*将缓存数组中的数据写入文件中,注意:写入的是读取的真实长度;
                 *如果使用fos.write(buffer)方法,那么写入的长度将会是1024,即缓存
                 *数组的长度*/
                fos.write(buffer,0,temp);
            }
        } catch (FileNotFoundException e) {
     
            e.printStackTrace();
        } catch (IOException e) {
     
            e.printStackTrace();
        } finally {
     
            try {
     
                if (fos != null) {
     
                    fos.close();
                }
            } catch (IOException e) {
     
                e.printStackTrace();
            }
            try {
     
                if (fis != null) {
     
                    fis.close();
                }
            } catch (IOException e) {
     
                e.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(Java)