字节流和字符流

InputStream和Reader

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

InputStream中包含如下三个方法

  • int read() 从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转 换为int类型).
  • int read(byte[] b) 从输入流中读取最多b.lenght个字节数据,并将其存贮在数组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 cbuf,int off,int len) 从输入流中读取最多len个字符的数据,并将其存在cbuf中,从off位置开始,返回实际的读取的字符数.

  • 使用FileInputStream读取自身

javapublic void readFile() throws IOException {//创建字节输入流FileInputStream fis = new FileInputStram("FileInputTest.java");//创建一个长度为1024的缓冲数组byte[] bbuf = new byte[1024];//保存实际读取的字节数int hasRead = 0;//循环读取文件内容while ((hasRead = fis.read(bbuf)) > 0) {System.out.println(new String(bbuf,0,hasRead));}//文件IO资源不属于内存资源//垃圾回收无法回收该资源//必须显式关闭fis.close();
}
  • 使用FileReader读取文件自身
public void readFile() throws IOException {FileReader fr = new FileReader("FileReaderTest.java");char[] cbuf = new char[32];int hasRead = 0;while ((hasRead = fr.read(cbuf)) > 0) {System.out.println(new String(cbuf,0,hasRead));}fr.clse();
}

此外,InputStream和Reader还支持如下几个方法来支持指针的移动
void mark(int readAheadLimit) 在记录指针当前位置记录一个标记(mark).
boolean markSupported() 判断此输入流是否支持mark()操作
void reset() 将此流的记录指针重新定位到上一次记录标记的位置(mark).
long skip(long n) 记录指针向前移动n个字节/字符.

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里还包含如下两个方法:
* void write(String str) 将str字符串输出到指定输出流中
* void write(String str,int off,int len) 将str字符串里从off位置开始,长度为len输出到指定输出流中.

下面的程序使用FileInputStream来执行输入,通过FileOutputStream执行输出,实现复制文件的功能

javapublic void copyFile() throws IOException {FileInputStream fis = null;FileOutputStream fos = null;try {fis = new FileInputStream("outfile.txt");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.printStatckTrance();} finally {if (fis != null) {fis.close();}if(fos != null) {fos.close();}}
}

如果希望直接输出字符串内容,使用Writer更为方便.

javapublic void out() {FileWriter fw = null;try {fw = new FileWrite("file.txt");fw.write("但我不能放歌,\n");fw.write("悄悄是别离的笙箫;\n");fw.write("夏虫也为我沉默,\n");fw.write("沉默是今晚的康桥!\n");} catch (IOException ioe) {} finally {if(null != fw) {fw.close();}}
}

上面程序会在当前目录下输出file.txt,文件内容就是程序中输出内容.

输入/输出流体系

分类 字节输入流 字节输出流 字符输入流 字符输出流
抽象基类 InputStream OutputStream Reader Writer
访问文件 FileInputStream FileOutputStream FileReader FileWriter
访问数组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter
访问管道 PipedInputStream PipedOutputStream PipedReader PipedWriter
访问字符串 StringReader StringWriter
缓冲流 BufferedInputStream BufferedOutputStream BufferedRead BufferedWriter
转换流 InputStreamReader OutputStreamReader
对象流 ObjectInputStream ObjectOutput
抽象基类 FilterInputStream FilterOutPutStream FilterReader FilterWriter
打印流 PrintStream PrintWriter
推回输入流 PushbackInputStream PushbackReader
特殊流 DataInputStream DataOutputStream

上面表中粗体字标出类的代表节点流,必须直接与指定物理节点关联;斜体字标出的为抽象基类,无法创建实例.

字节流比字符流功能强大,因为计算机中所有数据都是二进制的.字节流可以处理所有的二进制文件.如果使用字节流来处理文本文件时,需要使用合适的方式把字节转换成字符,无形中增加了编程的复杂程度.所以通常有个规则,如果需要进行输入/输出的是文本内容,应考虑使用字符流,如果需要进行输入/输出的二进制内容,应考虑使用字节流.

使用字符串作为物理节点:

javapublic void StringNodeTest() {String src = "软泥上的青荇,\n"+"油油的在水底招摇;\n"+"在康河的柔波里,\n"+"我甘心做一条水草。";StringReader sr = new StringReader(src);char[] cbuf = new char[32];int hasRead = 0;try {while((hasRead =sr.read(cbuf)) > 0) {System.out.println(new String(cbuf,0,hasRead));}} catch (IOException ioe) {ioe.} finally {if (null != sr){sr.close();}}
}

转换流

IO体系中提供了2个转换流,用于实现将字节流转换成字符流.InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流.

Java并没有提供字符流转换成字节流接口,看似设计遗漏.考虑下字符流和字节流的差别,字节流比字符流使用范围更广,但字符流操作比字节流方便,如果已经有一个字符流,为什么还要换成字节流,既然知道字节流的内容是文本,那么转换成字符流更方便一些,所以Java没有提供字符流到字节流的转换.

下面的例子通过使用键盘输入(System.in).这个标准的输入流是InputStream实例,使用起来不太方便,键盘输入的都是纯文本,使用InputStreamReader将其转换为字符输入流,普通Reader读起来依旧不方便,于是再转换成BufferedReader,利用它的readLine()方法可以一次读一行.

javapublic void convInput() {BufferedReader br = null;try {//System.in转换成Reader对象InputStreamReader reader = new InputStreamReader(System.in);//将Reader包装成BufferedReaderbr = new BufferedReader(reader);String buffer = null;While((buffer = br.readLine()) != null) {if("exit".equals(buffer)) {System.exit(1);}System.out.println("输入内容为:" + buffer);}} catach (IOException ioe) {} finally {try {if (null != br) {br.close();}} catach (IOException ioe) {}}
}

推回输入流

在IO体系中,有2个特殊的流.PushbackInputStream和PushbackReader.提供如下三个方法:
* void unread(byte[]/char[] buf) 将一个字节数组内容推回到推回缓冲区里,从而允许重复读取刚刚的内容.
* void unread(byte[]/char[] b,int off,int len) 将一个字节/字符数组从off开始,长度为len字节/ 字符的内容推回到推回缓冲区里,从而允许重复读取刚刚的内容.
* void unread(int b) 将一个字节/字符推回到推回缓冲区,从而允许重复读取刚刚读取的内容.

这三个方法和InputStream和Reader里三个read方法一一对应,这两个推回输入流都带有一个推回缓冲区,当程序调用这两个推回输入流的unread方法时,系统会把指定数组的内容推回到该缓冲区里,从而允许重复读取刚刚读取的内容.

java/**省略无数代码**/PushbackReader pr = null;try {pr = new PushbackReader(new FileReader("E:\\workplace1\\review\\src\\io\\PushbackReaderTest.java"), 64);char[] buf = new char[32];//保存上次读取的字符串内容String lastContent = "";int hasRead = 0;while ((hasRead = pr.read(buf)) > 0) {//读取到内容转换成字符串String content = new String(buf,0,hasRead);int targetIndex = 0;//将上一次内容和本次内容拼起来 检查是否包含目标字符串//如果包含目标字符串if ((targetIndex = (lastContent + content).indexOf("new PushbackReader")) > 0) {//将本次内容上次内容一起退回到推回缓冲区pr.unread((lastContent + content).toCharArray());//再次读取指定程度的内容(目标字符串之前的内容)pr.read(buf,0,targetIndex);//打印读取内容System.out.println(new String(buf,0,targetIndex));System.exit(0);} else {System.out.println(lastContent);lastContent = content;}}/**省略无数代码**/

重定向标准输入/输出

Java的标准输入输出分别通过System.in和System.out来代表,默认情况下他们分别代表键盘和显示器.
System类中提供三个重定向输入/输出标准的方法:
* static void setErr(PrintStream err) 重定向"标准"错误输出流
* static void setIn(InputStream in) 重定向"标准"输入流
* static void setOut(PrintStream out) 重定向"标准"输出流

下面的程序通过重定向标准输出流,将System.out的输出重定向到到文件输出:

java/**省略无数代码**/PrintStream ps = null;try {//创建重定向需要的输出流ps = new PrintStream(new FileOutputStream("out.txt"));//将标准输出流重定向到ps输出流System.setOut(ps);//测试输出System.out.println("普通字符串");System.out.println(new RedirectOut());} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {if (null != ps) {ps.close();}}
/**省略无数代码**/

下面的程序通过重定向标准输入流,将System.in重定向到指定文件而不是键盘:

java/**省略无数代码**/FileInputStream fis = null;try {fis = new FileInputStream("E:\\workplace1\\review\\src\\io\\RedirectIn.java");//将标准输入重定向到fis输入流System.setIn(fis);//获取标准输入Scanner sc = new Scanner(System.in);//设置只把回车作为分隔符sc.useDelimiter("\n");while (sc.hasNext()) {System.out.println("键盘输入内容为:" + sc.next());}
/**省略无数代码**/

Java IO (二),常见的输入/输出流相关推荐

  1. Java基础(二):集合、IO流(Zip压缩输入/输出流等)、File文件类、反射、枚举

    Java基础(一):编译和解释.数据类型.变量作用域.String常用方法.数组.面向对象.异常 Java基础(二):集合.IO流(Zip压缩输入/输出流等).File文件类.反射.枚举 Java异常 ...

  2. java输出流输入流的使用_Java中的IO流之文件输入输出流

    Java中的IO流之文件输入输出流 1.文件流介绍 文件流是以字节为单位进行读写文件的,所以属于字节流,并且是低级流.文件流位于java.io包下. 输入输出流分别是FileInputSteam和Fi ...

  3. 【Java学习笔记十】输入输出流

    在Java.io包中提供了一系列用于处理输入/输出的流类.从功能上分为两类:输入流和输出流.从六结构上可分为:字节流(以字节为处理单位)和字符流(以字符为处理单位). 字符是由字节组成.在Java中所 ...

  4. java out.flush_java中基本输入输出流的解释(flush方法的使用)

    网络程序的很大一部分是简单的输入输出,即从一个系统向另一个系统移动字节.字节就是字节,在很大程度上,读服务器发送的数据与读取文件没什么不同:向客户传送数据与写入一个文件也没有什么区别. Java中输入 ...

  5. java输入输出及文件_java输入输出流及文件操作

    我只选择了一些代码 注意包声明和相关结构 许多类都继承了MyFile这个类 深入研究可以参考<java文件操作> 1.[代码]读取文件内容 /** *Author:Yuanhonglong ...

  6. 1.1 Java流是什么?输入/输出流又是什么?

    在 Java 中所有数据都是使用流读写的.流是一组有序的数据序列,将数据从一个地方带到另一个地方.根据数据流向的不同,可以分为输入(Input)流和输出(Output)流两种. 在学习输入和输出流之前 ...

  7. java 对象读写_java 对象输入输出流读写文件的操作实例

    java 对象输入输出流读写文件的操作实例 java 支持对对象的读写操作,所操作的对象必须实现Serializable接口. 实例代码: package vo; import java.io.Ser ...

  8. java inputstream read_Java学习之输入输出流

    "持志如心痛,一心在痛上,岂有功夫说闲话,管闲事 --摘自阳明先生语录" Java中通过流来完成输入/输出,所有的输入/输出以流的形式处理,流可以理解为一个数据的序列.输入流表示从 ...

  9. Java IO(二)

    字节流 字符流: FileReader FileWriter BufferedReader BufferedWriter 字节流: FileInputStream FileOutputStream B ...

最新文章

  1. 微软:外接 USB 设备或 SD 卡时将无法更新 Windows 1903
  2. ASP.NET防止按F5键造成表单重复提交
  3. 高手是如何定位内存问题的代码位置的
  4. 矩阵快速幂各类题型总结(一般,共轭,1 * n, 矩阵简化)
  5. 数据离散化 - 等宽等频聚类离散 - Python代码
  6. Qt学习笔记-Qt程序切换皮肤
  7. 浅谈Fluent Ribbon 中的SplitButton
  8. phpcmsV9中的CSS_PATH是如何定义的
  9. 突破技术管理,IT人中年危机变契机
  10. 高通:骁龙将成为独立的产品品牌
  11. mysql多线程复制binlog_MySQL并发复制系列一:binlog组提交 (转载)
  12. 二十年前的电脑配置单,大家见过吗?
  13. mysql增加列并增加comment_运城多条高铁线路调整动车列数增加到99列
  14. 电脑版微信发消息转圈圈
  15. 掌握QCC推行方法,为企业创造经济效益
  16. 购买成功订单详情html,订单成功页面功能实现
  17. 第三方百度地图----显示所在位置
  18. vue 运行项目浏览器页面显示“该网页无法正常运作”
  19. 计算机设置休眠密码,win10系统如何设置电脑待机密码?windows10设置待机密码图文教程...
  20. 全网最全软件测试面试题,拿不到offer算我输!

热门文章

  1. Linux环境变量设置中配置文件分析(/etc/profile,~/.bashrc等)(转)
  2. Deep Learning(深度学习)相关网站
  3. mac环境下的linux光标快捷键
  4. 一段经典的js命名空间创建和链式调用代码
  5. 创新创新再创新(4)
  6. 黄聪:ICTCLAS分词系统研究(一)(转)
  7. VI连接esx主机时报错“client.xml”错误
  8. python画图保存成html格式、用浏览器打开页面为空白_解决pyecharts运行后产生的html文件用浏览器打开空白...
  9. IPv6 — IPv4v6 综合组网技术
  10. Keil 函数内联 inline