详解JAVA 字节流和字符流

1、InputStream 和 Reader

InputStream 和 Reader 是所有输入流的抽象基类,本身并不能创建实例来执行输入,但它们将成为所有输入流的模板,所以它们的方法是所有输入流都可使用的方法。

在 InputStream 里包含如下三个方法。

  • int read():从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转换为int类型)。
  • int read(byte[] b):从输入流中最多读取 b.length 个字节的数据,并将其存储在字节数组 b 中,返回实际读取的字节数。
  • int read(byte[] b, int off, int len):从输入流中最多读取 len 个字节的数据,并将其存储在数组 b 中,放入数组 b 中时,并不是从数组起点开始,而是从 off 位置开始,返回实际读取的字节数。

在 Reader 里包含如下三个方法。

  • int read():从输入流中读取单个字符,返回所读取的字符数据(字符数据可直接转换为int类型)。
  • int read(char[] cbuf):从输入流中最多读取 cbuf.length 个字符的数据,并将其存储在字符数组 cbuf 中,返回实际读取的字符数。
  • int read(char[] chuf, int off, int len):从输入流中最多读取 len 个字符的数据,并将其存储在字符数组 cbuf 中,放入数组 cbuf 中时,并不是从数组起点开始,而是从 off 位置开始,返回实际读取的字符数。

对比 InputStream 和 Reader 所提供的方法,就不难发现这两个基类的功能基本是一样的。

正如前面提到的,InputStream 和 Reader 都是抽象类,本身不能创建实例,但它们分别有一个用于读取文件的输入流:FileInputStream 和 FileReader,它们都是节点流一一会直接和指定文件关联。

下面程序示范了使用 FileInputStream 来读取自身的效果。

public class FileInputStreamTest {
  public static void main(String[] args) throws IOException {
    // 创建字节输入流
    FileInputStream fis = new FileInputStream("F:\\eclipse-workspace\\demo\\src\\com\\jwen\\demo15_3\\FileInputStreamTest.java");
    // 创建一个长度为1024的“竹筒”
    byte[] bbuf = new byte[1024];
    // 用于保存实际读取的字节数
    int hasRead = 0;
    // 使用循环来重复“取水”过程
    while ((hasRead = fis.read(bbuf)) > 0) {
      // 取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
      System.out.print(new String(bbuf, 0, hasRead));
    }
    // 关闭文件输入流,放在finally块里更安全
    fis.close();
  }
}

上面程序中的粗体字代码是使用 FileInputStream 循环“取水”的过程,运行上面程序,将会输出上面程序的源代码。

注意:上面程序创建了一个长度为1024的字节数组来读取该文件,实际上该Java源文件的长度还不到1024字节,也就是说,程序只需要执行一次 read() 方法即可读取全部内容。但如果创建较小长度的字节数组,程序运行时在输出中文注释时就可能出现乱码一一这是因为本文件保存时采用的是 GBK 编码方式,在这种方式下,每个中文字符占2字节,如果 read() 方法读取时只读到了半个中文字符,这将导致乱码。

上面程序最后使用了 fis.close() 来关闭该文件输入流,与 JDBC 编程一样,程序里打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件资源。Java 7 改写了所有的 IO 资源类,它们都实现了 AutoCloseable 接口,因此都可通过自动关闭资源的 try 语句来关闭这些 IO 流。下面程序使用 FileReader 来读取文件本身。

public class FileReaderTest {
  public static void main(String[] args) {
    try (
      // 创建字符输入流
      FileReader fr = new FileReader("F:\\eclipse-workspace\\demo\\src\\com\\jwen\\demo15_3\\FileReaderTest.java")) {
      // 创建一个长度为32的“竹筒”
      char[] cbuf = new char[32];
      // 用于保存实际读取的字符数
      int hasRead = 0;
      // 使用循环来重复“取水”过程
      while ((hasRead = fr.read(cbuf)) > 0) {
        // 取出“竹筒”中水滴(字符),将字符数组转换成字符串输入!
        System.out.print(new String(cbuf, 0, hasRead));
      }
    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }
}

上面的 FileReaderTest.java 程序与前面的 FileInputStreamTest.java 并没有太大的不同,程序只是将字符数组的长度改为32,这意味着程序需要多次调用 read() 方法才可以完全读取输入流的全部数据。程序最后使用了自动关闭资源的 try 语句来关闭文件输入流,这样可以保证输入流一定会被关闭。

除此之外,InputStream 和 Reader 还支持如下几个方法来移动记录指针。

  • void mark(int readAheadLimit):在记录指针当前位置记录一个标记(mark).
  • boolean markSupported():判断此输入流是否支持 mark() 操作,即是否支持记录标记。
  • void reset():将此流的记录指针重新定位到上一次记录标记(mark)的位置。
  • long skip(long n):记录指针向前移动个字节/字符。

2、OutputStream 和 Writer

OutputStream 和 Writer 也非常相似,两个流都提供了如下三个方法。

  • void write(int c):将指定的字节/字符输出到输出流中,其中 c 既可以代表字节,也可以代表字符。
  • void write(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定输出流中。
  • void write(byte[]/char[] buf, int off, int len):将字节数组/字符数组中从 off 位置开始,长度为 len 的字节/字符输出到输出流中。

因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来代替字符数组,即以 String 对象作为参数。Writer 里还包含如下两个方法。

  • void write(String str):将字符串里包含的字符输出到指定输出流中。
  • void write(String str, int off, int len):将字符串里从 off 位置开始,长度为 len 的字符输出到指定输出流中。

下面程序使用 FileInputStream 来执行输入,并使用 FileOutputStream 来执行输出,用以实现复制 FileOutputStreamTest.java 文件的功能。

public class FileOutputStreamTest {
  public static void main(String[] args) {
    try (
      // 创建字节输入流
      FileInputStream fis = new FileInputStream("FileOutputStreamTest.java");
      // 创建字节输出流
      FileOutputStream fos = new FileOutputStream("newFile.txt")) {
      byte[] bbuf = new byte[32];
      int hasRead = 0;
      // 循环从输入流中取出数据
      while ((hasRead = fis.read(bbuf)) > 0) {
        // 每读取一次,即写入文件输出流,读了多少,就写多少。
        fos.write(bbuf, 0, hasRead);
      }
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }
}

运行上面程序,将看到系统当前路径下多了一个文件:newFile.txt,该文件的内容和 FileOutputStreamTest.java 文件的内容完全相同。

注意:使用 Java 的 IO 流执行输出时,不要忘记关闭输出流,关闭输出流除可以保证流的物理资源被回收之外,可能还可以将输出流缓冲区中的数据 flush 到物理节点里(因为在执行 close() 方法之前,自动执行输出流的 flush() 方法)。Java 的很多输出流默认都提供了缓冲功能,其实没有必要刻意去记忆哪些流有缓冲功能、哪些流没有,只要正常关闭所有的输出流即可保证程序正常。

如果希望直接输出字符串内容,则使用 Writer 会有更好的效果,如下程序所示。

public class FileWriterTest {
  public static void main(String[] args) {
    try (FileWriter fw = new FileWriter("poem.txt")) {
      fw.write("锦瑟 - 李商隐\r\n");
      fw.write("锦瑟无端五十弦,一弦一柱思华年。\r\n");
      fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。\r\n");
      fw.write("沧海月明珠有泪,蓝田日暖玉生烟。\r\n");
      fw.write("此情可待成追忆,只是当时已惘然。\r\n");
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
  }
}

运行上面程序,将会在当前目录下输出一个 poem.txt 文件,文件内容就是程序中输出的内容。

注意:上面程序在输出字符串内容时,字符串内容的最后是\r\n,这是 Windows 平台的换行符,通过这种方式就可以让输出内容换行;如果是 UNIX/Linux/BSD 等平台,则使用 \n 就作为换行符。

以上就是详解JAVA 字节流和字符流的详细内容,更多关于JAVA 字节流和字符流的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java编程中字节流与字符流IO操作示例

     IO流基本概念 IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的对象都是在IO包上 流按操作数据分为两种:字节流和字符流 流按流向分为:输入流,输出流. 字节流的抽象基类:InputStream,OutputStream 字符流的抽象基类:Reader,Writer 注:由这4个类派生出来的子类名称都是以其父类名作为子类名的后缀. 如:InputStream的子类:FileInputStream 如:Reader的子类FileReader 如创建一个F

  • 详解Java中字符流与字节流的区别

    本文为大家分析了Java中字符流与字节流的区别,供大家参考,具体内容如下 1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个"流动的方向",通常可以从中读入一个字节序列的对象被称为输入流:能够向其写入一个字节序列的对象被称为输出流. 2. 字节流 Java中的字节流处理的最基本单位为单个字节,它通常用来处理二进制数据.Java中最基本的两个字节流类是InputStream和Out

  • java编程中字节流转换成字符流的实现方法

    java编程中字节流转换成字符流的实现方法 import java.io.*; /*readLine方法是字符流BufferReader类中的方法 * 而键盘录入的方法是字节流InputStream的方法 * 那么能不能将字节流转成字符流再使用字符流缓冲区中的readLine方法呢? * * InputStreamReader类是字节流转向字符流的桥梁.(它本身是一个字符流所以在构造时接受一个字节流) * * */ public class TransStreamDemo { public st

  • 【Java IO流】字节流和字符流的实例讲解

    字节流和字符流 对于文件必然有读和写的操作,读和写就对应了输入和输出流,流又分成字节和字符流. 1.从对文件的操作来讲,有读和写的操作--也就是输入和输出. 2.从流的流向来讲,有输入和输出之分. 3.从流的内容来讲,有字节和字符之分. 这篇文章先后讲解IO流中的字节流和字符流的输入和输出操作. 一.字节流 1)输入和输出流 首先,字节流要进行读和写,也就是输入和输出,所以它有两个抽象的父类InputStream.OutputStream. InputStream抽象了应用程序读取数据的方式,即

  • Java字符流与字节流区别与用法分析

    本文实例讲述了Java字符流与字节流区别与用法.分享给大家供大家参考,具体如下: 字节流与字符流主要的区别是他们的的处理方式 流分类: 1.Java的字节流 InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先. 2.Java的字符流 Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先. InputStream,OutputStream,Reader,writer都是抽象类.所以不能直接new 字节流是最基本的,所有的Inpu

  • java 字节流和字符流的区别详解

    字节流与和字符流的使用非常相似,两者除了操作代码上的不同之外,是否还有其他的不同呢? 实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件,如图所示. 下面以两个写文件的操作为主进行比较,但是在操作时字节流和字符流的操作完成之后都不关闭输出流. 范例:使用字节流不关闭执行 package org.lxh.demo12.byteiodemo; import java.io.File; import java.io.FileOutp

  • Java字符流和字节流对文件操作的区别

    记得当初自己刚开始学习Java的时候,对Java的IO流这一块特别不明白,所以写了这篇随笔希望能对刚开始学习Java的人有所帮助,也方便以后自己查询.Java的IO流分为字符流(Reader,Writer)和字节流(InputStream,OutputStream),字节流顾名思义字节流就是将文件的内容读取到字节数组,然后再输出到另一个文件中.而字符流操作的最小单位则是字符.可以先看一下IO流的概述: 下面首先是通过字符流对文件进行读取和写入: package lib; import java.

  • 详解JAVA 字节流和字符流

    1.InputStream 和 Reader InputStream 和 Reader 是所有输入流的抽象基类,本身并不能创建实例来执行输入,但它们将成为所有输入流的模板,所以它们的方法是所有输入流都可使用的方法. 在 InputStream 里包含如下三个方法. int read():从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转换为int类型). int read(byte[] b):从输入流中最多读取 b.length 个字节的数据,并将其存储在字节数组 b 中,返回实际读

  • 详解Java分布式IP限流和防止恶意IP攻击方案

    前言 限流是分布式系统设计中经常提到的概念,在某些要求不严格的场景下,使用Guava RateLimiter就可以满足.但是Guava RateLimiter只能应用于单进程,多进程间协同控制便无能为力.本文介绍一种简单的处理方式,用于分布式环境下接口调用频次管控. 如何防止恶意IP攻击某些暴露的接口呢(比如某些场景下短信验证码服务)?本文介绍一种本地缓存和分布式缓存集成方式判断远程IP是否为恶意调用接口的IP. 分布式IP限流 思路是使用redis incr命令,完成一段时间内接口请求次数的统

  • Java字节流和字符流及IO流的总结

    从接收输入值说起 在日常的开发应用中,有时候需要直接接收外部设备如键盘等的输入值,而对于这种数据的接收方式,我们一般有三种方法:字节流读取,字符流读取,Scanner 工具类读取. 字节流读取 直接看一个例子: public class Demo01SystemIn { public static void main(String[] args) throws IOException { int a = System.in.read(); System.out.println(a); char

  • Java字节流和字符流总结IO流!

    目录 从接收输入值说起 字节流读取 字符流读取 Scanner 读取 什么是 IO 流 字节流和字符流 字节流 字节输入流 字节输出流 缓冲流的原理 字符流 字符输入流 字符输出流 RandomAccessFile 总结 从接收输入值说起 在日常的开发应用中,有时候需要直接接收外部设备如键盘等的输入值,而对于这种数据的接收方式,我们一般有三种方法:字节流读取,字符流读取,Scanner 工具类读取. 字节流读取 直接看一个例子: public class Demo01SystemIn { pub

  • Java中字节流和字符流的理解(超精简!)

    目录 引言 字节流和字符流 字节流 字节输入流 字节输出流 字符流 字符输入流 字符输出流 附:字节流和字符流的区别 总结 引言 在完完全全的完成本学期的学习任务之后,终于可以有时间继续更新Java相关的文章了.那么今天我们要学习的是的Java中的IO流(I即为Input,O即为Output),也称为输入流,输出流,其主要的作用是为了能够对文件中的数据进行输入和输出(读和写),更加方便了今后我们在Java道路上的学习,好了,废话不多说,我们开始今天的学习吧! 字节流和字符流 在上图中,橙色部分是

  • Java常用字节流和字符流实例汇总

    IO流(输入流.输出流) 字节流.字符流 1.字节流: InputStream.OutputStream InputStream抽象了应用程序读取数据的方式: OutputStream抽象了应用程序写出数据的方式: 2.EOF=End 读到-1就读到结尾 3.输入流的基本方法: int b=in.read();读取一个字节无符号填充到int低八位;-1是EOF; in.read(byte[] buf) in.read(byte[] buf,int start,int size) 4.输出流基本方

随机推荐