java中的BIO基础-3

字节流
Java 把不同类型的输入、输出抽象为流 stream ,分为输入流和输出流,用统一的接口来表示
Java 开发环境中提供了包 java.io ,其中包括一系列的类来实现输入/输出处理
InputStream 是所有字节输入流的祖先,而 OutputStream 是所有字节输出流的祖先
public abstract class InputStream implements Closeable
public 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 个字节构成
// 如果用户不输入任何内容,则当前程序会在这里阻塞等待,直到用户输入为止 ---BIO
int kk = System . in . read (); // 这个方法上有个 IOException 异常,属于受检型异常,必须进行
处理,处理方法有 throws 或者 try/catch
                System . out . println (( char ) kk ); // 将读取内容转换为 char 类型进行显示
        } catch ( Exception e ) {
                e . printStackTrace ();
}
使用字节数组读取一组内容
System . out . println ( " 提示信息: " );
        byte [] buffer = new byte [ 8192 ]; // 注意一般设置缓存默认值都是 8192--8K
        try {
// 从键盘读取内容放入到 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 ();
        } else
                System . 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 Closeable
public abstract class OutputStream implements Closeable , Flushable 
字符流
在顶层有 Reader Writer 两个抽象类。 Reader Writer 中定义了 read() write() 方法,它们被派生流类重载
Reader 抽象类的定义
public abstract class Reader implements Readable , Closeable {
//BIO ,读取一个有效的字符,返回值为 0 65535 的整数,如果到达流的末尾则返回 -1
public int read () throws IOException
//BIO, 读取字符存储到 char 数组中,返回读取的字符个数,流结束则返回 -1
public 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 ) throws
IOException ;
/ 关闭流,同时释放资源
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版权协议,转载请附上原文出处链接和本声明。