在软件开发中,数据流和数据库操作占据了一个很重要的位置,所以,熟悉操作数据流和数据库,对于每一个开发者来说都是很重要的,今天就来总结一下JavaI/O.

  流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

Java 内用 Unicode 编码存储字符,字符流处理类负责将外部的其他编码的字符流和 java 内 Unicode 字符流之间的转换。而类 InputStreamReader 和 OutputStreamWriter 处理字符流和字节流的转换。字符流(一次可以处理一个缓冲区)一次操作比字节流(一次一个字节)效率高。

结构图看一下整个数据流中的API结构和对象继承关系信息:

Java中的流分为两种,一种是字节流,另一种是字符流,字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串,而字节流处理单元为 1 个字节,操作字节和字节数组。分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的:

实例分析

( 一 )以字节为导向的 stream------InputStream/OutputStream



InputStream 和 OutputStream 是两个 abstact 类,对于字节为导向的 stream 都扩展这两个鸡肋(基类)

在这其中InputStream和OutputStream在早期的Java版本中就已经存在了,它们是基于字节流的,而基于字符流的Reader和Writer是后来加入作为补充的。以上的层次图是Java类库中的一个基本的层次体系。

  

在这四个抽象类中,InputStream和Reader定义了完全相同的接口:

int read() int read(char cbuf[]) int read(char cbuf[], int offset, int length) 

而OutputStream和Writer也是如此:

int write(int c)  int write(char cbuf[])  int write(char cbuf[], int offset, int length)

这六个方法都是最基本的,read()和write()通过方法的重载来读写一个字节,或者一个字节数组。

2、 OutputSteam





( 二 )以字符为导向的 stream Reader/Writer

以 Unicode 字符为导向的 stream ,表示以 Unicode 字符为单位从 stream 中读取或往 stream 中写入信息。

Reader/Writer 为 abstact 类

以 Unicode 字符为导向的 stream 包括下面几种类型:

1. Reader



总结

字节流和字符流的区别:

1,字节流读取的时候,读到一个字节就返回一个字节。字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,UTF-8码表中是3个字节)时。先去查指定的编码表,将查到的字符返回。

2,字节流可以处理所有类型数据,如图片,mp3,avi。而字符流只能处理字符数据。

结论:只要是处理纯文本数据,就要优先考虑使用字符流。除此之外都用字节流

Reader中的常见的方法:

1,int read():读取一个字符。返回的是读到的那个字符。如果读到流的末尾,返回-1.

2,int read(char[]):将读到的字符存入指定的数组中,返回的是读到的字符个数,也就是往数组里装的元素的个数。如果读到流的末尾,返回-1.

3,close():读取字符其实用的是window系统的功能,就希望使用完毕后,进行资源的释放

Writer中的常见的方法:

1,write(ch): 将一个字符写入到流中。

2,write(char[]): 将一个字符数组写入到流中。

3,write(String): 将一个字符串写入到流中。

4,flush():刷新流,将流中的数据刷新到目的地中,流还存在。

5,close():关闭资源:在关闭前会先调用flush(),刷新流中的数据去目的地。然流关闭。、

FileWriter:该类没有特有的方法只有自己的构造函数。该类特点在于

1,用于处理文本文件。

2,该类中有默认的编码表,

3,该类中有临时缓冲。

构造函数:在写入流对象初始化时,必须要有一个存储数据的目的地。

对于读取或者写入流对象的构造函数,以及读写方法,还有刷新关闭功能都会抛出IOException或其子类。所以都要进行处理。或者throws抛出,或者try catch处理

细节:

当指定绝对路径时,定义目录分隔符有两种方式:

1,反斜线但是一定要写两个。\\new FileWriter("c:\\demo.txt");

2,斜线/  写一个即可。new FileWriter("c:/demo.txt");

字符流的缓冲区:缓冲区的出现提高了对流的操作效率。

原理:其实就是将数组进行封装。

对应的对象:

BufferedWriter:特有方法:newLine():跨平台的换行符。

BufferedReader:特有方法:readLine():一次读一行,到行标记时,将行标记之前的字符数据作为字符串返回。当读到末尾时,返回null。

在使用缓冲区对象时,要明确,缓冲的存在是为了增强流的功能而存在,

所以在建立缓冲区对象时,要先有流对象存在。

其实缓冲内部就是在使用流对象的方法,只不过加入了数组对数据进行了临时存储。为了提高操作数据的效率。

readLine():方法的原理:

其实缓冲区中的该方法,用的还是与缓冲区关联的流对象的read方法。只不过,每一次读到一个字符,先不进行具体操作,先进行临时存储。当读取到回车标记时,将临时容器中存储的数据一次性返回。

既然明确了原理,我们也可以实现一个类似功能的方法。

import java.io.*;
public class TestBufferStream2 {
public static void main(String[] args) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\share\\java\\dat2.txt"));
BufferedReader br = new BufferedReader(
new FileReader("d:\\share\\java\\dat2.txt"));
String s = null;
for(int i=1;i<=100;i++){
s = String.valueOf(Math.random());
bw.write(s);
bw.newLine();
}
bw.flush();
while((s=br.readLine())!=null){
System.out.println(s);
}
bw.close();
br.close();
} catch (IOException e) { e.printStackTrace();}
}
}

操作数组的流对象。

1,操作字节数组

ByteArrayInputStream

ByteArrayOutputStream

toByteArray();

toString();

writeTo(OutputStream);

2,操作字符数组。

CharArrayReader

CharArrayWriter

对于这些流,源是内存。目的也是内存。

而且这些流并未调用系统资源。使用的就是内存中的数组。

所以这些在使用的时候不需要close。

操作数组的读取流在构造时,必须要明确一个数据源。所以要传入相对应的数组。

对于操作数组的写入流,在构造函数可以使用空参数。因为它内置了一个可变长度数组作为缓冲区。

Java学习从菜鸟变大鸟之二 输入输出流(IO)的更多相关文章

  1. Java学习从菜鸟变大鸟之一 hashCode()和equals()的本质区别和联系

    在学习java,根据视频做实例的过程中,对equals和hashcode两个方法理解稍微深刻一点,主要是它们两个很容易混淆,容易出错,自己又通过网上的资料学习,和大家分享 equals()方法 equ ...

  2. Java学习从菜鸟变大鸟之三 多线程中Thread 和Runnable的区别与运用

    多线程机制是java中的一个特点,掌握它对后面的知识的理解至关重要,是java工程师的必备知识,多线程指在单个程序中可以运行多个不同的线程执行的不同的任务,线程是一个程序内部的顺序控制流.进程是静态的 ...

  3. J2EE学习从菜鸟变大鸟之九 深入浅出理解 Servlet-----实例解析

    关于Servlet的基础内容在前面已经和大家分享过了,参考J2EE学习从菜鸟变大鸟之七 Servlet,现在结合到DRP中学习,深刻的体会Servlet起到了枢纽中转的作用,控制逻辑(到MVC中更像是 ...

  4. J2EE学习从菜鸟变大鸟之八 企业级项目开发的思考

    什么是企业级项目开发 "企业级项目".企业级项目开发,Java也是企业级项目开发,这个我们到处说.听,每天被我们挂在嘴边,可是到底什么项目才算是"企业级"?自己 ...

  5. J2EE学习从菜鸟变大鸟之六 EJB(Enterprise JavaBean)企业级Java组件

    EJB (EnterpriseJavaBean)是J2EE的一部分,定义了一个用于开发基于组件的企业多重应用程序的标准.其特点包括网络服务支持和核心开发工具(SDK).其称为Java 企业Bean,是 ...

  6. J2EE学习从菜鸟变大鸟之五 JDBC(Java Data Base Connectivity)

    JDBC刚开始学习这个的时候看到了,以为是ODBC呢,很是相似啊,总的来说还是基本上一类的东东,但是还有一些细微的区别,下面和大家一起分享学习. JDBC(Java Data Base Connect ...

  7. J2EE学习从菜鸟变大鸟之四 JNDI(Java Naming and Directory Interface)

    掌握 J2EE 是件不是很轻松的事哈,但是很有意思,抽象抽象哈哈,因为它包含的技术和缩略语在不断地增长.Java 命名和目录接口(Java Naming and Directory Interface ...

  8. J2EE学习从菜鸟变大鸟之七 Servlet

    Servlet现在自己的理解是一个控制器,简单的可以理解为不同的JSP页面由用户发送过来的请求可以由Servlet控制器来控制其向下调用的方向(结合三层好理解),但它比较特殊,因为它通常会从外界接收数 ...

  9. Java学习-039-源码 jar 包的二次开发扩展实例(源码修改)

    最近在使用已有的一些 jar 包时,发现有些 jar 包中的一些方法无法满足自己的一些需求,例如返回固定的格式,字符串处理等等,因而需要对原有 jar 文件中对应的 class 文件进行二次开发扩展, ...

随机推荐

  1. 在Spring Boot中使用Spring Security实现权限控制

    丢代码地址 https://gitee.com/a247292980/spring-security 再丢pom.xml <properties> <project.build.so ...

  2. CAP原理和BASE思想和ACID模型

    问题的解读 对于上面三个例子,相信大家一定看出来了,我们的终端用户在使用不同的计算机产品时对于数据一致性的需求是不一样的: 1.有些系统,既要快速地响应用户,同时还要保证系统的数据对于任意客户端都是真 ...

  3. fireBug引入JQuery,方便书写jq调试代码

    在控制台执行下段代码,等到网络中加载完成后,即可正常运行jq代码.也可以根据需要进行修改引入其他js代码. javascript:(function(url) { var s = document.c ...

  4. 如何joomla修改版权信息

    1.在language\zh_CN目录下有一个zh-CN.mod_footer.ini文件,修改里面的内容: 2.具体模板的html\mod_footer目录下的default.php文件内(具体文件 ...

  5. Java面试19|过于深入的问题

    1.synchronized关键字的实现原理 可以参考:http://www.jianshu.com/p/c5058b6fe8e5 2.CAS是由Unsafe类的compareAndSwap()方法实 ...

  6. 代理delegate

    1>代理的用处是什么? 监听那些不能通过addTarget监听的事件 主要用开负责在两个对象之间,发生某些事件时,传递或发送消息 当我们需要 监听某些事件时,但苹果没有提供相关监听方法(addt ...

  7. Node.js Domain 模块

    Node.js Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常.引入 Domain 模块 语法格式如下: var domain = require(" ...

  8. ZooKeeper之(四)配置与命令

    4.1 配置文件 ZooKeeper安装好之后,在安装目录的conf文件夹下可以找到一个名为"zoo_sample.cfg"的文件,是ZooKeeper配置文件的模板. ZooKe ...

  9. Rails中rspec测试xxx_path调用失败的解决

    首先要想生成类似于home_path,about_path之类的方法,必须在路由文件中添加对应方法: match '/help',to:"static_pages#help",vi ...

  10. 多线程(四) 实现线程范围内模块之间共享数据及线程间数据独立(Map集合)

    多个线程访问共享对象和数据的方式 1.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 2.如果每个线程执行的代码 ...