JAVA之字节流和字符流

字节流

  • Java把不同类型的输入、输出抽象为流stream,分为输入流和输出流,用统一的接口来表示
  • Java开发环境中提供了包java.io,其中包括一系列的类来实现输入/输出处理
  • InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先
public abstract class InputStream implements Closeable 


public abstract class OutputStream implements Closeable, Flushable
具体子类: ByteArrayInputStream, FileInputStream, FilterInputStream, ObjectInputStream,
PipedInputStream, SequenceInputStream, StringBufferInputStream

InputStream

InputStream 类是一个抽象类,方法包括:
  • int read()
  • int read(byte[])
  • int read(byte[],int,int)
  • void close()关闭流
  • int available()报告流中直接可读的字节数
  1. skip(long)跳过流中指定的字节

OutputStream

OutputStream 也是一个抽象类。它的主要方法包括:
  1. void write(int)
  • void write(byte[])
  1. void write(byte[],int,int)
其中第一个方法的 int 型的参数对应要写入的字节,后两个方法的参数与 InputStream 类似。
  1. void close() 关闭输出流
  2. 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.inSystem.outSystem类的两个静态属性,分别对应了系统的标准输入/输出流
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(); 
}
  • FileInputStreamFileOutputStream 顺序读取文件
  • PipedInputStreamPipedOutputStream 管道
  • ByteArrayInputStreamByteArrayOutputStream 内存读写
  • FilterInputStreamFilterOutputStream 过滤流(有多线程同步)
  • DataInputStreamDataOutputStream 对数据类型读写,有多线程同步
  • BufferedInputStreamBufferedOutputStream 缓冲类型读写

1 、使用字节流进行文件的单字节复制
  • FileInputStreamInputStream的子类,FileInputStream属于节点流,用于按字节读取文件内容
  • FileOutputStreamOutputStream的子类,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;
相关的子类
  • InputStreamReaderOutputStreamWriter桥接流,用于自动实现字节流和字符流的转换
  • FileReaderFileWriter文件流,用于实现针对文本文件的读写操作
  • CharArrayReaderCharArrayWriter内存流,用于实现针对char数组的读写操作
  • PipedReaderPipedWriter管道流,用于线程之间的通讯
  • FilterReaderFilterWriter过滤流的父类
  • BufferedReaderBufferedWriter缓存流,用于在流中添加缓冲区
  • StringReaderStringWriter内存流,用于实现针对字符串的读写操作

 

使用字符流实现 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) 将字符数组中的所有数据压入到字符流中
一般来说:一次读写一个字符效率太低,可以引入 char[] 数组提高执行效率
练习:编写一个程序,读取文件 test.txt 的内容并在控制台输出。如果源文件不存在,则显示相应的错误信息。
如果使用的是字节流,所以只能保证读取的是 80 个英文字符,如果中文则会出现问题
//String的构造器方法 
new String(byte[],0,len) 
new String(char[],0,len)
默认文件是覆盖,可以修改 FileOutputStream fos=new FileOutputStream("fout.txt", true);
使用字符流针对字符操作要方便的多
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值