一.IO流简介

  1. 流是一个抽象概念,Java程序和外部设备(可以是硬盘上的文件,也可以是网络设备)之间的输入输出操作是基于流的。

    流就好比水管中的水流,具有流入和流出,类比数据的输入和输出。

    Java中流屏蔽了实际IO设备中处理数据的细节,主要用来处理设备之间的数据传输。

  2. IO流的分类

    根据数据的流向可以分为:输入流和输出流

    根据数据的类型可以分为:字节流和字符流

    Java中将所有流类型都放在了java.io包中,用于实现输入和输出功能,相关类关系如下图

二.字节流

  1. 一切皆为字节

    Java中的字节流 处理的基本单位是单个字节,一切的文件数据(文本,图片,视频等)在存储时,都是以二进制的形式保存的,都是一个字节一个字节的,传输时候也一样,所以字节流可以传输任意文件数据,所以在操作流的时候应该明确,无论使用什么流对象,其底层传输始终是二进制数据。

  2. 字节输出流(OutputStream)

    public abstract class OutputStream是字节输出流的所有类的超类,是一个抽象类,所有的字节输出流都是继承自OutputStream。

    它定义了一些共用的方法:

    • void close():关闭此输出流并释放与此流有关的所有系统资源
    • void flush():刷新此输出流并强制写出所有缓冲的输出字节。
    • void write(byte[] b):将 b.length 个字节从指定的 byte 数组写入此输出流。
    • void write(byte[] b, int off, int len):将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
    • abstract void write(int b):将指定的字节写入此输出流。

    OutputStream有很多子类,这里主要学习FileOutputStream,FileOutputStream是文件输出流,用于将数据写到文件。

    构造方法是:

    • FileOutputStream(File file):创建一个向指定File对象表示的文件中写入数据的文件输出流。

    • FileOutputStream(File file, boolean append):创建一个向指定File对象表示的文件中写入数据的文件输出流,其中参数append代表是否追加写入文件

    • FileOutputStream(String name):创建一个向具有指定名称的文件中写入数据的输出文件流。

    • FileOutputStream(String name, boolean append):创建一个向具有指定name的文件中写入数据的输出文件流,其中参数append代表是否追加写入文件

      注意:

      当创建一个流对象时,需要传入一个文件路径,在该路径下,如果没有这个文件,则会创建该文件,如果有这个文件,将会清空这个文件的数据再写入(带append参数,且append为true的则不会清空,因为它代表着追加内容)

    示例:

    import java.io.FileOutputStream;
    import java.io.IOException; public class TestFileOutputStream {
    public static void main(String[] args) throws IOException{
    // 1. 创建FileOutputStream对象
    FileOutputStream fos = new FileOutputStream("File\\a.txt"); // 写入一个字节 97 就是字符 'a'
    fos.write(97); // 写入字节数组
    byte[] bytes = "你好".getBytes();
    fos.write(bytes); // 写入字节数组,指定长度
    byte[] b = "abcdef".getBytes();
    fos.write(b, 2, 3); // 从第二位开始,写3个,就是c,d,e fos.close(); }
    }

    运行结果:

    生成文件a.txt,内容为:a你好cde

    注意:

    write调用时候是不会写换行的。如果需要换行,需要自己写入。

    不同系统的换行不同:

    Windows是\r\n

    Unix是\n

  3. 字节输入流(InputStream)

    public abstract class InputStream是字节输入流的所有类的超累,是一个抽象类,他定义了一些共用方法:

    • void close():关闭此输入流并释放与该流关联的所有系统资源。
    • abstract int read():从输入流中读取数据的下一个字节。
    • int read(byte[] b):从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中,返回值为每次读取到的有效字节个数。

    InputStream有很多子类,这里主要学习FileInputStream,FileInputStream是文件输入流,用于从文件中读取字节。

    构造方法是:

    • FileInputStream(File file):过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
    • FileInputStream(String name):通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

    注意:

    当创建一个输入流对象时,必须传入一个文件路径,在改路径下,如果没有该文件的话,会报FileNotFoundException

    示例:文件b.txt内容为:abcdefg

    使用int read()读取:

    import java.io.FileInputStream;
    import java.io.IOException; public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("File\\b.txt"); // 读取一个字节
    // System.out.println(fis.read()); // 97
    // System.out.println(fis.read()); // 98
    // System.out.println(fis.read()); // 99
    // System.out.println(fis.read()); // 100
    // System.out.println(fis.read()); // 101
    // System.out.println(fis.read()); // 102
    // System.out.println(fis.read()); // 103
    // System.out.println(fis.read()); // -1 // 使用循环读
    int r;
    while ((r = fis.read()) != -1) {
    System.out.print((char)r);
    } // 输出 abcdefg fis.close();
    }
    }

    说明:

    1. 示例使用每次读取一个字节的方式从文件中读取数据,其中要注意虽然每次读取了一个自己,但是会被自动提升为int类型,所以打印出来的是97,98,99,100,101,102,103,这些是字符对应的ASCII码,当使用强制转换为char之后,就正常输出abcdefg了。
    2. 当读取到文件末尾时候,读出来的是-1

    使用int read(byte[] b)读取:

    import java.io.FileInputStream;
    import java.io.IOException; public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("File\\b.txt"); // 读取到数组
    byte[] b = new byte[3];
    int len; while ((len = fis.read(b)) != -1) {
    System.out.print(new String(b) + " ");
    } fis.close();
    }
    }

    说明:

    1. 程序输出的结果为:abc def gef
    2. 这种输出结果是错误的,正确应该是 abc def g,因为在第三次读取时候,文件中只读取了一个字节g,然后存在了数组的第一位,因为第二次时候数组内容为def,所以第三次时候,数组的内容为gef,只改变了第一位
    3. 要修正上面的问题,要使用len,获取有效的字节。

    修正代码:

    import java.io.FileInputStream;
    import java.io.IOException; public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("File\\b.txt"); // 读取到数组
    byte[] b = new byte[3];
    int len; while ((len = fis.read(b)) != -1) {
    System.out.print(new String(b, 0, len) + " " );
    } fis.close();
    }
    }

三.字符流

​ 当使用字节流读取文本本间时,可能会存在一个小问题,就是遇到中文字符时候,可能不会显示完整的字符,因为一个中文字符可能占用多个字符存储,所以Java中提供了字符流类,以字符为单位读写数据。

  1. 字符输出流(Writer)

    public abstract class Writer是用于写出字符流的所有类的超类,是一个抽象类,它定义了字节输出流的基本共性能方法:

    • void write(int c):写入单个字符。
    • void write(char[] cbuf):写入字符数组。
    • abstract void write(char[] cbuf, int off, int len):写入字符数组的某一部分。
    • void write(String str): 写入字符串。
    • void write(String str, int off, int len):写入字符串的某一部分。
    • void flush():刷新该流的缓冲。
    • void close():关闭此流,但要先刷新它。

    FileWriter类是写字符到文件的类,构造时使用系统默认的字符编码和默认字节缓冲区。

    构造方法:

    • FileWriter(File file):根据给定的 File 对象构造一个 FileWriter 对象。
    • FileWriter(File file, boolean append):根据给定的 File 对象构造一个 FileWriter 对象。其中append参数代表是否追加。
    • FileWriter(String fileName):根据给定的文件名构造一个 FileWriter 对象。
    • FileWriter(String fileName, boolean append):根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

    基本写数据示例:

    import java.io.FileWriter;
    import java.io.IOException; public class TestFileWriter {
    public static void main(String[] args) throws IOException{
    FileWriter fw = new FileWriter("File\\c.txt"); fw.write(97); // 写第一个字符
    fw.write('b'); // 写第二个字符
    fw.write('c'); // 写第三个字符 fw.close();
    }
    }

    注意:

    1. 如果没有调用close方法,写入的数据只是保存到了缓冲区,并没有写到文件中,这一点和FileOutputStream不一样,或者写完调用flush()刷新缓冲区。
    2. 最后如果调用了close(),可以不调用flush()刷新,因为close()会先刷新缓冲,再关闭流。
    3. 即使使用了flush()刷新了缓冲,写出了数据,但最后还是要调用close()方法来释放资源。

    其他方法写数据示例:用法和FileOutputStream类似

    import java.io.FileWriter;
    import java.io.IOException; public class TestFileWriter {
    public static void main(String[] args) throws IOException{
    FileWriter fw = new FileWriter("File\\c.txt"); // 写字符数组
    char[] chars = "我是中国人".toCharArray();
    fw.write(chars); // 从索引1开始,写2个字节
    fw.write(chars, 1, 2); // 写字符串
    String str = "你好吗"; fw.write(str); fw.write(str, 1, 1); fw.close();
    }
    }

    注意:

    字符流只能操作文本文件,不能操作图片,视频等非文本文件(因为是二进制存储的,要用字节流)

Java IO---字节流和字符流的更多相关文章

  1. JAVA IO 字节流与字符流

    文章出自:听云博客 题主将以三个章节的篇幅来讲解JAVA IO的内容 . 第一节JAVA IO包的框架体系和源码分析,第二节,序列化反序列化和IO的设计模块,第三节异步IO. 本文是第一节.     ...

  2. Java IO 字节流与字符流 (三)

    概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为:字节流和字符流 流按流向不同分为:输入流和输出流 IO流常用基类 ...

  3. Java IO 字节流与字符流 (二)

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序 ...

  4. Java IO 字节流与字符流 (五)

    Java的IO流分为字符流(Reader,Writer)和字节流(InputStream,OutputStream),字节流顾名思义字节流就是将文件的内容读取到字节数组,然后再输出到另一个文件中.而字 ...

  5. java中字节流与字符流的区别

    字节流 在I/O类库中,java.io.InputStream和java.io.OutputStream分别表示字节输入流和字节输出流,它们都是抽象类,不能实例化,数据流中的最小单位是字节,所以叫做字 ...

  6. Java中字节流和字符流的比较(转)

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操 ...

  7. java中字节流和字符流的区别

    流分类: 1.Java的字节流   InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先.2.Java的字符流  Reader是所有读取字符串输入流的祖先,而 ...

  8. java IO(三):字符流

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  9. Java中字节流和字符流复制文件

    字节流和字符流复制文件的过程: 1.建立两个流对象 绑定数据源和目的地 2.遍历出需复制的文件写入复制过后的新文件中(只不过是遍历的时候是区分字节和字符的) 3.访问结束后关闭资源 字节流复制文件: ...

  10. 14、IO (字节流、字符流)

    输入和输出 * A:输入和输出 * a: 参照物 * 到底是输入还是输出,都是以Java程序为参照 * b: Output * 把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作 ...

随机推荐

  1. 查看ISTIO-CITADEL的证书信息

    进行任何一个POD,查看/etc/certs目录,即可知道证书信息. kubectl exec -it reviews-v1-fd6c96c74-wptxg -c istio-proxy bash l ...

  2. msyql常用命令

    1.创建.删除数据库 create database dbname; drop database dbname; 2.选择某一个数据库 use dbname; 3.显示所有表 show tables; ...

  3. 01-C#笔记-hello_world

    /* * 主文件是 xxx.cs * 基本的 hello world 程序如下: */ using System; using System.Collections.Generic; using Sy ...

  4. hdu2281&&POJ1320——Pell方程

    hdu2281 输入一个 $N$,求最大的 $n$($n \leq N$)和 $x$,使得 $x^2 = \frac{1^2+2^2+...+n^2}{n}$. 分析: 将右边式子的分子求和化简,有: ...

  5. Python进阶-I 初识函数(function)

    函数 在java中叫方法. 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print() ...

  6. 【java异常】【redis】ERR Client sent AUTH, but no password is set

    项目中使用jedis或redisson连接redis时,如果redis没有密码,但在配置文件中写为 spring: redis: database: 0 host: 127.0.0.1 passwor ...

  7. Candy Treasure Box

    This is an interesting puzzle game. In the game, you need to use your brain, think carefully, operat ...

  8. CF Educational Round 78 (Div2)题解报告A~E

    CF Educational Round 78 (Div2)题解报告A~E A:Two Rival Students​ 依题意模拟即可 #include<bits/stdc++.h> us ...

  9. 【BZOJ3508】开灯

    [BZOJ3508]开灯 题面 bzoj 题解 其实变为目标操作和从目标操作变回来没有区别,我们考虑从目标操作变回来. 区间整体翻转(\(\text{Xor}\;1\))有点难受,我们考虑将这个操作放 ...

  10. PATB1048数字加密

    关于代码都是可以在PAT上跑通的 自己是在VS2017上写的,所以会有语句system("pause");,表示暂定方便查看结果. *在一个是VS2017中使用scanf会报错,所 ...