字节流、字符流

1.1 IO概述

  • 学习IO流的目的
  1. 实现数据的持久化。
  • 什么是IO
  1. Input:输入
  2. Output:输出
  • 输入输出称为IO操作
  • IO流的作用
  1. 将文件中的数据读取到内存中
  2. 将内存中的数据保存到文件中
  • IO流的分类
  1. 按照数据流向分类:输入流(将文件中的数据读取到内存中)/输出流(将内存中的数据保存到文件中)
  2. 按照操作的数据类型进行分类:字节流(以字节为单位读写数据)/字符流(以字符为单位读写数据)
  3. 按照数据的流向和类型分类:字节输入流/字节输出流/字符输入流/字符输出流

 

2.1 数据的本质

  •  计算机只识别0和1
  • 所有的数据(文本文件、视频、图片、音频等)在内存中存储都是0和1组成
  • 所有数据在传输过程中都是以0和1进行传输(二进制)
  • 数据的本质:二进制

2.2 字节输出流(OutputStream):

  •  OutputStream类概述
  • output:输出。
  • 是所有字节输出的父类
  • Stream:字节流。
  • 是一个字节输出流,以字节为单位输出数据到文件中。
  • 是一个抽象类,不能直接创建该类的对象,只能创建子类对象。
  • OutputStream类常用子类
  • FileOutputStream
  • BufferedOutputStream
  • ObjectOutputStream
  • PrintStream
  • OutputStream类常用方法
  • void close() 关闭流释放资源(注意:创建流之后就关闭流释放资源,养成良好的习惯
  • void write(byte[] b):输出一个字节数组
  • void write(byte[] b,int off,int len):输出一个字节数组的一部分内容
  1. off:数组的起始索引
  2. len:要输出的字节个数
  • void write(int b):输出一个字节

2.3 FileOutputStream类

  • FileOutputStream类常用构造方法
  •  FileOutputStream(String name)
  1. 根据文件路径字符串创建字节输出流对象。
  2. 如果目标文件不存在,则会创建该文件
  • FileOutputStream(File file)
  1. 根据文件对象创建字节输出流对象
  2. 如果目标文件不存在 ,则会创建该文件
  • FileOutputStream(File file,boolean append)
  • FileOutputStream(String name,boolean append)
  1. 根据文件对象或文件路径字符串创建字节输出流对象
  2. append:true 表示追加输出数据,不清空当前文件的内容
  3. append:false 表示不追加输出数据,清空当前文件的内容。
  4. 如果目标文件不存在,则会先创建该文件。
  • 字节输出流的使用步骤:
  1.  创建字节输出流对象并关联目标文件
  2. 调用字节输出流对象的write方法输出数据
  3. 调用字节输出流对象的close方法关闭流释放资源

1.构造举例:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class FileOutputStreamConstructor {
    public static void main(String[] args) throws FileNotFoundException {
        //使用File对象创建流对象
        File f = new File("a.txt");
        FileOutputStream fos = new FileOutputStream(f);

        //使用文件名创建流对象
        FileOutputStream fos1 = new FileOutputStream("b.txt");
    }
}

2. 写出字节数据举例:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。
    流操作完毕之后,必须释放资源,调用close方法。
 */
public class FosWrite {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fs = new FileOutputStream("fs.txt");

        //写出数据
        fs.write(97);
        fs.write(98);
        fs.write(99);

        //关闭资源
        fs.close();
    }
}

3.写出字节数组:write(byte[] b)  ,每次可以写出数组中的数据

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FosWriteDemo01 {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("fos.txt");

        String str = "马化腾";

        //将字符串转化为字节数组
        byte[] b = str.getBytes();
        //写出字节数组数据
        fos.write(b);
        //关闭资源
        fos.close();
    }
}

4. 写出指定长度字节数组: write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    写出指定长度字节数组:
    write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
 */
public class FosWriteDemo02 {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("b.txt");

        //将字符串转为字节数组
        byte[] b = "abcde".getBytes();

        //写出指定长度字节数组
        fos.write(b,2,2);

        //关闭流
        fos.close();
    }
}
/*
    输出结果:cd
 */

5.数据追加续写

  • 上面的案例中,每次程序运行,创建输出流对象,都会清空目标文件中的数据。如果想保留目标文件中的数据,还能继续添加新的数据则需要用到以下两个方法:
  • FileOutputStream(File file,boolean append):创建文件输出流以写入由指定的File对象表示的文件
  • FileOutputStream(String name,boolean append):创建文件输出流以指定的名称写入文件。
  • 这两个构造方法,参数都需要传入一个boolean类型的值,true表示追加数据,false表示清空原有数据。这样创建的输出流对象,就可以指定是否继续追加续写了。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    写出指定长度字节数组:
    write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节
 */
public class FosWriteDemo02 {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("b.txt",true);

        //将字符串转为字节数组
        byte[] b = "abcde".getBytes();

        //写出指定长度字节数组
        fos.write(b,2,2);

        //关闭流
        fos.close();
    }
}

 6. 写出换行

输出一个换行符

\r    回车

\n    换行

\r\n    换行(强烈推荐使用)

如:fos.write("\r\n".getBytes());

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FosWriteDemo03 {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileOutputStream fos = new FileOutputStream("foos.txt");

        //定义字节数组
        byte[] bytes ={97,98,99,100,101,102};

        //遍历数组
        for (int i = 0; i < bytes.length; i++) {
           //写出一个字节
           fos.write(bytes[i]);
           //写出一个换行,换行符号转成数组输出
            fos.write("\r\n".getBytes());
        }
        //关闭资源
        fos.close();
    }
}


3.1 字节输入流(InputStream)

  • InputStream类概述
  • Input:输入
  • Stream:字节流
  • 是一个字节输入流,以字节为单位读取是数据。
  • 是一个抽象类,也不能直接创建该类对象,只能创建子类对象。
  • 是所有字节输入流的父类。
  • InputStream类常用子类
  •  FileInputStream
  • BufferedInputStream
  • ObjectInputStream
  • inputStream类常用方法 
  • void close():关闭流释放资源
  • int read()
  1. 读取一个字节,返回该读取到的字节数
  2. 如果读取到文件末尾,则返回值为-1
  • int read(byte[] b)
  1. 读取一个字节数组,将读取到的内容存储到指定的字节数组中。
  2. 返回实际读取到的字节个数
  3. 如果读取到文件末尾,则返回值为-1
  • int read(byte[] b,int off,int len)
  1. 读取一个字节数组,将读取到内容存储到指定的字节数组中。
  2. off:字节数组的起始索引
  3. len:存储字节的个数

3.2 FileInputStream类

  • FileInputStream类常用构造方法:
  • FileInputStream(String name);
  • FileInputStream(File file);
  1. 根据文件路径字符串或文件对象创建字节输入流对象。
  2. 如果目标文件不存在,则直接抛出异常。
  3. 关联的目标文件必须是普通文件不能是文件夹,否则直接抛出异常。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class FileInputStreamDemo01 {
    public static void main(String[] args) throws FileNotFoundException {
        //使用File对象创建流对象
        File file = new File("a.txt");

        FileInputStream fis = new FileInputStream(file);

        //使用文件名创建流对象
        FileInputStream  fileInputStream = new FileInputStream("b.txt");
    }
}

 1.读取字节数据:read方法,每次可以读取一个字节数据,提升为int类型,读取到文件末尾,返回-1

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FISRead {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileInputStream fis = new FileInputStream("H:/read.txt");

        //读取数据,返回一个字节
        int read = fis.read();
        System.out.println((char) read);

        read = fis.read();
        System.out.println((char) read);

        read = fis.read();
        System.out.println((char) read);

        read = fis.read();
        System.out.println((char) read);

        read = fis.read();
        System.out.println((char) read);
        //读取到末尾,返回-1
        read = fis.read();
        System.out.println(read);

        //关闭资源
        fis.close();
    }
}

 2. 用循环的方式改进

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FISReadDemo01 {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileInputStream fis = new FileInputStream("H:/read.txt");

        //定义变量,保存数据
        int b ;
        while ((b=fis.read())!= -1){
            System.out.println((char)b);
        }
        //关闭资源
        fis.close();
    }
}

 3.使用字节数组读取:read(byte[] b),每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FISReadDemo02 {
    public static void main(String[] args) throws IOException {
        //使用文件名创建流对象
        FileInputStream fis = new FileInputStream("H:/read.txt");

        //定义变量,作为有效个数
        int len;

        //定义字节数组,作为装字节数据的容器
        byte[] b = new byte[2];

        //循环读取
        while ((len=fis.read(b))!=-1){
            System.out.println(new String(b));
        }

        //关闭资源
        fis.close();
    }
}

 每次读取内容都是从数组中的第0个位置开始,所以依次读取的内容是ab    cd    ed 

4.使用循环进行改进

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

/*
    使用循环改进
 */
public class FISReadDemo03 {
    public static void main(String[] args) throws IOException {
        test01();
    }
    public static void test01() throws IOException {
        //创建字节输入流对象并关联目标文件
        FileInputStream fis = new FileInputStream("H:/read.txt");

        //创建字节数组,用来存储读取到的字节数
        byte[] b = new byte[2];

        //定义变量,接收实际读取到的字节个数
        int len;

        //使用循环读取
        while ((len = fis.read(b))!= -1){
            //将字节数组的内容转换为字符串输出
            System.out.println(new String(b) );
        }
        //关闭流资源
        fis.close();
    }
}

 错误数据d,是由于最后一次读取时,只读取一个字节e,数组中,上次读取的数据没有被完全替换,所以要通过len,获得有效的字节

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FISReadDemo04 {
    public static void main(String[] args) throws IOException {
        test01();
    }
    public static void test01() throws IOException {
        //创建字节输入流对象并关联目标文件
        FileInputStream fis = new FileInputStream("H:/read.txt");

        //定义变量,接收实际读取到的字节个数
        int len;

        //创建字节数组,用于保存读取到的字节数
        byte[] bytes = new byte[2];

        while ((len=fis.read(bytes))!= -1){
            //将字节数组的内容转换为字符串输出
            System.out.println(new String(bytes,0,len));//len 每次读取的有效字节个数
        }
        //关闭流资源
        fis.close();
    }
}

4.1 图片复制

原理:从已有文件中读取字节,将该字节写出到另一个文件中: 

import java.io.*;
public class FileCopy {
    public static void main(String[] args) throws Exception {
       //创建文件对象并关联源文件
        File srcFile = new File("H:/aaa.jpg");
        //创建文件对象并关联目标文件
        File destFile = new File("H:/bbb.jpg");
        copyFile(srcFile,destFile);
    }
    public static void copyFile(File srcFile,File destFile) throws Exception {
        //创建字节输入流对象关联源文件
        FileInputStream fis = new FileInputStream(srcFile);
        //创建字节输出流对象并关联目标文件
        FileOutputStream fos = new FileOutputStream(destFile);

        //创建字节数组用于保存读取到的文件数据
        byte[] b = new byte[1024];

        //定义整型变量用于保存实际读取到的字节个数
        int len=-1;

        //循环读写数据
        while ((len=fis.read(b))!=-1){
           //利用fos将字节数组内容输出到目标文件中
            fos.write(b,0,len);
        }
        //关闭流释放资源
        fis.close();
        fos.close();
    }
}

5.1 字符流

  •  当使用字节流读取文本文件时,可能会有一个小问题,就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。

5.2 字符输入流(Reader)

  •  Reader类概述
  • 是字符输入流,也是一个抽象类,不能创建对象,只能使用子类。
  • 以字符为单位读取数据。
  • 是所有字符输入流的父类。
  • Reader类常用子类
  •  FileReader
  • BufferedReader
  • InputStreamReader
  • Reader类常用方法
  • void close:关闭流释放资源
  •  int   read()
  1. 读取一个字符,返回实际读取的字符数
  2. 读取到文件末尾返回-1
  • int read(char[] cbuf)
  1. 读取一个字符数组,将读取到的字符存储到字符数组中
  2. 返回实际读取到的字符个数
  3. 读取到文件末尾返回-1
  • int read(char [] cbuf,int off,int len)
  1. 读取一个字符数组,将读取到的内容存储到指定的字符数组中。
  2. off:字符数组的起始索引。
  3. len:存储字符的个数。

 5.3 FileReader类

  • FileReader类常用构造方法
  • FileReader(String name)
  • FileReader(File file)
  1. 根据文件路径字符串或文件对象创建字符输入流对象
  • 字符输入流使用步骤:
  1. 创建字符输入流对象并关联目标文件
  2. 调用read方法:读取字符,字符数组
  3. 调用close方法关闭流释放资源
  •  FileReader类一次读取一个字符
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/*
    FileReader一次读取一个字符
 */
public class FileReaderDemo01 {
    public static void main(String[] args) throws IOException {
        //字符输入流读取数据:一次读取一个字节:没有使用循环
       test01();
        System.out.println("-------------");
        //字符输入流读取数据:一次读取一个字节:使用循环
        test02();
    }

    //字符输入流读取数据:一次读取一个字节:没有使用循环
    public static void test01() throws IOException {
        //创建字符输入流对象并关联目标文件
        FileReader fr = new FileReader("a.txt");

        //读取一个字符
        int len = fr.read();
        System.out.println((char) len);

        //再读取一个字符
        len = fr.read();
        System.out.println((char) len);

        //再读取一个字符
        len = fr.read();
        System.out.println((char) len);

        //关闭流释放资源
        fr.close();
    }

    //字符输入流读取数据:一次读取一个字节:使用循环
    public static void test02() throws IOException {
        //创建字符输入流对象并关联目标文件
        FileReader fr = new FileReader("b.txt");

        //定义变量接收读取的字符数
        int len = -1;

        while ((len=fr.read())!=-1){
            System.out.println((char)len);
        }
        //关闭流释放资源
        fr.close();
    }
}
  • FileReader类一次读取一个字符数组
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

/*
    FileReader类一次读取一个字符数组
 */
public class FileReaderDemo02 {
    public static void main(String[] args) throws IOException {
        test();
    }
    public static void test() throws IOException {
        //定义字符输入流对象并关联目标文件
        FileReader fr =  new FileReader("a.txt");

        //定义字符数组,用于保存读取到的数据
        char[] chs = new char[2];

        //定义变量,用于接收实际读取到的字符个数
        int len=-1;
        while ((len = fr.read(chs))!=-1){
            //将字符数组转化为字符串输出
            System.out.println(new String(chs,0,len));
        }
        //关闭流
        fr.close();
    }
}

6.1 字符输出流(Writer):

  • Writer类概述
  • 是字符输出流,也是一个抽象类,不能创建对象,只能使用子类。
  • 以字符为单位输出的数据。
  • 是所有字符输出流的父类。 
  •  Writer类常用子类
  • FileWriter
  • BufferedWriter
  • OutputStreamWriter
  • printWriter
  •  Writer类常用方法
  • void close();
  • void writer(char[] cbuf):输出字符数组
  • void writer(char[] cbuf,int off,int len):输出字符数组的一部分
  • void write(int c):输出一个字符
  • void write(String str):输出字符串
  • void write(String str,int off,int len):输出字符串的一部分
  • FileWriter类
  • FileWriter类常用构造方法
  •  FileWriter(String name)
  • FileWriter(File file)
  1. 默认是不追加,会清空文件内容
  • FileWriter(String name,boolean append)
  • FileWriter(File file,boolean append)
  1. 根据文件路径字符串和文件对象创建字符输出流对象。
  2. append:true 追加  false:不追加
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo01 {
    public static void main(String[] args) throws IOException {
        //创建字符输出流对象并关联目标文件
        FileWriter fw = new FileWriter("c.txt",true);

        //定义字符串
        String str = "我用Java书写人生";
        //输出字符串
        fw.write(str);
        //输出字符串的一部分
        fw.write(str,6,4);

        //输出换行符
        fw.write("\r\n");

        //字符数组
        char[] buf = {'广','州'};
       //输出字符数组
        fw.write(buf);
        //输出字符数组的一部分
        fw.write(buf,1,1);

        //关门流
        fw.close();
    }
}

版权声明:本文为博主原创文章,转载请注明出处。 https://mp.csdn.net/postedit/81543823 

猜你喜欢

转载自blog.csdn.net/Huangyuhua068/article/details/81543823