一、前言
Java数据流(Stream)可以理解为数据的序列,即数据在输入或输出的时候是以“数据流”形式传输的。而Java.io包(Input和Output的缩写)几乎包含了所有操作输入或输出的类。
流一般分为输入流(从一个数据源读取数据)和输出流(向一个目标输出数据)。而根据流的格式不同又分为字符流和字节流。
二、文件的读取(IO流操作)
如前所述,一个流被定义为一个数据序列。输入流用于从源读取数据,输出流用于向目标写数据。
Java中的字符流处理的最基本的单元是Unicode码元(大小2字节),它通常用来处理文本数据。所谓Unicode码元,也就是一个Unicode代码单元,范围是0x0000~0xFFFF。在以上范围内的每个数字都与一个字符相对应,Java中的String类型默认就把字符以Unicode规则编码而后存储在内存中。
Java中的字节流处理的最基本单位为单个字节,它通常用来处理二进制数据。Java中最基本的两个字节流类是InputStream和OutputStream,它们分别代表了组基本的输入字节流和输出字节流。InputStream类与OutputStream类均为抽象类,我们在实际使用中通常使用Java类库中提供的它们的一系列子类。
两者区别有:
- 基本单位不同:字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元。
- 处理数据类型:字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流通常处理文本数据,它支持写入及读取Unicode码元。
下图是一个描述输入流和输出流的类层次图。
三、字符输入流Reader
1、介绍
用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。方法摘要如下,
2、BufferedReader类:带有缓冲区的字符输入流
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。如:
BufferedReader br = new BufferedReader(new FileReader("ok.in"));//使用BufferedReader封装的字符输入流
将缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。
3、InputStreamReader类:字节流通向字符流的桥梁
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的
(16位Unicode单元序列和字节序列之间的映射关系)读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。charset
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。
四、字符输出流Writer
1、介绍
同Reader一样属于字符流,Reader是输入流,而Writer是输出流。
2、BufferedWriter类:带有缓冲区的字符输出流
文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
3、OutputStreamWriter类:字节流通向字节流的桥梁
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的
将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。charset
五、字节输入流FileInputStream
1、介绍
此抽象类是表示字节输入流的所有类的超类。
2、FileInputStream类
FileInputStream
用于读取诸如图像数据之类的原始字节流。
//使用字符串类型的文件名来创建一个输入流对象来读取文件 InputStream f = new FileInputStream("C:/java/hello"); //使用一个文件对象来创建一个输入流对象来读取文件。 File f = new File("C:/java/hello"); InputStream out = new FileInputStream(f);
3、BufferedInputStream类:为字节输入流添加缓冲区
BufferedInputStream
为另一个输入流添加一些功能,即缓冲输入以及支持 mark
和 reset
方法的能力。在创建 BufferedInputStream
时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark
操作记录输入流中的某个点,reset
操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark
操作后读取的所有字节。
六、字节输出流FileOutputStream
1、介绍
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
2、FileOutputStream类
文件输出流是用于将数据写入 File
或 FileDescriptor
的输出流。如果该流在打开文件进行输出前,目标文件不存在,那么该流会创建该文件。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。
3、BufferedOutputStream类:为字节输出流添加缓冲区
该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
七、控制台的输入输出(System操作)
1、读取控制台输入(System.in)
System.in:“标准”输入流(属于字节流)。此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。
如读取System.in输入流的一行内容并打印到控制台:
1 package test; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 7 class Test{ 8 public static void main(String[] args){ 9 System.out.println("请输入一句话:"); 10 InputStreamReader fr = new InputStreamReader(System.in);//将输入流转换为字符流 11 BufferedReader br = new BufferedReader(fr);//使用缓冲区工具类封装字符流 12 try { 13 System.out.println((String)br.readLine());//读取一行 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 }
下面的程序示范了用 read() 方法从控制台不断读取字符直到用户输入 "q"。
1 // 使用 BufferedReader 在控制台读取字符 2 3 import java.io.*; 4 5 public class BRRead { 6 public static void main(String args[]) throws IOException 7 { 8 char c; 9 // 使用 System.in 创建 BufferedReader 10 BufferedReader br = new BufferedReader(new 11 InputStreamReader(System.in)); 12 System.out.println("输入字符, 按下 'q' 键退出。"); 13 // 读取字符 14 do { 15 c = (char) br.read(); 16 System.out.println(c); 17 } while(c != 'q'); 18 } 19 }
2、控制台输出(System.out)
控制台的输出由 print( ) 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类对象的一个引用。
在此前已经介绍过,控制台的输出由 print( ) 和 println() 完成。这些方法都由类 PrintStream 定义,System.out 是该类对象的一个引用。
PrintStream 继承了 OutputStream类,并且实现了方法 write()。这样,write() 也可以用来往控制台写操作。
import java.io.*; // 演示 System.out.write(). public class WriteDemo { public static void main(String args[]) { int b; b = 'A'; System.out.write(b); System.out.write(' '); } }
注:write()不常用,而一般用println()。