字节流
Java 把不同类型的输入、输出抽象为流 stream ,分为输入流和输出流,用统一的接口来表示
Java 开发环境中提供了包 java.io ,其中包括一系列的类来实现输入/输出处理
InputStream 是所有字节输入流的祖先,而 OutputStream 是所有字节输出流的祖先
public abstract class InputStream implements Closeablepublic abstract class OutputStream implements Closeable , Flushable
InputStream
InputStream 类是一个抽象类,方法包括:
int read()
int read(byte[])
int read(byte[],int,int)
void close() 关闭流
int available() 报告流中直接可读的字节数
skip(long) 跳过流中指定的字节
练习 1 :使用字节流读取一个文本文件,并显示其内容
OutputStream
OutputStream 也是一个抽象类。它的主要方法包括:
void write(int)
void write(byte[])
void write(byte[],int,int)
其中第一个方法的 int 型的参数对应要写入的字节,后两个方法的参数与 InputStream 类似。
void close() 关闭输出流
void flush() 强行将写入缓冲区中剩余的数据写入
File file = new File ( "d:\\FileTest.java" );if ( file . exists ()) {try ( InputStream is = new FileInputStream ( file );) {byte [] buffer = new byte [ 8192 ];int len = is . read ( buffer );while ( len > 0 ) {System . out . write ( buffer , 0 , len );len = is . read ( buffer );}} catch ( Exception e ) {e . printStackTrace ();}}
InputSream 和 OutputStream 中定义了 read() 和 write() 方法,它们被派生流类重载。字节流是字节序
列,它与外部设备中的字节存在着一一对应的关系,不存在字符的转换,被读写字节的个数与外部设备
中的字节个数是相同的
基本输入输出方法
System 类是 Java 语言中一个功能强大、非常有用的类,它提供了标准输入 / 输出及运行时的系统信息
System类不能创建对象,也就是说, System 类的所有属性和方法都是静态的,引用时要以 System作为前缀
System.in 与 System.out 是 System 类的两个静态属性,分别对应了系统的标准输入 / 输出流
System 类管理标准输入输出流和错误流
System.out :把输出送到缺省的显示 ( 通常是显示器 ) ,是 PrintStream 的对象
System.in :从标准输入获取输入 ( 通常是键盘 ) ,是 InputStream 的对象
System.err :把错误信息送到缺省的显示,是 PrintStream 的对象
同时使用 System.out 和 System.err 输出信息不能保证显示顺序就是执行顺序,为了避免这种情况在测试
代码执行中经常使用 System.err 输出
练习题
题目:用户在键盘依次输入若干个数字,每输入一个数字都需要按回车键确认,最后在键盘输入一个非
数字字符串结束整个输入操作过程。程序将计算出这些数的和以及平均值。
用来读写外设字符的,它们都是字节流。如果编程人员愿意,可以用基于字符的流来包装它们
System . out . println ( " 提示信息: " );try {// 从键盘上读取一个字节的数据并返回读取的 int 类型内容 0-255 ,如果输入中文则会出现乱码,因为一个中文是 2 个字节构成// 如果用户不输入任何内容,则当前程序会在这里阻塞等待,直到用户输入为止 ---BIOint kk = System . in . read (); // 这个方法上有个 IOException 异常,属于受检型异常,必须进行处理,处理方法有 throws 或者 try/catchSystem . out . println (( char ) kk ); // 将读取内容转换为 char 类型进行显示} catch ( Exception e ) {e . printStackTrace ();}
使用字节数组读取一组内容
System . out . println ( " 提示信息: " );byte [] buffer = new byte [ 8192 ]; // 注意一般设置缓存默认值都是 8192--8Ktry {// 从键盘读取内容放入到 buffer 字节数组中,并返回读取的字节数 . 如果用户不输入数据则一直阻塞等待int len = System . in . read ( buffer );// 如果输入的是中文信息,则会多两个字节长 [ 和操作系统平台相关 ], 不管中文信息中字符个数 , 一个中文为2 个字节if ( len > 0 ){System . out . println ( " 读取的字节数为: " + len );String str = new String ( buffer ); // 将数组内容转换为 String 类型数据System . out . println ( str );}} catch ( Exception e ) {e . printStackTrace ();}
FileInputStream 、 FileOutputStream 顺序读取文件
PipedInputStream 、 PipedOutputStream 管道
ByteArrayInputStream 、 ByteArrayOutputStream 内存读写
FilterInputStream 、 FilterOutputStream 过滤流(有多线程同步)
DataInputStream 、 DataOutputStream 对数据类型读写,有多线程同步
BufferedInputStream 、 BufferedOutputStream 缓冲类型读写

1 、使用字节流进行文件的单字节复制
FileInputStream 是 InputStream 的子类, FileInputStream 属于节点流,用于按字节读取文件内容
FileOutputStream 是 OutputStream 的子类, FileOutputStream 属于节点流,用于按字节输出数据
到文件中
//FileInputStream 中 read 方法的定义/**从指定的输入流中按字节读取数据,如果读到流的末尾则返回 -1, 否则返回读取到的数据。如果文件不存在则异常 FileNotFoundException 【 IOException 的子类】*/public int read () throws IOException {return read0 ();}//FileOutputStream 中 write 方法的定义// 属性 , 用于表示是否进行文件的追加操作而不是覆盖操作private final boolean append ;// 构造器方法的定义,其中 name 是文件名称,默认采用覆盖操作public FileOutputStream ( String name ) throws FileNotFoundException {this ( name != null ? new File ( name ) : null , false );}// 按照字节执行写出 int 数据,自动会去除多余的字节。如果文件不存在则自动创建新文件,如果文件已经存在则按照append 的值决定采用的是追加操作还是覆盖操作public void write ( int b ) throws IOException {write ( b , append );}private native void write ( int b , boolean append ) throws IOException ; //由 VM 采用对等类的方式提供实现
public class Test1 {public static void main ( String [] args ) throws IOException {try ( InputStream is = new FileInputStream ( "c:/ 面向对象文档 .txt" );OutputStream os = new FileOutputStream ( "test.txt" );) {int kk ;while (( kk = is . read ()) != - 1 ) {os . write ( kk );}}}}
2 、读取 A.java 文件并在控制台上显示
如何使用控制台输出 : System.out 字节流
分析:使用字节流从 A.java 中一个字节一个字节的读取内容,然后再使用 System.out.print 方法输出即可
注意:读取操作返回的 int 的取值范围为 0-255 ,则表示这里不会有符号位,所以 is.read()==-1 不是只适合于文本文件
File ff = new File ( "T1.java" );if ( ff . exists ()) { // 如果文件存在则进行拷贝操作,否则提示文件不存在InputStream is = new FileInputStream ( ff );OutputStream os = new FileOutputStream ( "t1.bak" );while ( true ) {int kk = is . read (); // 返回值应该是 0-255 ,如果返回 -1 表示流已经结束if ( kk < 0 ) break ;os . write ( kk );}is . close ();os . close ();} elseSystem . out . println ( "T1.java 文件不存在 " );
InputStream 基本输入类
InputStream 类是基本的输入类。它定义了所有输入流所需的方法。
public abstract int read() throws IOException 读取一个字节并以整数的形式返回, 0-255 。如果
返回 -1 已到输入流的末尾。
public int read(byte b[]) throws IOException 读取一系列字节并存储到一个数组,返回实际读取的
字节数。如果已经读到输入流的末尾则返回 -1
public void close() throws IOException 关闭输入流并释放资源
public int read(byte b[],int offset,int length) throws IOException 功能为从输入流中读数据。这一
方法有几种重载形式,可以读一个字节或一组字节。当遇到文件尾时,返回 -1 。最后一种形式中的
offset 是指把结果放在 b[] 中从第 offset 个字节开始的空间, length 为长度
public long skip (long n) throws IOEnception 从输入流跳过几个字节。返回值为实际跳过的字节
数
OutputStream 基本输出类
三个重载形式都是用来向输出流写数据的
public abstract void write(int b) 向输入流写入一个字节数据,该字节为参数的低 8 位。
public void write(byte b[],int offset,int length) 将一个字节类型的数组中的从指定位置 offset 开始
的 length 个字节写入到输出流
public void close( ) 关闭输出流,释放资源
public void write(byte b[]) 将一个字节类型的数组中的数据写入到输出流
public void flush() 清除缓冲区,将缓冲区内尚未写出的数据全部输出
需求:使用字节流将一个文件进行拷贝
每次读写一个字节效率太低,所以使用字节数组。同时编码中需要考虑如果文件存在则进行拷贝操作, 否则提示文件不存在
要点 1 :从文件中读取数据放入到 buffer 字节数组中,如果文件中的内容大于 byte[] ,则最多读取 1024 个字节;如果文件中数据不足,则实际有多少则读取多少;写入buffer 数组默认是从 0 开始写入 , 最终返回实际读取的字节数。如果读取到流末尾则返回-1
要点 2 :不能直接写出数组,否则会有多余内容产生。可以使用 write(byte[],int,int) 保证只写出读取到的内容
要点 3 :注意 try/finally 结构, JDK1.7 中提供 Closeable 接口支持自动关闭,从而简化 try/finally 写法
查看源代码
public abstract class InputStream implements Closeablepublic abstract class OutputStream implements Closeable , Flushable
字符流
在顶层有 Reader 和 Writer 两个抽象类。 Reader 和 Writer 中定义了 read() 和 write() 方法,它们被派生流类重载
Reader 抽象类的定义
public abstract class Reader implements Readable , Closeable {//BIO ,读取一个有效的字符,返回值为 0 到 65535 的整数,如果到达流的末尾则返回 -1public int read () throws IOException//BIO, 读取字符存储到 char 数组中,返回读取的字符个数,流结束则返回 -1public int read ( char cbuf []) throws IOException// 关闭流,同时释放资源abstract public void close () throws IOException ;
Writer抽象类的定义
public abstract class Writer implements Appendable , Closeable , Flushable {// 写出一个字符到字符流,要写的字符包含在给定整数值的 16 个低位; 16 个高位被忽略。public void write ( int c ) throws IOException// 将字符数组中的指定部分内容压入到字符流,从 off 开始共 len 个字符abstract public void write ( char cbuf [], int off , int len ) throwsIOException ;/ 关闭流,同时释放资源abstract public void close () throws IOException ;
相关的子类
InputStreamReader 、 OutputStreamWriter 桥接流,用于自动实现字节流和字符流的转换
FileReader 、 FileWriter 文件流,用于实现针对文本文件的读写操作
CharArrayReader 、 CharArrayWriter 内存流,用于实现针对 char 数组的读写操作
PipedReader 、 PipedWriter 管道流,用于线程之间的通讯
FilterReader 、 FilterWriter 过滤流的父类
BufferedReader 、 BufferedWriter 缓存流,用于在流中添加缓冲区
StringReader 、 StringWriter 内存流,用于实现针对字符串的读写操作

使用字符流实现 txt 文件的读取显示【其中包含中文】
编写一个程序,读取文件 test.txt 的内容并在控制台输出。如果源文件不存在,则显示相应的错误信息。
字符流 Reader
int read() 读取一个字符并以整数的形式返回 0-65535 ,如果返回 -1 则已到输入流末尾
int read(char[] cbuf) 读取一系列字符并存储到一个数组中,返回实际读取的字符数,如果读到输入
流末尾则返回 -1
void close() 关闭输入流并释放内存资源
int read(char[] cbuf, int off, int len) 读取 len 个字符并存储到一个数组中,从 off 位置开始,返回实
际读取的字符数,如果读取到输入流末尾则返回 -1
long skip(long n) 跳过 n 个字符不读,返回实际跳过的字节数
字符流 Writer
void write(int c) 将字符( int 数组的低 8 位)压入到字符流中
void write(char[] cbuf, int off, int len) 将字符数组中的指定部分内容压入到字符流中,从 off 开始共
len 个字符
void write(String str) 将字符串中的内容压入到字符流中
void close() 关闭流并释放所占用的资源
void write(String str, int off, int len) 将字符串中的指定部分内容压入到字符流中,从下标 off 开始
共 len 个字符
void flush() 刷新缓冲区,将缓冲区中的数据全部送出到目标地,然后清空缓冲区
void write(char[] cbuf) 将字符数组中的所有数据压入到字符流中
版权声明:本文为m0_56627229原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。