I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道。在当今这个数据大爆炸时代,I/O 问题尤其突出,很容易成为一个性能瓶颈。

本文的目的是分析 I/O 的内在工作机制,以及java I/O类库的基本架构,以帮助初学者从总体上了解Java I/O。具体各个I/O类库的使用,请读者在遇到实际问题时,结合本文的讲解来理解掌握。

1.什么是I/O

描述Java的I/O机制,我们用从河中抽水的例子来解释读文件的过程。

要将河水抽出来,首先我们需要一个抽水机,然后把抽水机丢到河流里。这里,河水相当于文件,我们需要建立一个抽水机,并将抽水机与河水关联起来:

FileInputStream fis = new FileInputStream("E:/rivier.txt");

fis就是抽水机,E:/rivier.txt就是河水。

设备准备好了,就可以打开水龙头获得水啦,但获得的水需要存放,所以第二步,我们还需要先有一个盛水的容器:

byte[] bottle = new byte[10];

容器bottle是一个byte类型的数组,大小为10.之所以将容器定义为byte数组而不是其它数组类型,是因为我们使用的这个抽水机比较特殊,抽出来的水最小单位就是1个byte(你就当1滴水来理解吧)。

接下来,将容器放到水龙头下面,打开水龙头,就开始将水抽进容器里了。

fis.read(bottle);

这样抽水机fis就抽出了10滴水(10个byte)放到bottle这个容器里面了。然后bottle里的数据就可以任意有我们处置了。

Java为我们提供了两种类型的抽水机,第一种抽水机的名字叫做XXXInputStream,它抽水的单位是字节,当然盛水的容器自然就是字节数组byte[]。

第二种抽水机的名字叫做XXXReader,它抽水的单位是字符,盛水容器就是字符数组char[]。

也就是说,我们如果我们用第一种抽水机XXXInputStream,抽出来的是byte;如果用第二种抽水机XXXReader,抽出来的是char。(有关字节byte和字符char的区别,自己脑补...)

这里的XXX表示抽的水是河水,还是湖水、海水、污水......,即XXX表示数据的来源。如FileInputStream,表示这个抽水机是专门从文件中读取数据的;ByteArrayInputStream,就是专门从字符数组也就是内存中读数据的。

小结一下,要读一个文件,步骤如下:

1. 实例化一个XXXInputStream对象(选择一种抽水机,指定水源)

2. 确定接收数据的对象(准备容器)

3. read()(打开水龙头)

现在,通过上面的抽水机,用户可以从各种地方,按各种大小的被子来得到水。但用户觉得抽水机功能还是弱了点, 如果打开水龙头,就是热水,就是热咖啡就好啦!

显然抽水机已经力不从心了,如果把加热,煮咖啡的功能设计到抽水机里面,那么抽水机会显得太庞杂,也增加了出故障时维修的难度。

所以,我们换一种思路,在抽水机的水龙头下,接一根加热管:

FileInputStream fis = new FileInputStream("e:/yellow_river.txt");//准备好抽水机
ObjectInputStream ois= new ObjectInputStream(fis);//增加一个加热器

这样,只需要调用加热管的水龙头,就可以获得热水啦:

ois.readDouble();//读出来的就是一个double型的数据,不再是byte数据(即抽出的就是热水)

所以,总的来说,在Java中读文件,就像抽水,首先,需要根据读取单位,根据读取源,选择合适的抽水机。如果需要,还可以在抽水机后添加管子,增强功能。

请试着按照排水的例子,描述文件的机制。

2. 实例理解

现在我们结合上面的例子,来理解几个实例。

1)按字节读文件FileInputStream

FileInputStream fis = new FileInputStream("e:/in.txt");   //创建输入流对象(抽水机)
while (fis.available() > 0) {
byte[] b = new byte[10]; //创建数组(盛水容器)
int nResult = fis.read(b); //读数据到数组,并且读到数据时,nResult被赋值为>-1的整数,表示实际读了多少个byte
if (nResult == -1) //文件中的数据读完了,没数据可读了
break;
System.out.println(new String(b));
}
fis.close(); //数据读完了,抽水机需要关掉

2)按字符读文件FileReader:

FileReader rdFile = new FileReader("e:/in.txt");   //实例化文件输入流对象(抽水机)
while (rdFile.ready()) { //输入流是否准备好读(抽水机是否准备好抽水)
char[] chIn = new char[10]; //准备容器
int nResult = rdFile.read(chIn); //读数据
if (nResult == -1) //如果没有读到数据
、 break;
System.out.println(chIn);
}
rdFile.close(); //不抽水了,关掉抽水机

FileReader满足XXXReader命名规则,从名字可以判断是按字符来读数据,并且数据来源是文件。

3.带缓冲区的读

还是用抽水的例子来讲解什么是缓冲区。我们在使用水的时候,可以有两种方法,一种是每次要用水,就去打开水龙头,等着它将容器装满。第二种方法是,家里有一个大水缸,先将大水缸装满,每次用水的时候,直接去水缸里取。当水缸里的谁不够用时,再打开水龙头将大水缸放满。

不考虑水存放时间长了会变质的影响,显然第二种方法效率高。

文件通常放在磁盘等设备中,读写速度远没有内存的速度快。上面FileInputStream或FileReader每次执行read()方法,都会去硬盘读取一次。如果事先将文件中的数据读取一定大小到内存中,以后每次read(),从这块内存中读,就会减少硬盘的读写次数,效率高得多。如果这块内存中的数据不够用了,再去硬盘继续读数据把这块内存填满,后面继续使用这块内存。这块内存就是缓冲区。

用法示例:

FileReader rdFile = new FileReader("e:/in.txt"); //创建字符文件输入流对象
BufferedReader brdFile = new BufferedReader(rdFile); //创建一个BufferedReader对象
String strLine;
while ((strLine = brdFile.readLine()) != null) {
System.out.println(strLine);
}
brdFile.close();

例子中,将rdFile这个FileReader对象包装在BufferedReader对象brdFile里,直接操作brdFile对象,就可以实现带缓冲功能的读操作了。

同样,按字节读可以使用BufferedInputStream类来对InputSteam进行包装。

4. I/O体系结构

我们已经了解了Java I/O 系统,并学会了一些简单的I/O操作,接下来请打开Java Doc,让我们看看Sun公司是怎样通过面向对象的思想,设计I/O系统的。

总结一下:

1. InputStream和OutputStream是按字节读写数据的抽象类,是所有字节输入输出流的基类。

2. Reader和Writer是按字符读写数据的抽象类,是所有字符输入输出流的基类。

3. 继承它们的都是针对特定数据源的“抽水机”或“排水机”,提供了read和write的基本实现。

4. 构造方法一般都需要提供数据源。

5. 不必记住每个类的具体用法,只需要掌握IO的总体结构,然后记住几个重要类的功能,至于具体的成员方法的用法,可以在使用的时候再去查看方法的申明定义或查看在线Java Doc。

【实践练习】

从网络获取天气数据,将获取到的数据在控制台打印输出。

package WeatherDemo;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection; public class MyWeather { public MyWeather(String Cityid) throws IOException {
String Ctiyid;
URLConnection connectionData;
StringBuilder sb;
BufferedReader br;// 读取data数据流
sb = new StringBuilder(); URL url = new URL("http://api.k780.com:88/?app=weather.future&weaid=" + Cityid + "&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json");
connectionData = url.openConnection();
connectionData.setConnectTimeout(1000); try {
br = new BufferedReader(new InputStreamReader(
connectionData.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null)
sb.append(line);
} catch (SocketTimeoutException e) {
System.out.println("连接超时");
} catch (FileNotFoundException e) {
System.out.println("加载文件出错");
}
System.out.print(sb.toString()); }
public static void main(String[] args) {
try {
new MyWeather("101010100"); // 101010100(北京)就是你的城市代码
} catch (Exception e) {
e.printStackTrace();
}
}
}

首先,需要在网络搜索获取天气信息的途径,这里提供本文作者自己找到的一篇博客:http://www.nohacks.cn/post-35.html,本代码使用了博客中“ 3.3  未来几天天气”里提到的api。

有关URL的用法这里可不必关心,重点放在如何读取网络数据。

【问题】

1.new InputStreamReader(connectionData.getInputStream(), "UTF-8"))参数“UTF-8"作用是什么?不要此参数编译能否通过?看到什么结果?

2.

br = new BufferedReader(new InputStreamReader(
connectionData.getInputStream(), "UTF-8"));

能不能写成:

br = new BufferedReader(connectionData.getInputStream());

如果不能,为什么?

3.为什么要用到StringBuilder sb,而不是String sb?

Java入门:Java IO概括的更多相关文章

  1. 三、Java入门

    Java入门 Java的特性和优势 特性 ​ 简单 ​ 面对对象 ​ 可移植性 优势 ​ 性能高 ​ 分布式(跨平台:Write Once .Run Anywhere) ​ 动态性(反射) ​ 多线程 ...

  2. Java中的IO流 - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...

  3. Java入门 - 语言基础 - 20.Stream和File和IO

    原文地址:http://www.work100.net/training/java-stream-file-io.html 更多教程:光束云 - 免费课程 Stream和File和IO 序号 文内章节 ...

  4. Java入门-浅析Java学习从入门到精通【转】

    一. JDK (Java Development Kit)  JDK是整个Java的核心,包括了Java运行环境(Java Runtime Envirnment),一堆Java工具和Java基础的类库 ...

  5. Java 入门

    Java 入门 入门书籍 Java相关书籍: <Java编程思想> 算是比较经典和全面的书籍; 10章可以快速过一下,都是基本语法,不需要花太多时间. 中后段的一些章节,类型信息.泛型.容 ...

  6. Java开发知识之Java入门

    Java开发知识之Java入门 一丶了解JAVA的版本 JAVA 有三个版本 JAVA SE: 标准版,开发桌面跟商务应用程序 JAVA SE 包括了Java的核心类库,集合,IO 数据库连接 以及网 ...

  7. Java入门(一):Hello World !

    前言 从今天开始,准备写Java Web开发的系列文章,毕竟自己主攻的还是Java方向,Python只是业余学习的兴趣使然,在第二技能还没有培养成熟前,做好第一技能的巩固和提高是很有必要的.从正式入行 ...

  8. Java 入门进阶

    Java 入门进阶 發表於 2015-04-16 http://xielong.me/2015/04/16/%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%B7%A5%E7%A8%8B% ...

  9. Java入门:注册模块的实现

    1.主活动图 用户选择注册选项,进入注册界面,开始输入注册信息,到最后完成注册.具体的活动图如下: 以上活动图中,矩形框里的操作不是在一个类里面实现的,而是通过Form类和UserService类来实 ...

  10. java入门概念梳理总结

    Java入门学习 简介 public class HelloWorld { public static void main(String []args) { System.out.println(&q ...

随机推荐

  1. AJAX(Asynchronous JavaScript and XML)学习笔记

    基本概念: 1.AJAX不是一种新的编程语言,而是一种使用现有标准的新方法. 2.AJAX最大的优点是在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容,用于创建快速动态网页(传统网页如 ...

  2. 互评Beta版本——杨老师粉丝群——Pinball

    互评beta版本    杨老师粉丝群——<PinBall> 一.基于NABCD评论作品,及改进建议 1.根据(不限于)NABCD评论作品的选题 (1)N(Need,需求) 随着年龄的增长, ...

  3. 团队博客作业Week3 --- 项目选择&&需求疑问

    项目选择 经过团队内所有成员一致探讨,我们团队选择完善和改进之学霸系统的第二个子模块,即:网站内容结构定义和数据处理.具体的要求如下:(摘自Xueba系统项目需求) 网站内容结构定义和数据处理(Con ...

  4. java实验三实验报告

    一.实验内容 1. XP基础 2. XP核心实践 3. 相关工具 二.实验过程(本次试验是在自己电脑上完成,没有使用实验楼) (一)敏捷开发与XP 1.XP是以开发符合客户需要的软件为目标而产生的一种 ...

  5. ListView高效分页

    使用控件自带的分页功能时,会先将所查询的数据全部加载出来,若数据量较大,则造成浏览器端等待时间过长. 然而在庞大的数据量,用户所需要的不过是那么几条,甚至只要其中的一条数据,所以,为了减少开销,每次只 ...

  6. 深入理解Java虚拟机&运行时数据区

      其中,程序计数器.虚拟机栈.本地方法栈3个区域随线程而生,随线程而灭.

  7. Mac OS10.10 openfire无法启动问题

    1.我用的Java版本是Version 8 Update 51,验证方法可到这个网址下去验证http://www.java.com/zh_CN/download/installed.jsp 2.ope ...

  8. [51单片机] Keil C51中变量的使用方法详解

    引言    8051内核单片机是一种通用单片机,在国内占有较大的市场份额.在将C语言用于51内核单片机的研究方面,Keil公司做得最为成功.由于51内核单片机的存储结构的特殊性,Keil C51中变量 ...

  9. grunt入门讲解2:如何使用 Gruntfile 配置任务

    Grunt的task配置都是在 Gruntfile 中的grunt.initConfig方法中指定的.此配置主要包括以任务名称命名的属性,和其他任意数据.一旦这些代表任意数据的属性与任务所需要的属性相 ...

  10. 用vue实现省市县三级联动

    我真的没想到这个会困扰到我.最开始以为,不就是直接找个简单的插件就实现了吗,jquery插件找了几个,都没有达到目的. 需求是这样的: 点击input框,弹出一个popup,然后可以滚动选择省,市,县 ...