Java IO流基础:IO流 文件 字符流 字节流 处理流等...

目录

一,文件 File

1.创建文件的三种方式

2.获取文件信息的操作

3.目录操作 

二,io流原理

1.流的分类

 三,节点流

1.字节流 FileInputStream FileOutputStream

2.字符流 FileReader FileWriter

四,处理流

1.节点流和处理流的区别

2.BufferedInputStream BufferedoutputStream

3.BufferedReader BufferedWriter

五,对象处理流

1.序列化和反序列化 

 2.objectInputStream objectOutputStream

3. serialVersionUID

六,InputStreamReader OutputStreamWrite

1.InputStreamReader

 2.OutputStreamWrite


一,文件 File

1.创建文件的三种方式

(1)根据路径创建文件:创建File对象,传入文件路径,调用createNewFile方法(会抛出IOException异常),注意:file对象被创建出后首先被保存在内存中,调用方法createNewFile后才会被写到硬盘中。

public static void create01() throws IOException {
        String filePath = "E:\\FileTest\\news1.txt";
        File file = new File(filePath);  //根据路径创建文件
        file.createNewFile();  //createNewFlie()创建新文件,抛出IOException异常
    }

(2)根据父目录文件加子路径创建文件: 创建File对象,传入父目录文件和子路径,调用createNewFile方法。

public static void create02() throws IOException{
        File parent = new File("E:\\FileTest\\");
        String child = "news2.txt";
        File file = new File(parent, child); //根据父目录文件加子路径创建
        file.createNewFile();
    }

(3)根据父路径加子路径创建文件:创建File对象,传入父路径和子路径,调用createNewFile方法。

public static void create03() throws IOException{
        String  parent = "E:\\FileTest\\";
        String child = "news3.txt";
        File file = new File(parent, child); //根据父目录和子路径创建文件
        file.createNewFile();
    }

2.获取文件信息的操作

getName获取文件名称
getAbsolutePath获取文件绝对路径
getparent获取文件父路径
length获取文件大小,按字节算
exists文件是否存在
isFile是否是一个文件
isDirectory是否是一个目录
delete删除文件

3.目录操作 

创建目录有两种方式:mkdirs()创建多级目录,mkdir()创建单级目录。 创建成功会返回True。

package Text_Streams.File;

import java.io.File;

public class Directory {
    public static void main(String[] args) {
        String directoryPath = "E:\\FileTest\\Demo\\a";
        File file = new File(directoryPath);       
        if(file.mkdirs()){  //mkdirs创建多级目录,mkdir创建单级目录
             System.out.println(file.getName() + "创建成功!");
        }
        else System.out.println(file.getName() + "创建失败!");
    }
}

二,io流原理

        io流即 input 流(输入流)和 output 流(输出流)。输入流指读取外部数据(外部存储设备中的数据)到程序(内存)当中,输出流指将程序(内存)中的数据输出到外部存储设备中。

1.流的分类

  • 按操作数据单位不同分为:字节流和字符流;
  • 按数据流的流向不同分为:输入流和输出流;
  • 按流的角色不同分为:节点流和处理流(包装流);

        Java IO流的四个抽象基类如下,Java IO流都是从这四个基类派生出的,由这四个类派生出的子类名称都是以其父类名称作为子类名后缀,例如:FileInputStream就是字节输入流,FileWrite就是字符输出流。

(抽象基类)字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

 三,节点流

1.字节流 FileInputStream FileOutputStream

字节流读取文件时按字节单位读取,适合用于读取二进制文件如:图片,音乐,视频等。

(1)FileInputStream用read()方法读取文件,以int形式返回读取内容,读取结束时返回-1,具体操作步骤如下:

  1. 创建FileInputStream对象,传入文件路径或文件对象;
  2. 调用read方法读取文件,read方法抛出IO异常;
  3. 读取结束后关闭输入流,避免资源浪费;
public static void readFile() throws IOException {
        int fileRead = 0;
        String filePath = "E:\\FileTest\\news1.txt";
        File file = new File(filePath);
        FileInputStream fileInputStream = new FileInputStream(file);  //创建FileInoutStream对象,读取文件(从硬盘到内存)
        while((fileRead = fileInputStream.read()) != -1){  //read方法按字节读取,读取结束时返回-1
            System.out.print((char)fileRead);  //read返回ascall码,需强转为char
        }
        fileInputStream.close();  //读取结束后要关掉输入流,以防资源浪费
    }

read方法默认一个字节一个字节读取,在调用read方法时,可以在read中传入一个字节数组,这样输入流每次读取时可以最多读取数组长度个字节到数组中,并返回实际读取到的字节数

public static void readFile1() throws IOException {
        byte by[] = new byte[8];
        int fileLength = 0;
        String filePath = "E:\\FileTest\\news1.txt";
        FileInputStream fileInputStream = new FileInputStream(filePath);  //创建FileInoutStream对象,读取文件(从硬盘到内存)
        while((fileLength = fileInputStream.read(by)) != -1){  //从该输入流读取最多by.length个字节到by中,返回实际读取到的字节数
            System.out.print(new String(by, 0, fileLength));  //字符串方法,将数组中指定范围的字节内容转化为字符串
        }
        fileInputStream.close();  //读取结束后要关掉输入流,以防资源浪费
    }

(2)FileOutputStram用write()方法输出数据,操作步骤如下:

  1. 创建FileOutputStram对象,传入文件路径或文件对象;
  2. 调用write方法,有三种写入方式:写入一个字节,写入字节数组中全部内容,写入字节数组中指定范围的内容;
  3. 关闭输出流;
public static void writeFile() throws IOException {
        String filePath = "E:\\FileTest\\news4.txt";
        FileOutputStream fileOutputStream = new FileOutputStream(filePath);

        String str = "ysqdysqd";
        fileOutputStream.write('y'); //1.写入一个字节
        fileOutputStream.write(str.getBytes());  //2.写入字符串,getBytes将字符串转换为字节数组
        fileOutputStream.write(str.getBytes(), 0, 4);  //3.从off开始,将字节数组中长度为len的字节输出
        fileOutputStream.close();
    }

 FileOutputStream默认将文件原有内容全部覆盖,在创建对象时,可以将append值设为true,这样写入内容会追加到原有内容之后。

new FileOutputStream(filePath); 直接覆盖原来的内容
new FileOutputStream(filePath,true); 将append置为true,写入的内容会追加到原有内容之后

(3)实现文件拷贝:复制硬盘中的内容,可以开启输入流将指定文件读取到内存中,然后再开启输出流将数据重新输出到硬盘中,具体操作如下:

public static void copy() throws IOException{
        String filePath = "E:\\FileTest\\learn.jpg";
        String filePath2 = "E:\\FileTest\\learn1.jpg";
        FileInputStream fileInputStream = new FileInputStream(filePath);
        FileOutputStream fileOutputStream = new FileOutputStream(filePath2);
        int len;
        byte by[] = new byte[1024];
        while((len = fileInputStream.read(by)) != -1){
            fileOutputStream.write(by, 0, len);
        }
        if(fileOutputStream != null)fileOutputStream.close();
        if(fileInputStream != null)fileInputStream.close();
    }

运行成功,没有问题。 

2.字符流 FileReader FileWriter

在操作文本文件时,适合用字符流,字符流FileReader和FileWriter的操作方法与字节流FileInputStream和FileOutputStream基本一致,这里直接用文件拷贝代码来举例它们的用法。

public static void fileRead() throws IOException {
        String filePath = "E:\\FileTest\\news1.txt";
        String filePath1 = "E:\\FileTest\\news5.txt";
        File file = new File(filePath);
        FileReader fileReader = new FileReader(file);
        FileWriter fileWriter = new FileWriter(filePath1, true);
        int reader;
        char ch[] = new char[8];
        while((reader = fileReader.read(ch)) != -1)
        {
            fileWriter.write(ch, 0, reader);
        }
        if(fileReader != null)fileReader.close();
        fileWriter.flush();  //字符输出流结束时需要刷新,否则可能会输出失败
        if(fileWriter != null)fileWriter.close();
    }

四,处理流

1.节点流和处理流的区别

  • 节点流从一个特定的数据源读取数据,如FileReader,FileWrite等;
  • 处理流(也叫包装流),“连接”在已有的流(节点流或处理流)之上,提供更为强大的读写功能

 总的来说,节点流是一种低级流,直接与数据源接触。处理流包装了节点流,即消除了不同节点流之间的实现差异,也可以提供更方便的方法来完成输入输出,此外,处理流不会与数据源直接接触。举例说明:

public BufferedInputStream(InputStream in, int size) {
        super(in);  //封装了一个InputStream对象
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

 从处理流BufferedInputStream的构造方法可以看出,其中封装了一个InputStream的对象,使用时可以根据传入的InputStream向下转型,也就是“消除了不同节点流之间的实现差异”,此外也可以重新包装原有的方法,也就是”提供更为强大的读写功能“。

2.BufferedInputStream BufferedoutputStream

BufferedInputStream和BufferedoutputStream是包装字节流的处理流,使用步骤如下:

  1. 实例化一个字节流对象;
  2. 将字节流对象包装到处理流当中;
  3. 进行读写操作;
  4. 关闭外部流;

 处理流的读写方式与包装的流读写方法一致,需要注意的是,关闭IO流时关闭外部流,也就是处理流即可,因为底层会自动关闭节点流,代码示例如下:

public static void copy() throws IOException {
        String filePath = "E:\\FileTest\\learn2.jpg";
        String filePath1 = "E:\\FileTest\\learn3.jpg";
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(filePath1));
        byte by[] = new byte[8];
        int len;
        while((len = bufferedInputStream.read(by)) != -1){
            bufferedOutputStream.write(by, 0, len);
        }
        bufferedInputStream.close();  //关闭外部流即可
        bufferedOutputStream.flush();  //输出流记得刷新
        bufferedOutputStream.close();
    }

3.BufferedReader BufferedWriter

 包装字符流的处理流,使用步骤与上述两个处理流一致:

  1. 实例化一个字符流对象;
  2. 将字符流对象包装到处理流当中;
  3. 进行读写操作;
  4. 关闭外部流;
public static void read1() throws IOException {
        String filePath = "E:\\FileTest\\news5.txt";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));  
        String len;
        while((len = bufferedReader.readLine()) != null){  //readLine读取结束返回null
            System.out.println(len);
        }
        bufferedReader.close();
    }
    public static void write1() throws IOException{
        String filePath = "E:\\FileTest\\news5.txt";
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath, true));
        String str = "原神启动!";
        bufferedWriter.write(str);
        bufferedWriter.newLine(); //插入换行符
        bufferedWriter.close();
    }

五,对象处理流

在上面的操作中,我们保存的只是单纯的文字,图片之类的数据,假如我保存了一个数据100,我怎么知道这个数据是字符串还是整型数字呢?这时,我们就需要同时保存数据和数据的类型。对于这样的需求,我们就需要用到序列化反序列技术。

1.序列化和反序列化 

  1. 序列化就是在保存数据时,同时保存数据的值数据类型
  2.  反序列化就是在恢复数据时,同时恢复数据的值数据类型
  3. 需要让某个对象支持序列化机制,必须实现这连个接口之一:SerializableExternalizable;

 2.objectInputStream objectOutputStream

对象流objectInputStream和objectOutputStream可以用来实现序列化和反序列化,操作如下:

//序列化
public static void write() throws IOException {
        String filePath = "E:\\FileTest\\news6.txt";
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
        objectOutputStream.writeInt(100);  //自动装箱 int -> Integer Integer实现了Serializable
        objectOutputStream.writeBoolean(true);
        objectOutputStream.writeChar('s');
        objectOutputStream.writeObject(new Dog("神里凌华的狗", 250));  //对象序列化
        objectOutputStream.writeUTF("原神启动!");

        objectOutputStream.close();
    }

//反序列化
public static void read1() throws IOException, ClassNotFoundException {
        String filePath = "E:\\FileTest\\news6.txt";
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
        //读取(反序列化)的时候要与保存数据(序列化)的顺序一样
        System.out.println(objectInputStream.readInt());
        System.out.println(objectInputStream.readBoolean());
        System.out.println(objectInputStream.readChar());
        Object dog = objectInputStream.readObject();
        System.out.println(dog.toString());
        System.out.println(objectInputStream.readUTF());

        objectInputStream.close();
    }

注意: 

  1. 读取(反序列化)时要与保存数据(序列化)的顺序一致;
  2. 序列化对象时,对象里面属性的类型也要实现序列化接口,基本数据类型如int型数据会被自动装箱成Integer,Integer实现了序列化接口;
  3. 序列化具有可继承性,若某类实现了序列化,那他的子类默认实现序列化;
  4. transient修饰的字段不会被序列化;

3. serialVersionUID

 serialVersionUID是在序列化与反序列化过程中用于检验的版本号,在序列化时,会将对象的serialVersionUID写入到字节序列中,反序列化时会检查接收方对象的serialVersionUID是否与序列化时写入的一致,如果一致则反序列化成功,不一致则报错InvalidCastException

  serialVersionUID可以显式声明隐式声明,若隐式声明,则每次修改Class时,自动生成的serialVersionUID会改变,导致反序列化失败。所以serialVersionUID最好显式声明:

private static final long serialVersionUID = 1l;

六,InputStreamReader OutputStreamWrite

        字符流默认的编码方式是UTF-8,但是遇到不是该种编码方式的文件时,字符流就会读取失败,这时就需要用到InputStreamReader和OutputStreamWrite类,帮助实现字节流和字符流之间的转化。

1.InputStreamReader

InputStreamReader将字节流转化为字符流,可以指定编码方式,使用步骤:

  1. 将字节流装入InputStreamReader,并指定编码方式;
  2. 将InputStreamReader装入字符流;
  3. 读写;
  4. 关闭外层流;
public static void input() throws IOException{
        String filePath = "E:\\FileTest\\news51.txt";
        //字节流转化为字符流 两步包装:
        //1.将 FileInputStream 转化为 InputStreamReader,并指定编码 gbk
        InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //2.把 InputStreamReader 装入包装流 BufferedReader
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        //3.读取
        String len;
        while((len = bufferedReader.readLine()) != null)
        {
            System.out.println(len);
        }
        bufferedReader.close();//关外层流即可
    }

 2.OutputStreamWrite

 OutputStreamWrite将字符流转化为字节流,使用方式与InputStreamReader一致。

public static void output() throws IOException{
        String filePath = "E:\\FileTest\\news51.txt";
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(filePath), "gbk");
        BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
        bufferedWriter.write("hello world!");
        bufferedWriter.close();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值