Java IO -- 字节流 & 字符流

来源:互联网 发布:mac spine1.7.03 安装 编辑:程序博客网 时间:2024/05/24 06:35

输入和输出操作

若想要将程序运行的数据在程序运行结束都保存下来(持久化操作),或者将存储在硬盘中的数据在程序运行时读取出来,那么就要进行输入和输出操作。

  • 把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作。
  • 把持久化设备上的数据读取到内存中这个动作称为输入(读)Input 操作。
  • 因此我们把这种输入和输出动作称为IO操作。

Java 字符流 和 字节流

java程序中所有数据都是以流的方式传输和存储的

程序中需要数据是需要输入流进行读入数据,当程序需要保存或输出数据时,需要输出流写出数据
java中按照传输方式的不同,可以分为字符流和字节流

字节流: 用于处理字节文件、二进制文件(对象)

输入:InputStream(Abstract)

FileInputStream // 字节输入流BufferedInputStream // 字节缓冲输入流

输出:OutputStream(Abstract)

FileOuputStream // 字节输出流BufferedOutputStream // 字节缓冲输出流

字符流:用于处理字符、字符串

输入:Reader(Abstract)

FileReader // 字符输入流BufferedReader // 字符缓冲输入流

输出:Writer(Abstract)

FileWriter // 字符输出流BufferedWriter // 字符缓冲输出流
  1. 操作流程
|--- 1.创建一个输入流(读操作:InputStream)|--- 2.创建一个输出流(写操作:OutputStream)|--- 3.进行读取/写入操作|--- 4.关闭输入/输出流

Java 字节流

流中保存的实际都是字节文件 ???

在数据传输过程中,一切数据(文本、图像、音频等)最终存储的都为一个个字节,也就是二进制数字。所以在数据传输中使用二进制数据可以完成任意数据的传递。因此在进行文件传输时,要始终明确,传输的始终都是二进制数据。

字节流 读取 & 写入文件

创建输出流时(写入文件)的不同构造器

将数据写入指定文件,如果文件不存在则会自动创建,如果文件已存在,则进行覆盖

public FileOutputStream(File file) throws FileNotFoundExceptionpublic FileOutputStream(String name) throws FileNotFoundException

将数据写入指定文件,如果文件已经存在,但不想覆盖该文件,以便保留原有数据。可以使用以下构造器:

public FileOutputStream(File file, boolean append) throws FileNotFoundExceptionpublic FileOutputStream(String name,boolean append) throws FileNotFoundException

创建一个向指定 File对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。

如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,则抛出FileNotFoundException。

使用IO字节流复制文件

public class FileIOTest {    public static void main(String[] args) throws IOException {        // 创建输入流        FileInputStream inputStream = new FileInputStream(new File("test.txt"));        // 创建输出流,一经创建就必须明确数据的写入位置        // 输出流的写入位置是文件,会自动创建,如果已存在,那么会覆盖掉原有文件,若想在原有文件末尾追加数据,可选用相应构造器        FileOutputStream outputStream = new FileOutputStream(new File("test-copy.txt"));        int len = 0;        byte[] data = new byte[1024];        while ((len = inputStream.read(data)) != -1) {            outputStream.write(data, 0, len);        }        outputStream.close();        inputStream.close();    }}

字节缓冲流

字节缓冲流根据流的方向,共有2个:
- 写入数据到流中,字节缓冲输出流 BufferedOutputStream
- 读取流中的数据,字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,通过缓冲区读写,提高了IO流的读写速度

用法与普通输入流基本一致,但在创建时需要传入一个相应的流

public static void copyFile(File f, File f2) throws IOException {    BufferedInputStream input = new BufferedInputStream(new FileInputStream(f));    BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(f2));    int len = 0;     byte[] data = new byte[1024];    while ((len = input.read(data)) != -1) {        output.write(data, 0, len);    }    output.close();    input.close();}

Java 字符流

尽管计算机中一切都是以字节为单位存储的,我们可以使用java的字节流传输任何格式的文件。但是在IO开发过程中,会经常传输字符数据,而以字节流传输字符数据时,每次都需要将字符串转换成字节再处理,这使得程序员无法对数据内容进行判断(程序员只能识别字符,无法识别字节)。为便于操作,java提供了专门以字符作为操作单位的类——字符流,其底层仍然为字节流

字符流只能操作字符,无法操作其他数据,如声音、视频等。

字节流与字符流的转换(转换流)

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

// 构造器public OutputStreamWriter(OutputStream out) // 创建使用默认字符编码的 OutputStreamWriterpublic OutputStreamWriter(OutputStream out, String charsetName) throws UnsupportedEncodingException // 创建使用指定字符集的 OutputStreamWriter。// 使用OutPutStreamWriter writer = new OutputStreamWriter(new FileOutputStream("test.txt"), "UTF-8");
OutputStreamWriter流对何如何把字符转成字节输出?

其实在OutputStreamWriter流中存在自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数(调用编码转换器)存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

// 构造器public InputStreamReader(InputStream in) // 创建一个使用默认字符集的InputStreamReaderpublic InputStreamReader(InputStream in, String charsetName) throws UnsupportedEncodingException // 创建使用指定字符集的 InputStreamReader// 使用InputStreamReader reader = new InputStream(new FileInputStream("test.txt"), "UTF-8");

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象

转换流的子类(字符流及其缓冲流)

字符流的使用
public class ReaderWriterTest {    public static void main(String[] args) throws IOException {        FileReader reader = new FileReader("水浒传.txt");        FileWriter writer = new FileWriter("水浒传-copy.txt");        int len = 0;        char[] data = new char[1024];        // 每次读取一个字符        // while ((len = reader.read()) != -1) {        // 每次读取一个数组        while ((len = reader.read(data)) != -1) {            writer.write(data, 0, len);        }        writer.close();        reader.close();    }}
缓冲流的使用
public class BufferedReaderWriterTest {    public static void main(String[] args) throws IOException {        BufferedReader reader = new BufferedReader(new FileReader("水浒传.txt"));        BufferedWriter writer = new BufferedWriter(new Filewriter("水浒传-copy.txt"));        int len = 0;        char[] data = new char[1024];        // 每次读取一个字符        // while ((len = reader.read()) != -1) {        // 每次读取一个数组        while ((len = reader.read(data)) != -1) {            writer.write(data, 0, len);        }        writer.close();        reader.close();    }}

OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。

FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?条件:1、操作的是文件。2、使用默认编码

原创粉丝点击