字节流、字符流

发布时间:2026/9/24 13:58:44
字节流、字符流 一、IO概述1.1 什么是IO生活中你肯定经历过这样的场景。当你编辑一个文本文件忘记了ctrls可能文件就白白编辑了。当你电脑上插入一个U盘可以把一个视频拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢键盘、内存、硬盘、外接设备等等。我们把这种数据的传输可以看做是一种数据的流动按照流动的方向以内存为基准分为输入input和输出output即流向内存是输入流流出内存的输出流。Java中I/O操作主要是指使用java.io包下的内容进行输入、输出操作。输入也叫做读取数据输出也叫做作写出数据。1.2 IO分类根据数据流向划分输入流和输出流输入流把数据从其他设备上读取到内存中的流。输出流把数据从内存中写出到其他设备上的流。根据数据类型划分字节流和字符流字节流以字节为单位读写数据的流。字符流以字符为单位读写数据的流。注意字节流和字符流是 Java I/O输入/输出系统中用于处理数据的两种基本方式。它们的主要区别在于处理数据的基本单位不同以及在处理文本数据时对编码的支持。字节流可以处理任何类型的文件包括图片、视频等二进制文件。不涉及字符编码转换因此不会因为编码问题导致乱码。适合处理大量数据性能较高。字符流专门设计用来处理文本数据能够自动处理字符编码转换。通过指定字符集如 UTF-8, GBK 等可以确保正确地读取和写入文本内容避免乱码问题。提供了更多的高级功能例如按行读取文本。二、字节流2.1 一切皆为字节所有文件数据文本、图片、视频等在存储时都是以二进制的形式进行存储的。2.2字节输出流【OutputStream】java.io.OutputStream抽象类是表示字节输出流的所有类的超类将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。public void close()关闭此输出流并释放与此流相关联的任何系统资源。public void flush()刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[] b)将 b.length字节从指定的字节数组写入此输出流。public void write(byte[] b, int off, int len)从指定的字节数组写入 len字节从偏移量 off开始输出到此输出流。public abstract void write(int b)将指定的字节输出流。2.3 FileOutputStream类FileOutputStream类是文件输出流用于将数据写出到文件构造方法public FileOutputStream(File file)创建文件输出流以写入由指定的 File对象表示的文件。public FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。当你创建一个流对象时必须传入一个文件路径。该路径下如果没有这个文件会创建该文件。如果有这个文件会清空这个文件的数据public class FileOutputStreamConstructor throws IOException {public static void main(String[] args) {// 使用File对象创建流对象File file new File(a.txt);FileOutputStream fos new FileOutputStream(file);// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(b.txt);}}写出字节数据写出字节write(int b)方法每次可以写出一个字节数据代码使用演示public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt);// 写出数据fos.write(97); // 写出第1个字节fos.write(98); // 写出第2个字节fos.write(99); // 写出第3个字节// 关闭资源fos.close();}}小贴士虽然参数为int类型四个字节但是只会保留一个字节的信息写出。流操作完毕后必须释放系统资源调用close方法千万记得。注任意文件在通过文本编辑器记事本、notepad打开的时候都得查询编码表其中 0-127 查询 ascII码表其它 查询系统默认表(中文查询GBK表)写出字节数组write(byte[] b)每次可以写出数组中的数据代码使用演示public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt);// 字符串转换为字节数组byte[] b 程序员.getBytes();// 写出字节数组数据fos.write(b);// 关闭资源fos.close();}}输出结果程序员写出指定长度字节数组write(byte[] b, int off, int len),每次写出从off索引开始len个字节代码使用演示public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txt);// 字符串转换为字节数组byte[] b abcde.getBytes();// 写出从索引2开始2个字节。索引2是c两个字节也就是cd。fos.write(b,2,2);// 关闭资源fos.close();}}输出结果cd数据追加续写经过以上的演示每次程序运行创建输出流对象都会清空目标文件中的数据。如何保留目标文件中数据还能继续添加新数据呢public FileOutputStream(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。public FileOutputStream(String name, boolean append) 创建文件输出流以指定的名称写入文件。这两个构造方法参数中都需要传入一个boolean类型的值true表示追加数据false表示清空原有数据。这样创建的输出流对象就可以指定是否追加续写了代码使用演示public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos new FileOutputStream(fos.txttrue);// 字符串转换为字节数组byte[] b abcde.getBytes();// 写出从索引2开始2个字节。索引2是c两个字节也就是cd。fos.write(b);// 关闭资源fos.close();}}文件操作前cd文件操作后cdabcde写出换行Windows系统里换行符号是\r\n。把 boolean append参数传入 FileOutputStream流中创建输出流对象就可以指定是否追加续写了回车符\r和换行符\n回车符回到一行的开头return。换行符下一行newline。系统中的换行Windows系统里每行结尾是回车换行即\r\nUnix系统里每行结尾只有换行即\nMac系统里每行结尾是回车即\r。从 Mac OS X开始与Linux统一。2.4 字节输入流【InputStream】java.io.InputStream抽象类是表示字节输入流的所有类的超类可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。public void close()关闭此输入流并释放与此流相关联的任何系统资源。public abstract int read() 从输入流读取数据的下一个字节。public int read(byte[] b) 从输入流中读取一些字节数并将它们存储到字节数组 b中 。2.5 FileInputStream类java.io.FileInputStream类是文件输入流从文件中读取字节。构造方法FileInputStream(File file) 通过打开与实际文件的连接来创建一个 FileInputStream 该文件由文件系统中的 File对象 file命名。FileInputStream(String name) 通过打开与实际文件的连接来创建一个 FileInputStream 该文件由文件系统中的路径名 name命名。当你创建一个流对象时必须传入一个文件路径。该路径下如果没有该文件,会抛出FileNotFoundException。构造举例代码如下public class FileInputStreamConstructor throws IOException{public static void main(String[] args) {// 使用File对象创建流对象File file new File(a.txt);FileInputStream fos new FileInputStream(file);// 使用文件名称创建流对象FileInputStream fos new FileInputStream(b.txt);}}读取字节数据读取字节read方法每次可以读取一个字节的数据提升为int类型读取到文件末尾返回-1代码使用演示public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象FileInputStream fis new FileInputStream(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);// 读取到末尾,返回-1read fis.read();System.out.println( read);// 关闭资源fis.close();}}输出结果abcde-1也可以使用循环的方式小贴士虽然读取了一个字节但是会自动提升为int类型。流操作完毕后必须释放系统资源调用close方法千万记得。使用字节数组读取read(byte[] b)每次读取b的长度个字节到数组中返回读取到的有效字节个数通过len获取有效的字节 返回-1代码使用演示public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象.FileInputStream fis new FileInputStream(read.txt); // 文件中为abcde// 定义变量作为有效个数int len // 定义字节数组作为装字节数据的容器byte[] b new byte[2];// 循环读取while (( len fis.read(b))!-1) {// 每次读取后,把数组的有效字节部分变成字符串打印System.out.println(new String(b0len));// len 每次读取的有效字节个数}// 关闭资源fis.close();}}输出结果abcde三、字符流当使用字节流读取文本文件时可能会有一个小问题。就是遇到中文字符时可能不会显示完整的字符那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类以字符为单位读写数据专门用于处理文本文件。3.1 字符输入流【Reader】java.io.Reader抽象类是表示用于读取字符流的所有类的超类可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。public void close()关闭此流并释放与此流相关联的任何系统资源。public int read() 从输入流读取一个字符。public int read(char[] cbuf) 从输入流中读取一些字符并将它们存储到字符数组 cbuf中3.2 FileReader类java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。小贴士字符编码字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。idea中UTF-8字节缓冲区一个字节数组用来临时存储字节数据。构造方法FileReader(File file) 创建一个新的 FileReader 给定要读取的File对象。FileReader(String fileName) 创建一个新的 FileReader 给定要读取的文件的名称。当你创建一个流对象时必须传入一个文件路径。类似于FileInputStream 。构造举例代码如下public class FileReaderConstructor throws IOException{public static void main(String[] args) {// 使用File对象创建流对象File file new File(a.txt);FileReader fr new FileReader(file);// 使用文件名称创建流对象FileReader fr new FileReader(b.txt);}}读取字符数据读取字符read方法每次可以读取一个字符的数据提升为int类型读取到文件末尾返回-1循环读取使用字符数组读取read(char[] cbuf)每次读取b的长度个字符到数组中返回读取到的有效字符个数读取到末尾时返回-1代码使用演示public class FISRead {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileReader fr new FileReader(read.txt);// 定义变量保存有效字符个数int len // 定义字符数组作为装字符数据的容器char[] cbuf new char[2];// 循环读取while ((len fr.read(cbuf))!-1) {System.out.println(new String(cbuf,0,len));}// 关闭资源fr.close();}}输出结果程序员3.3 字符输出流【Writer】java.io.Writer抽象类是表示用于写出字符流的所有类的超类将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。void write(int c)写入单个字符。void write(char[] cbuf)写入字符数组。abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。void write(String str)写入字符串。void write(String str, int off, int len)写入字符串的某一部分,off字符串的开始索引,len写的字符个数。void flush()刷新该流的缓冲。void close()关闭此流但要先刷新它。3.4 FileWriter类java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。构造方法FileWriter(File file) 创建一个新的 FileWriter给定要读取的File对象。FileWriter(String fileName) 创建一个新的 FileWriter给定要读取的文件的名称。当你创建一个流对象时必须传入一个文件路径类似于FileOutputStream。构造举例代码如下public class FileWriterConstructor {public static void main(String[] args) throws IOException {// 使用File对象创建流对象File file new File(a.txt);FileWriter fw new FileWriter(file);// 使用文件名称创建流对象FileWriter fw new FileWriter(b.txt);}}基本写出数据写出字符write(int b)方法每次可以写出一个字符数据代码使用演示public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw new FileWriter(fw.txt);// 写出数据fw.write(97); // 写出第1个字符fw.write(b); // 写出第2个字符fw.write(C); // 写出第3个字符fw.write(30000); // 写出第4个字符中文编码表中30000对应一个汉字。/*【注意】关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区并未保存到文件。*/// fw.close();}}输出结果abC田小贴士虽然参数为int类型四个字节但是只会保留一个字符的信息写出。未调用close方法数据只是保存到了缓冲区并未写出到文件中。关闭和刷新因为内置缓冲区的原因如果不关闭输出流无法写出字符到文件中。但是关闭的流对象是无法继续写出数据的。如果我们既想写出数据又想继续使用流就需要flush方法了。flush刷新缓冲区流对象可以继续使用。close:先刷新缓冲区然后通知系统释放资源。流对象不可以再被使用了。代码使用演示public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw new FileWriter(fw.txt);// 写出数据通过flushfw.write(刷); // 写出第1个字符fw.flush();fw.write(新); // 继续写出第2个字符写出成功fw.flush();// 写出数据通过closefw.write(关); // 写出第1个字符fw.close();fw.write(闭); // 继续写出第2个字符,【报错】java.io.IOException: Stream closedfw.close();}}写出其他数据写出字符数组write(char[] cbuf)和write(char[] cbuf, int off, int len)每次可以写出字符数组中的数据用法类似FileOutputStream写出字符串write(String str)和write(String str, int off, int len)每次可以写出字符串中的数据更为方便代码使用演示续写和换行操作类似于FileOutputStream。public void textRead() throws IOException { // 使用文件名称创建流对象 FileWriter fw new FileWriter(b.txt,true); // 字符串转换为字节数组 char[] chars 程序员.toCharArray(); // 写出字符数组 fw.write(chars); // 程序员// 写出换行 fw.write(\r\n);// 写出从索引2开始2个字节。索引2是程两个字节也就是程序。 fw.write(chars,1,2); // 程序 // 关闭资源 fw.close(); }