文章目录

  • 一. java流的三大类
    • 1. 输出流和输入流
    • 2. 字节流和字符流
    • 3. 节点流和处理流
  • 二. 字节流
    • 1. 文件流 FIS和FOS
      • 1.1 文件输出流:FileOutputStream
      • 1.2 文件输入流:FileInputStream
    • 2 缓冲字节流BOS和BIS
    • 3. 对象流OIS和OOS
      • 3.1 ObjectOutputStream
      • 3.2 ObjectInputStream
      • 3.3 Serializable接口
  • 三. 字符流
    • 1. 转换流ISR和OSW
    • 2. 缓冲字符输出流:BW和PW(自动行刷新)
    • 3. 缓冲字符输入流BufferedReader

一. java流的三大类

相关文章推荐 总结java-API-IO流必会概念

1. 输出流和输入流

  • java io可以让我们用标准的读写操作来完成对不同设备的读写数据工作.
  • java将IO按照方向划分为输入与输出,参照点是我们写的程序.
  • 输入:用来读取数据的,是从外界到程序的方向,用于获取数据.
  • 输出:用来写出数据的,是从程序到外界的方向,用于发送数据.

IO:Input,Output 即:输入与输出

JAVA IO用于我们程序可以和外界交换数据。用于与外界的数据进行读写操作的。

java中将输入与输出比喻为"流":stream
如何理解流:讲流想象为一个连接我们程序和另一端的"管道",在其中按照同一方向顺序移动的数据。
有点像"水管"中向着统一方向流动的水。

输入流: 读取操作:从外界向我们的程序中移动的方向,因此是用来获取数据的流

输出流:写出操作
** 注意:流是单向的,输入永远用来读,输出永远用来写。将来我们在实际开发中希望与程序交互的另一端**
互相发送数据时,我们只需要创建一个可以连接另一端的"流",进行读写操作完成。

2. 字节流和字符流

00000000 8位2进制 1byte 1字节
1024byte = 1kb
1024kb = 1mb
1024mb = 1gb
1024gb = 1tb

java将流按照读写单位划分为字节流与字符流.

  • java.io.InputStream和OutputStream是所有字节流的超类
  • 而java.io.Reader和Writer则是所有字符流的超类,它们和字节流的超类是平级关系.
  • Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
  • 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符
  • 流完成

Java定义了两个超类(抽象类):
java.io.InputStream:所有字节输入流的超类(抽象类),里面定义了读取字节的相关方法。所有字节输入流都继承自它
java.io.OutputStream:所有字节输出流的超类(抽象类),里面定义了写出字节的相关方法。所有的字节输出流都继承自它

3. 节点流和处理流

java将流分为两类:节点流与处理流:
节点流:俗称"低级流",特点:真实连接我们程序和另一端的"管道",负责实际读写数据的流
文件流就是典型的节点流,真实连接我们程序与文件的"管道",可以读写文件数据了。
处理流:俗称"高级流"
特点:
1:不能独立存在(单独实例化进行读写操作不可以)
2:必须连接在其他流上,目的是当数据"流经"当前流时,可以对其做某种加工操作,简化我们的工作、
流的连接:实际开发中经常会串联一组高级流最终到某个低级流上,对数据进行流水线式的加工读写。

实际应用中,我们可以通过串联一组高级流到某个低级流上以流水线式的加工处理对某设备的数据进行读写,这个过程也成为流的连接,这也是IO的精髓所在.

二. 字节流

1. 文件流 FIS和FOS

java.io.FileInputStream和java.io.FileOutputStream
作用是真实连接我们程序和文件之间的"管道"。其中文件输入流用于从文件中读取字节。而文件输出流则
用于向文件中写入字节。

1.1 文件输出流:FileOutputStream

package io;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class FOSDemo {public static void main(String[] args) throws IOException {//需求:向当前目录的文件fos.dat中写入数据/*在创建文件输出流时,文件输出流常见的构造器:FileOutputStream(String filename)上述构造器会在创建时将该文件创建出来(如果该文件不存在才会这样做),自动创建该文件的前提是该文件所在的目录必须存在,否则会抛出异常。     一个小技巧:在指定相对路径时,如果是从"当前目录"(./)开始的,那么"./"是可以忽略不写的因为在相对路径中,默认就是从"./"开始*/
//        FileOutputStream fos = new FileOutputStream("./fos.dat");FileOutputStream fos = new FileOutputStream("fos.dat");//与上面一句位置相同/*OutputStream(所有字节输出流的超类)中定义了写出字节的方法:其中:void write(int d)写出一个字节,将给定的参数int值对应的2进制的"低八位"写出。文件输出流继承OutputStream后就重写了该方法,作用是将该字节写入到文件中。     向文件中写入1个字节fow.write(1)将int值的1对应的2进制的"低八位"写如到文件第一个字节位置上1个int值占4个字节,每个字节是一个8为2进制int 1的2进制样子:00000000 00000000 00000000 00000001^^^^^^^^写出的字节write方法调用后,fos.dat文件中就有了1个字节,内容为:00000001再次调用:fos.write(2)int 2的2进制样子:00000000 00000000 00000000 00000010^^^^^^^^写出的字节write方法调用后,fos.dat文件中就有了2个字节,内容为:00000001 00000010上次写的   本次写的*/fos.write(1);fos.write(2);System.out.println("写出完毕!");//注意!流使用完毕后要关闭,来释放底层资源fos.close();}
}

1.2 文件输入流:FileInputStream

package io;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;/*** 使用文件输入流读取文件中的数据*/
public class FISDemo {public static void main(String[] args) throws IOException {//将fos.dat文件中的字节读取回来/*fos.dat文件中的数据:00000001 00000010*/FileInputStream fis = new FileInputStream("fos.dat");/*java.io.InputStream(所有字节输入流的超类)定义着读取字节的相关方法int read()读取1个字节并以int型整数返回读取到的字节内容,返回的int值中对应的2进制的"低八位"就是读取到的数据。如果返回的int值为整数-1(这是一个特殊值,32位2进制全都是1)表达的是流读取到了末尾了。int read(byte[] data)文件输入流重写了上述两个方法用来从文件中读取对应的字节。*//*fos.dat文件中的数据:00000001 00000010^^^^^^^^第一次读取的字节当我们第一次调用:int d = fis.read();//读取的是文件中第一个字节该int值d对应的2进制:00000000 00000000 00000000 00000001|------自动补充24个0-------| ^^^^^^^^读取到的数据而该2进制对应的整数就是1.*/int d = fis.read();//读取到的就是整数1System.out.println(d);/*fos.dat文件中的数据:00000001 00000010^^^^^^^^第二次读取的字节当我们第二次调用:d = fis.read();//读取的是文件中第二个字节该int值d对应的2进制:00000000 00000000 00000000 00000010|------自动补充24个0-------| ^^^^^^^^读取到的数据而该2进制对应的整数就是2.*/d = fis.read();//2System.out.println(d);/*fos.dat文件中的数据:00000001 00000010 文件末尾^^^^^^^^没有第三个字节当我们第三次调用:d = fis.read();//读取到文件末尾了!该int值d对应的2进制:11111111 11111111 11111111 11111111该数字是正常读取1个字节永远表达不了的值。并且-1的2进制格式好记。因此用它表达读取到了末尾。*/d = fis.read();//-1System.out.println(d);fis.close();}
}

1.3 文件复制

package io;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;/*** 利用文件输入流与输出流实现文件的复制操作*/
public class CopyDemo {public static void main(String[] args) throws IOException {//用文件输入流读取待复制的文件
//        FileInputStream fis = new FileInputStream("image.jpg");FileInputStream fis = new FileInputStream("01.rmvb");//用文件输出流向复制文件中写入复制的数据
//        FileOutputStream fos = new FileOutputStream("image_cp.jpg");FileOutputStream fos = new FileOutputStream("01_cp.rmvb");/*原文件image.jpg中的数据10100011 00111100 00001111 11110000....^^^^^^^^读取该字节第一次调用:int d = fis.read();d的2进制:00000000 00000000 00000000 10100011读到的字节fos向复制的文件image_cp.jpg中写入字节第一次调用:fos.write(d);作用:将给定的int值d的2进制的"低八位"写入到文件中d的2进制:00000000 00000000 00000000 10100011写出字节调用后image_cp.jpg文件数据:10100011循环条件是只要文件没有读到末尾就应该复制如何直到读取到末尾了呢?前提是:要先尝试读取一个字节,如果返回值是-1就说明读到末尾了如果返回值不是-1,则说明读取到的是一个字节的内容,就要将他写入到复制文件中*/int d;//先定义一个变量,用于记录每次读取到的数据long start = System.currentTimeMillis();//获取当前系统时间while ((d = fis.read()) != -1) {fos.write(d);}long end = System.currentTimeMillis();System.out.println("复制完毕!耗时:" + (end - start) + "ms");fis.close();fos.close();}
}

1.4 块读写的文件复制操作–3个方法

int read(byte[] data) 一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。 返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。

块写操作 void write(byte[] data) 一次性将给定的字节数组所有字节写入到文件中

void write(byte[] data,int offset,int len) 一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件

package io;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;/*** 通过提高每次读写的数据,减少读写次数可以提高读写效率。*/
public class CopyDemo2 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("01.rmvb");FileOutputStream fos = new FileOutputStream("01_cp.rmvb");/块读:一次性读取一组字节块写:一次性将写出一组字节java.io.InputStream上定义了块读字节的方法:int read(byte[] data)一次性读取给定字节数组length个字节并从头开始装入到数组中。返回值为实际读取到的字节量如果返回值为-1则表示流读取到了末尾。文件流重写了该方法,作用是块读文件里的数据。java.io.OutputStream上定义了块写字节的方法:void write(byte[] data)一次性将给定的字节数组中所有的字节写出。void write(byte[] data,int offset,int len)一次性将给定的字节数组data中从下标offset处开始的连续len个字节写出。原文件数据(假设文件共6个字节):11110000 00001111 01010101 11111111 00000000 10101010byte[] buf = new byte[4];//创建一个长度为4的字节数组buf默认的样子(每个元素若以2进制表现):{00000000,00000000,00000000,00000000}int len;//记录每次实际读取的字节数当第一次调用:len = fis.read(buf);由于字节数组buf的长度为4.因此可以一次性最多从文件中读取4个字节并装入到buf数组中返回值len表示的整数是这次实际读取到了几个字节。原文件数据(假设文件共6个字节):11110000 00001111 01010101 11111111 00000000 10101010^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^第一次读取的4个字节buf:{11110000,00001111,01010101,11111111}len:4 表示本次读取到了4个字节第二次调用:len = fis.read(buf);原文件数据(假设文件共6个字节):11110000 00001111 01010101 11111111 00000000 10101010 文件末尾了^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^本次实际只能读取到2个字节buf:{00000000,10101010,01010101,11111111}|本次新读的2字节数据| |---上次的旧数据---|len:2表示本次实际只读取到了2个字节。它的意义就是告诉你buf数组中前几个字节是本次真实读取到的数据第三次调用:len = fis.read(buf);原文件数据(假设文件共6个字节):11110000 00001111 01010101 11111111 00000000 10101010 文件末尾了^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^buf:{00000000,10101010,01010101,11111111} 没有任何变化!len:-1 表示本次读取时已经是文件末尾了!!编译完该句代码:byte[] buf = new byte[10240];在实际开发中,有时候用一个计算表达式更能表现这个值的含义时,我们不妨使用计算表达式long t = 864000000;long t = 60 * 60 * 24 * 1000;/byte[] buf = new byte[1024 * 10];//10kbint len;//记录每次实际读取到的字节数long start = System.currentTimeMillis();while ((len = fis.read(buf)) != -1) {fos.write(buf, 0, len);}long end = System.currentTimeMillis();System.out.println("复制完毕,耗时:" + (end - start) + "ms");fis.close();fos.close();}
}

1.5 写文本数据 byte[] getBytes(UTF-8)

String提供方法: byte[] getBytes(String charsetName) 将当前字符串转换为一组字节

参数为字符集的名字,常用的是UTF-8。 其中中文字3字节表示1个,英文1字节表示1个。

package io;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 使用文件输出流向文件中写入文本数据*/
public class WriteStringDemo {public static void main(String[] args) throws IOException {/*1:创建一个文件输出流2:将写出的文字先转换为2进制(一组字节)3:关闭流文件流有两种创建方式:1:覆盖模式,对应的构造器:FileOutputStream(String filename)FileOutputStream(File file)所谓覆盖模式:文件流在创建是若发现该文件已存在,则会将该文件原内容全部删除。然后在陆续将通过该流写出的内容保存到文件中。        */FileOutputStream fos = new FileOutputStream("fos.txt",true);String line = "让我再看你一遍,从南到北。";/*String提供了将内容转换为一组字节的方法:getBytes()java.nio.charset.StandardCharsets*/byte[] data = line.getBytes(StandardCharsets.UTF_8);fos.write(data);line = "像是北五环路蒙住的双眼。";data = line.getBytes(StandardCharsets.UTF_8);fos.write(data);       System.out.println("写出完毕!");fos.close();}
}

1.6文件输出流-追加模式

重载的构造方法可以将文件输出流创建为追加模式

  • FileOutputStream(String path,boolean append)
  • FileOutputStream(File file,boolean append)

当第二个参数传入true时,文件流为追加模式,即:指定的文件若存在,则原有数据保留,新写入的数据会被顺序的追加到文件中

package io;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 使用文件输出流向文件中写入文本数据*/
public class WriteStringDemo {public static void main(String[] args) throws IOException {/1:创建一个文件输出流2:将写出的文字先转换为2进制(一组字节)3:关闭流文件流有两种创建方式:1:覆盖模式,对应的构造器:FileOutputStream(String filename)FileOutputStream(File file)所谓覆盖模式:文件流在创建是若发现该文件已存在,则会将该文件原内容全部删除。然后在陆续将通过该流写出的内容保存到文件中。2:追加模式,对应的构造器FileOutputStream(String filename,boolean append)FileOutputStream(File file,boolean append)当第二个参数为true时,那么就是追加模式。所谓追加模式:文件流在创建时若发现该文件已存在,则原内容都保留。通过当前流陆续写出的内容都会被陆续追加到文件末尾。/FileOutputStream fos = new FileOutputStream("fos.txt",true);String line = "斯国一!";byte[] data = line.getBytes(StandardCharsets.UTF_8);fos.write(data);line = "奥里给!";data = line.getBytes(StandardCharsets.UTF_8);fos.write(data);System.out.println("写出完毕!");fos.close();}
}

1.7 读取文本数据

package io;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 从文件中读取文本数据*/
public class ReadStringDemo {public static void main(String[] args) throws IOException {/*1:创建一个文件输入流2:从文件中将字节都读取回来3:将读取到的字节转换回字符串*/FileInputStream fis = new FileInputStream("fos.txt");byte[] data = new byte[1024];//1kbint len = fis.read(data);//块读操作,返回值表达实际读取到了多少字节System.out.println("实际读取了:"+len+"个字节");/String提供了构造方法可以将一个字节数组还原为字符串String(byte[] data,Charset charset)将给定的字节数组data中所有字节按照给定的字符集转换为字符串。String(byte[] data,int offset,int len,Charset charset)将给定的字节数组data从下标offset处开始的连续len个字节按照指定的字符集转换为字符串/String line = new String(data,0,len,StandardCharsets.UTF_8);System.out.println(line.length());//输出字符串长度System.out.println(line);fis.close();}
}

2 缓冲字节流BOS和BIS

java.io.BufferedOutputStream和BufferedInputStream.缓冲流是一对高级流,作用是提高读写数据的效率.

缓冲流内部有一个字节数组,默认长度是8K.缓冲流读写数据时一定是将数据的读写方式转换为块读写来保证读写效率.

package io;import java.io.*;/* 缓冲流,是一对高级流,作用是加快读写效率。* java.io.BufferedInputStream和java.io.BufferedOutputStream**/
public class CopyDemo3 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("ppt.pptx");BufferedInputStream bis = new BufferedInputStream(fis);FileOutputStream fos = new FileOutputStream("ppt_cp.pptx");BufferedOutputStream bos = new BufferedOutputStream(fos);int d;long start = System.currentTimeMillis();while((d = bis.read())!=-1){//使用缓冲流读取字节bos.write(d);//使用缓冲流写出字节}long end = System.currentTimeMillis();System.out.println("耗时:"+(end-start)+"ms");bis.close();//关闭流时只需要关闭高级流即可,它会自动关闭它连接的流bos.close();}
}

缓冲输出流写出数据时的缓冲区问题

通过缓冲流写出的数据会被临时存入缓冲流内部的字节数组,直到数组存满数据才会真实写出一次

package io;import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;/*** 缓冲输出流写出数据的缓冲区问题*/
public class BOS_FlushDemo {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("bos.txt");BufferedOutputStream bos = new BufferedOutputStream(fos);String line = "奥里给!";byte[] data = line.getBytes(StandardCharsets.UTF_8);bos.write(data);System.out.println("写出完毕!");/缓冲流的flush方法用于强制将缓冲区中已经缓存的数据一次性写出。注:该方法实际上实在字节输出流的超类OutputStream上定义的,并非只有缓冲输出流有这个方法。但是实际上只有缓冲输出流的该方法有实际意义,其他的流实现该方法的目的仅仅是为了在流连接过程中传递flush动作给缓冲输出流。/bos.flush();//冲bos.close();}
}

3. 对象流OIS和OOS

java.io.ObjectOutputStream和ObjectInputSteam

对象流是一对高级流,在流连接中的作用是进行对象的序列化与反序列化。

对象序列化:将一个java对象按照其结构转换为一组字节的过程

对象反序列化:将一组字节还原为java对象(前提是这组字节是一个对象序列化得到的字节)

3.1 ObjectOutputStream

package io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;/* 对象序列化* java.io.ObjectInputStream和ObjectOutputStream* 它们是一对高级流,在流连接中负责进行对象的序列化与反序列化* 对象序列化:将一个java对象按照其结构转换为一组字节的过程* 对象反序列化:将一组字节按照其描述还原为一个java对象的过程*/
public class OOSDemo {public static void main(String[] args) throws IOException {//将一个Person对象写入文件person.obj中String name = "刘桑";int age = 55;String gender = "男";String[] otherInfo = {"拍片技术一流","技术好","大家的启蒙老师"};Person p = new Person(name,age,gender,otherInfo);FileOutputStream fos = new FileOutputStream("person.obj");ObjectOutputStream oos = new ObjectOutputStream(fos);/当我们将对象输出流连接到文件流上,把一个对象写出时,会经历以下操作:1:对象先经过对象输出流writeObject(p)该方法会将该对象按照其结构转换为一组字节,这个过程称为对象序列化2:对象输出流会将序列化后的一组字节再经过其连接的文件输出流最终将这组字节写入到文件中保存(写入到磁盘),该过程称为:数据持久化。执行writeObject()进行序列化对象是抛出异常:java.io.NotSerializableException原因:对象输出流在序列化是要求序列化的对象必须实现了接口:java.io.Serializable/oos.writeObject(p);System.out.println("写出完毕!");oos.close();}
}
package io;
import java.io.Serializable;
import java.util.Arrays;/***  java:爪哇 bean:豆子*  JAVA BEAN设计规范*  1:属性私有化*  2:为属性提供公开的get和set方法*  3:要有公开的无参构造器*/
public class Person implements Serializable {private String name;private int age;private String gender;private String[] otherInfo;public Person(){}public Person(String name, int age, String gender, String[] otherInfo) {this.name = name;this.age = age;this.gender = gender;this.otherInfo = otherInfo;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String[] getOtherInfo() {return otherInfo;}public void setOtherInfo(String[] otherInfo) {this.otherInfo = otherInfo;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", gender='" + gender + '\'' +", otherInfo=" + Arrays.toString(otherInfo) +'}';}
}

3.2 ObjectInputStream

package io;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;/*** 使用对象输入流完成对象的反序列化*/
public class OISDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//从person.obj文件中将对象反序列化回来FileInputStream fis = new FileInputStream("person.obj");ObjectInputStream ois = new ObjectInputStream(fis);/*Object readObject()该方法会进行对象的反序列化,如果对象流通过其连接的流读取的字节分析并非是一个java对象时,会抛出异常:ClassNotFoundException需要*/Person p = (Person)ois.readObject();System.out.println(p);}
}

3.3 Serializable接口

需要进行序列化的类必须实现接口:java.io.Serializable 实现序列化接口后最好主动定义序列化版本号这个常量。 这样一来对象序列化时就不会根据类的结构生成一个版本号,而是使用该固定值。 那么反序列化时,只要还原的对象和当前类的版本号一致就可以进行还原。

transient关键字
可以修饰属性,用于在进行对象序列化时忽略不必要的属性,达到对象瘦身的目的

package io;import java.io.Serializable;
import java.util.Arrays;/*** 使用当前类实例测试对象流的读写操作*/
public class Person implements Serializable {public static final long serialVersionUID = 1L;private String name;//姓名private int age;//年龄private String gender;//性别private String[] otherInfo;//其他信息public Person(String name, int age, String gender, String[] otherInfo) {this.name = name;this.age = age;this.gender = gender;this.otherInfo = otherInfo;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String[] getOtherInfo() {return otherInfo;}public void setOtherInfo(String[] otherInfo) {this.otherInfo = otherInfo;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", gender='" + gender + '\'' +", otherInfo=" + Arrays.toString(otherInfo) +'}';}
}

三. 字符流

  • java将流按照读写单位划分为字节流与字符流.
  • java.io.InputStream和OutputStream是所有字节流的超类
  • 而java.io.Reader和Writer则是所有字符流的超类,它们和字节流的超类是平级关系.
  • Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
  • 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成.

1. 转换流ISR和OSW

java.io.InputStreamReader和OutputStreamWriter
作用:

  • 1:衔接字节流与其他字符流
  • 2:将字符与字节相互转换

它们是字符流非常常用的一对实现类同时也是一对高级流,实际开发中我们不直接操作它们,但是它们在流连接中是非常重要的一环.

由于字符流最小读写单位为字符,因此字符流【只适合读写文本数据】

使用转换输出流向文件中写入文本数据

package io;import java.io.*;
import java.nio.charset.StandardCharsets;
public class OSWDemo {public static void main(String[] args) throws IOException {/*使用这一对流演示转换流的读写字符方法java.io.Writer所有字符输出流的超类上,定义了写出字符的相关方法void write(int d)写出一个字符,实际传入的应当是一个char。void write(char[] data)void write(char[] data,int offset,int len)void write(String str) 直接写出一个字符串*/FileOutputStream fos = new FileOutputStream("osw.txt");OutputStreamWriter osw = new OutputStreamWriter(fos,StandardCharsets.UTF_8);String line = "如果你突然打了个喷嚏,那一定就是我在想你。";osw.write(line);//转换流的write(String str)会将写出的字符串转换为字节然后写出osw.write("如果半夜被手机吵醒,那一定就是我关心。");System.out.println("写出完毕!");osw.close();}
}

使用转换输入流读取文本文件

package io;import java.io.*;/*** 转换字符输入流* 可以将读取的字节按照指定的字符集转换为字符*/
public class ISRDemo {public static void main(String[] args) throws IOException {//将osw.txt文件中的所有文字读取回来.FileInputStream fis = new FileInputStream("osw.txt");InputStreamReader isr = new InputStreamReader(fis,"UTF-8");/*字符流读一个字符的read方法定义:int read()读取一个字符,返回的int值实际上表示的是一个char(低16位有效).如果返回的int值表示的是-1则说明EOF*///测试读取文件中第一个字
//        int d = isr.read();
//        char c = (char)d;
//        System.out.println(c);//循环将文件所有字符读取回来int d;while((d = isr.read()) != -1){System.out.print((char)d);}isr.close();}
}

转换流的意义:------负责字符与字节的实际转换

实际开发中我们还有功能更好用的字符高级流.但是其他的字符高级流都有一个共通点:不能直接连接在字节流上.而实际操作设备的流都是低级流同时也都是字节流.因此不能直接在流连接中串联起来.转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上.在流连接中起到"转换器"的作用

2. 缓冲字符输出流:BW和PW(自动行刷新)

java.io.BufferedWriter和BufferedReader

  • 缓冲字符流(是一对高级流)
  • 缓冲流内部维护一个char数组,默认长度8k.以块读写方式读写字符数据保证效率
  • java.io.PrintWriter则是具有自动行刷新的换成字符输出流(实际缓冲功能是靠BufferedWriter实现的,它内部总是连接着这个流。
  • 使用缓冲字符流后就可以实现按行读写字符串,并且读写效率高。
    PrintWriter继承自Writer.
    它提供很多构造方法,其中就有可以直接对文件进行写操作的构造器
    PrintWriter(File file)
    PrintWriter(String filename)

字符集(UTF-8)只能以字符串形式表达。因此注意拼写。字符集不区分大小写。

但是如果字符集名字拼写错误,会抛出异常:
UnsupportedEncodingException
不支持的 字符集 异常

如果实例化PW时第一个参数传入的是一个流,则此时可以再传入一个boolean型的参数,此值为true时就打开了自动行刷新功能。 即: 每当我们用PW的println方法写出一行字符串后会自动flush.
此时每当我们调用它的println方法写出一行字符串后就会自动flush()一次。
注意:print方法和write方法写出字符串时并不会自动flush()!!!

package io;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
public class PWDemo1 {public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {PrintWriter pw = new PrintWriter("pw.txt");     //这里可以按照指定的字符集写出字符串到文本文件中。      PrintWriter pw = new PrintWriter("pw.txt","UTF-8");/*println()方法是输出字符出后带上换行符print()方法输出字符串后不带换行符*/pw.println("夜空中最亮的星,能否听清。");pw.println("那仰望的人,心底的孤独和叹息。");System.out.println("写出完毕!");pw.close();}
}

在流链接中使用PW

package io;import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** 练习PrintWriter的流连接操作*/
public class PWDemo2 {public static void main(String[] args) throws FileNotFoundException {//文件输出流(低级流,字节流) 作用:向文件中写出字节FileOutputStream fos = new FileOutputStream("pw2.txt");//转换输出流(高级流,字符流) 作用:1衔接字符与字节流的 2:将写出的字符转换为字节OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);//缓冲字符输出流(高级流,字符流) 作用:块写文本数据加速的(内部有一个8k的char数组)BufferedWriter bw = new BufferedWriter(osw);//具有自动行刷新功能(高级流,字符流) 作用:1按行写出字符串(println) 2:自动行刷新PrintWriter pw = new PrintWriter(bw);/*完成一个简易记事本工具将控制台上输入的每一行字符串按行写入到该文件中如果单独输入exit,则程序退出。思路:用一个死循环,重复做下面的工作1:在控制台上输入一行字符串2:判断输入的字符串是否为"exit"若是:则break掉循环退出程序若不是:则将输入的字符串通过println方法写入文件*/Scanner scanner = new Scanner(System.in);while(true) {String line = scanner.nextLine();if("exit".equals(line)){break;}pw.println(line);}System.out.println("写出完毕!");pw.close();}
}

完成一个简易记事本工具

package io;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** 练习PrintWriter的流连接操作*/
public class PWDemo2 {public static void main(String[] args) throws FileNotFoundException {//文件输出流(低级流,字节流) 作用:向文件中写出字节FileOutputStream fos = new FileOutputStream("pw2.txt");//转换输出流(高级流,字符流) 作用:1衔接字符与字节流的 2:将写出的字符转换为字节OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);//缓冲字符输出流(高级流,字符流) 作用:块写文本数据加速的(内部有一个8k的char数组)BufferedWriter bw = new BufferedWriter(osw);//具有自动行刷新功能(高级流,字符流) 作用:1按行写出字符串(println) 2:自动行刷新PrintWriter pw = new PrintWriter(bw,true);Scanner scanner = new Scanner(System.in);while(true) {String line = scanner.nextLine();if("exit".equals(line)){break;}pw.println(line);
//           pw.print("");//不会自动flush
//           pw.write("");//不会自动flush}System.out.println("写出完毕!");pw.close();}
}

3. 缓冲字符输入流BufferedReader

java.io.BufferedWriter和BufferedReader

  • 缓冲字符流(是一对高级流)
  • 缓冲流内部维护一个char数组,默认长度8k.以块读写方式读写字符数据保证效率

缓冲字符输入流:java.io.BufferedReader
使用缓冲字符输入流按行读取字符串
该高级流的主要作用:
1:块读文本数据加速(内部有一个默认8k的char数组)
2:可以按行读取字符串
常用方法
提供了一个独有的方法:readLine()
作用:读取一行字符串。连续读取若干字符直到遇到了换行符位置,并将换行符之前的 内容返回。
注意:返回的字符串里不包含最后的换行符。

特殊情况:
如果这一行只有一个换行符,那么返回值为空字符串:“”
如果读取到了流的末尾,那么返回值为null。

实际运行时:
当我们第一次调用readLine()方法时,缓冲字符输入流实际会一次性读取8k的char回来并存入内部的char数组中(块读文本操作)。readLine方法只将char数组中从头开始一直到第一个换行符位置的内容以一个字符串形式返回。

package io;
import java.io.*;
public class BRDemo {public static void main(String[] args) throws IOException {//将当前源代码输出到控制台上//文件输入流(低级流,字节流) 作用:从文件中读取字节FileInputStream fis = new FileInputStream("./src/io/BRDemo.java");//转换输入流(字符流,高级流) 作用:1衔接字节与字符流 2将读取的字节转换为字符InputStreamReader isr = new InputStreamReader(fis);//缓冲字符输入流(字符流,高级流) 作用:1块读字符数据加速  2按行读取字符串BufferedReader br = new BufferedReader(isr);String line;while((line = br.readLine()) != null){System.out.println(line);}br.close();}
}

day27-API-java流的三大分类,常用的流(文件流,对象流, 缓冲流, 转换流, PW)相关推荐

  1. java切割输入流_Java分割流,对象流,参与序列化,分割读取文件,对象输入或输出流等【诗书画唱】...

    自己写的题目:用分割流把一个Java文件分割读取,打印出每次读取的内容,要求每次读取打印500个字节. package fenGeLiu; import java.io.*; public class ...

  2. 【02】Java进阶:13-IO资源的处理、属性集、缓冲流、转换流、序列化、打印流、装饰设计模式、commons-io工具包

    day13[Properties类.缓冲流.转换流.序列化流.装饰者模式.commons-io工具包] 今日内容 IO异常处理 Properties类 缓冲流 转换流 序列化\反序列化流 打印流 装饰 ...

  3. java基础 io流 字节流 字符流 节点流 包装流 转换流 缓冲流 对象流 打印流 Properties类

    目录 1.概念 2.常用的文件操作 2.1 创建文件 2.2 获取文件相关信息 2.3 目录的操作和文件删除 3. IO流原理及流的分类 3.1 流的分类 4.InputStream 字节输入流 4. ...

  4. java file转输入流_Java转换流

    前面提到IO流可分为字节流和字符流,有时字节流和字符流之间也需要进行转换.在JDK中提供了两个类可以将字节流转换为字符流,它们分别是InputStreamReader和OutputStreamWrit ...

  5. Java - io输入输出流 --转换流

    转换流  转换输出流 OutputStreamWriter: 说明: /* * OutputStreamWriter 这个类的作用 * 就是指定输出流的编码格式 * 这个类的构造方法 需要传递 一个输 ...

  6. day17【缓冲流、转换流、序列化流、装饰者模式、commons-io工具包】

    [缓冲流.转换流.序列化流.装饰者模式.commons-io工具包] 第一章 缓冲流 1.1字节缓冲流 1.2字符缓冲流 1.3实操--文本排序 第二章 转换流 2.1字符编码和字符集 2.2编码引出 ...

  7. 缓冲流、转换流、序列化流

    目录 一.缓冲流 1.缓冲流的作用 2.缓冲流的分类 3.字节缓冲流的介绍和使用 4.字符缓冲流的介绍和使用 5.综合练习:文本排序 二.转换流 1.字符编码 2.字符集 3.编码引出的问题 4.In ...

  8. 第十五章 IO流(转换流 字符流 字符缓冲流 打印流)

    Java基础15 第十五章 IO流(转换流 字符流 字符缓冲流 打印流) 15.1 字符编码和字符集 15.1.1 字符编码 15.1.2 字符集 15.1.3 String类getBytes()方法 ...

  9. day22【Properties、ResourceBundle工具类、缓冲流、转换流、序列化】课上

    1.属性集(掌握,很重要) 概念介绍 1.Properties,属于双列集合,他的父类Hashtable,jdk1.0就存在了. 2.该集合没有泛型,因为该集合中的存放数据类型都是String类型 3 ...

最新文章

  1. NET中的设计模式---单件模式
  2. 使用mss2sql将SqlServer转换为Mysql
  3. 工信部明确公共互联网网络安全突发事件分级预警、应急
  4. js 字符串加减法_JavaScript (+) 加法运算符
  5. 导出测试点的信号名_小程序导出数据到excel表,借助云开发云函数实现excel数据的保存...
  6. 6大奖项!首届 .NET 黑客松大赛圆满收官!
  7. VS2015开发Android,自带模拟器无法调试、加载程序,算是坑吗
  8. Vmware虚拟机的安装和使用
  9. 【kafka】 kafka如何设置指定分区进行发送和消费
  10. Maven配置文件无法被导出或者生效的问题【已解决】
  11. 360安全卫士怎么打开加速球
  12. html 卫星地图显示地名,卫星图看:河南10个名字非常好听的县(区),你认识几个?...
  13. Ubuntu安装yum
  14. [Xilinx ZYNQ] #4 Petalinux 入门 [黑金资料 基础教程s1 整理]
  15. ROS出现“Couldn't find executable named listener below //home/xxx/catkin_ws/src/mypack”问题
  16. 腾讯派息式减持京东,中国“伯克希尔”的投资策略变的逻辑是?
  17. 2018吉林CCPC(HDU6555)A.The Fool
  18. spring整合shiro权限管理与数据库设计
  19. Mysql修改表中字段名称、字段类型
  20. android显示ios emoji表情符号,教程:在 Android 上也能用 iOS 新 Emoji 表情

热门文章

  1. 惠普笔记本通过系统如何进入BIOS?
  2. thinkphp 实现汉字转换成拼音
  3. Nginx源码完全注释(1)ngx_alloc.h / ngx_alloc.c
  4. 1月第1周业务风控关注 | 四部门联合印发App违法违规收集使用个人信息行为认定方法
  5. 如何与新同事共同成长?
  6. Android 触摸OnTouchListener没有响应问题解决
  7. P3398 仓鼠找sugar(LCA,树剖)
  8. 奋斗(2)第12集剧情介绍
  9. [转载]windows搭建cloudreve对接OneDrive教程
  10. 骨传导耳机听歌音质怎么样、公认音质好的骨传导耳机排名