好记性不如烂笔头,就拿Java IO来说吧,这部分的基础类我大学都已经学过一遍了,但是现在忘记的差不多了,所以准备写一篇博客,讲这些东西都回忆一下,并且整理一下。

首先借用网上的一张图:

纵向分为字节流和字符流.横向分为针对读写进行划分

在这幅图中那些非常基本的也就不提了,就提一下需要注意的几个类。

1.BufferedXXX 缓冲 无论是读还是写,字符还是字节流都存在,主要是作为一个缓冲的作用,起到的作用是减少和操作系统的IO交互,减少性能消耗

2.PipedXXX  管道    管道也是存在这四个当中,管道的用法相当于我们使用的队列,你往其中塞入数据的话,那么从另一端就可以取出来,否则就会堵塞,下面使用字符流的输入流作为例子:

package com.hotusm.io.learn.string;

import java.io.PipedReader;
import java.io.PipedWriter; /**
* 字符流取出管道
* 1.PipedReader(PipedWriter src, int pipeSize) 第一个参数为输入管道流 第二个参数为管道的大小
* 如果没有第二个参数那么默认的管道大小为1024
* 2.PipedReader() 没有参数的构造函数为还没初始化的状态 需要调用connect(PipedWriter src)
* 3.read() 会进行堵塞 直到有数据流到达 然后在进行读取
*/
public class PipedReaderTest { public static void main(String[] args) throws Exception{
testPipedReaderConnect();
}
public static void testPipedReaderConnect() throws Exception{
PipedReader pipedReader=new PipedReader();
final PipedWriter writer=new PipedWriter();
//这种方式进行连接
pipedReader.connect(writer);
char[] buff=new char[10];
new Thread(()->{
try {
//停留三秒钟之后
Thread.sleep(3000);
writer.write("hello piped");
} catch (Exception e) {
e.printStackTrace();
} }).start();
pipedReader.read(buff);
System.out.println(buff);
} }

3.字符流中独有的InputStreamReader 和OutputStreamWriter 。 使用适配器模式将字节流适配成字符流,这样就可以将字节流作为字符流使用。

4.输入流中特有的PushbackXXX 看上图种都是继承自XXXFilter ,它们都是=使用了装饰模式为读取的时候增加了回退的功能.下面使用字符形式展示其作用:

package com.hotusm.io.learn.string;

import java.io.CharArrayReader;
import java.io.PushbackReader; /**
* PushbackReader 能够将流或者字符进行回推到 缓冲区中. 1.PushbackReader(Reader reader,int size)
* size: 每一次的read()的个数 ,默认是1 同时也是缓冲区的大小 2.unread()重载方法
* 将一个或者多个的字符回推到缓冲区中,位置就是上一次读过的结尾 比如 abcd 读到c 现在推出gf 那么就是为 abcgfd 下次读的话 就会从
* gf开始读 3.skip(long size) 跳过size 个字符
*/
public class FilterReaderAndPushbackReaderTest { public static void main(String[] args) {
testFilterReaderUnreadSingleChar();
System.out.println();
testFilterReaderUnreadMutilChar();
testFilterReaderSkip();
} /**
* 输出:abcCd
*/
public static void testFilterReaderUnreadSingleChar() {
String str = "abcd";
try (CharArrayReader charArrayReader = new CharArrayReader(str.toCharArray());
PushbackReader pushbackReader = new PushbackReader(charArrayReader);) {
int c;
while ((c = pushbackReader.read()) != -1) {
System.out.print((char) c);
// unread()的用法 将字符给回推到缓冲区中
if (c == 'c') {
pushbackReader.unread('C');
}
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 输出:abcdefFUCgUC
*/
public static void testFilterReaderUnreadMutilChar() {
String str = "abcdefg";
try (CharArrayReader charArrayReader = new CharArrayReader(str.toCharArray());
PushbackReader pushbackReader = new PushbackReader(charArrayReader, 3);) {
char[] byteArr = new char[3];
// read方法会一直读入构造函数中第二个参数中的数量的字符
while ((pushbackReader.read(byteArr)) != -1) {
System.out.print(byteArr);
// unread()的用法 将字符给回推到缓冲区中
if (new String(byteArr).equals("def")) {
// 推回的不能大于缓冲区的 缓冲区就是我们构造函数的第二个参数
pushbackReader.unread("FUC".toCharArray());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 输出:abcfg
*/
public static void testFilterReaderSkip() {
String str = "abcdefg";
try (CharArrayReader charArrayReader = new CharArrayReader(str.toCharArray());
PushbackReader pushbackReader = new PushbackReader(charArrayReader, 3);) {
char[] byteArr = new char[3];
// read方法会一直读入构造函数中第二个参数中的
while ((pushbackReader.read(byteArr)) != -1) {
System.out.print(byteArr);
//这里是重点!!!
pushbackReader.skip(2L);
byteArr = new char[3];
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

5.输出流中特有的两个PrintWriter和PrintStream,和前面不同的是,这两个除了一个是字符一个是字节之外,还有其他的不同点.它们也要一些相似点.下面一一来展示。

当我们使用PrintWriter的时候,但我们设置了能够自动刷新的话,那么只有在println,printf,format方法调用的时候才会起作用,这点和字节流的PrintStream是不同的。下面是源码中的描述:

* <p> Unlike the {@link PrintStream} class, if automatic flushing is enabled
* it will be done only when one of the <tt>println</tt>, <tt>printf</tt>, or
* <tt>format</tt> methods is invoked, rather than whenever a newline character
* happens to be output. These methods use the platform's own notion of line
* separator rather than the newline character.

而PrintStream是是要调用了println或者是字符中进行了换行('\n')就会自动的刷新,这是和字符流中的不同点。源码中这样描述:

 <code>PrintStream</code> can be created so as to flush
* automatically; this means that the <code>flush</code> method is
* automatically invoked after a byte array is written, one of the
* <code>println</code> methods is invoked, or a newline character or byte
* (<code>'\n'</code>) is written.

参考: http://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html

------------ 增加于17.04.29

关于BufferedReader    在Socket编程中出现堵塞的问题。

首先看下面的代码(其中client对象是Socket):

private void doCommand(String command) throws IOException {
byte[] byets = command.getBytes(); OutputStream outputStream = client.getOutputStream();
outputStream.write(byets);
outputStream.flush(); InputStream inputStream = client.getInputStream(); BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
String line=bufferedReader.readLine();

上面这段代码是客户端Socket向服务端发送一个命令并且得到回应。上面的写法看起来并没有任何的问题,但是实际上在运行过程中你就会发现及时是服务端已经将数据发送完毕之后,客户端代码仍然堵塞着。

出现这面问题的原因是BufferedReader只要在遇到流结尾或者是流关闭的时候才算作完成,但是在Socket中,即使是服务端输入完毕,客户端也不能认为流关闭了,因为服务端还可以继续的向其中输入流,所以BufferedReader就会认为这个流一直没有结尾。正确的代码应该是:

private void doCommand(String command) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
writer.write(command);
writer.flush();
client.shutdownOutput(); BufferedInputStream buffer = new BufferedInputStream(client.getInputStream()); StringBuilder sb = new StringBuilder();
while (true) {
int c = buffer.read();
if (c == '\r' || c == '\n' || c == -1) {
break;
}
sb.append((char) c);
}
System.out.println(sb.toString());
client.shutdownInput(); }

Java-IO基础类回忆的更多相关文章

  1. Java IO设计模式彻底分析 (转载)

    一.引子(概括地介绍Java的IO) 无论是哪种编程语言,输入跟输出都是重要的一部分,Java也不例外,而且Java将输入/输出的功能和使用范畴做了很大的扩充.它采用了流的 机制来实现输入/输出,所谓 ...

  2. java.io包详细解说

    转自:http://hzxdark.iteye.com/blog/40133 hzxdark的博客 我不知道各位是师弟师妹们学java时是怎样的,就我的刚学java时的感觉,java.io包是最让我感 ...

  3. [Java] Java IO 概况

    Java IO 是 Java 的一套 API, 用于读入和写出数据(输入和输出).Java IO API 位于 java.io package.实际上 java.io package 没有解决所有的输 ...

  4. java IO流全面总结

    流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作. Ja ...

  5. Java IO与网络编程笔记

    <!doctype html>Java IO&NIO figure:first-child { margin-top: -20px; } #write ol, #write ul ...

  6. hudson运行出现java.io.IOException Cannot run program的错误分析

    作者:朱金灿 来源:http://blog.csdn.net/clever101 在昨天运行每日构建时hudson突然出错,错误信息如下: [MySoft3.1] $ cmd /c call &quo ...

  7. Java IO、网络编程、NIO、Netty、Hessian、RPC、RMI的学习路线

    好久没看Java IO这块的内容,感觉都快忘得差不多了.平成编程也没有设计到太多的Java基础知识,所以这里希望可以抽点时间回顾一下,让艾宾浩斯记忆曲线不要下降的太快. 回顾这个主要还是以总结为主,能 ...

  8. Java IO(九)FilterInputStream 和 FilterOutputStream

    Java IO(九)FilterInputStream 和 FilterOutputStream 一.介绍 FilterInputStream 和 FilterOutputStream 是过滤字节输入 ...

  9. java.IO输入输出流:过滤流:buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? ...

随机推荐

  1. 学习Selenium的历程

    Selenium资源包下载 我这段时间在学习Web自动化测试方面的知识,在搭建相应的环境上出现了问题.去Selenium官网下载相对应得包,老是下载不了.而如果直接到CSDN等上下载,需要积分,或者下 ...

  2. 【暴力枚举&BFS】Flow Free @RMRC2017/upcexam5124

    时间限制: 1 Sec 内存限制: 128 MB 题目描述 Flow Free is a puzzle that is played on a 2D grid of cells, with some ...

  3. Atcoder4105 Same Integers(模拟)

    https://abc093.contest.atcoder.jp/tasks/arc094_a?lang=en 思路题还是不太会做哈.感觉数据不大,一开始dfs做但是发现不是最优解,一想确实是这么一 ...

  4. RESTEASY ,从学会使用到了解原理。

    转载本文需注明出处:EAII企业架构创新研究院,违者必究.如需加入微信群参与微课堂.架构设计与讨论直播请直接回复公众号:“EAII企业架构创新研究院”.(微信号:eaworld) 1,背景知识; 1. ...

  5. linux下修改/dev/shm tmpfs文件系统大小

    默认系统就会加载/dev/shm ,它就是所谓的tmpfs,有人说跟ramdisk(虚拟磁盘),但不一样.象虚拟磁盘一样,tmpfs 可以使用您的 RAM,但它也可以使用您的交换分区来存储.而且传统的 ...

  6. Wordpress显示文章摘要

    放在文章的循环里: <?php if (!empty($post->post_excerpt) ) { //如果文章有摘要则输出摘要 the_excerpt(); } ?>

  7. fastjson转换json字符串key的首字母小写变大写的解决办法

    https://blog.csdn.net/erbao_2014/article/details/53688934 问题描述在开发过程中,由于接口文档的描述,要求json字符串的key首字母为大写,而 ...

  8. 模拟位置 定位 钉钉打卡 运动轨迹 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  9. 【转】Go Interface 源码剖析

    源网址:http://legendtkl.com/2017/07/01/golang-interface-implement/ 0.引言 在上一篇文章 <深入理解 Go Interface> ...

  10. linux驱动工程面试必问知识点

    linux内核原理面试必问(由易到难) 简单型 1:linux中内核空间及用户空间的区别?用户空间与内核通信方式有哪些? 2:linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化, ...