`
ss1
  • 浏览: 77644 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

完全精通java输入输出流

阅读更多

  Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库 中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流....本文的目的 是为大家做一个简要的介绍。

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

  Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):InputStream,OutputStream,Reader,Writer。Java中其他多种多样变化的流均是由它们派生出来的:



  在这其中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()通过方法的重载来读写一个字节,或者一个字节数组。

  更多灵活多变的功能是由它们的子类来扩充完成的。知道了Java输入输出的基本层次结构以后,本文在这里想给大家一些以后可以反复应用例子,对于所有子类的细节及其功能并不详细讨论。

import java.io.*;

    public class IOStreamDemo {

          public void samples() throws IOException {

               //1. 这是从键盘读入一行数据,返回的是一个字符串
               BufferedReader stdin =new BufferedReader(new InputStreamReader(System.in));
               System .out.print("Enter a line:" );
               System .out.println(stdin.readLine());

               //2. 这是从文件中逐行读入数据

               BufferedReader in = new BufferedReader(new FileReader("IOStreamDemo.java" ));
               String s, s2 = new String();
               while ((s = in.readLine())!= null
                          s2 += s + "\n"
               in.close();

               //3. 这是从一个字符串中逐个读入字节
               StringReader in1 = new StringReader(s2);
               int c;
               while ((c = in1.read()) != -1)
                          System .out.print((char)c);

               //4. 这是将一个字符串写入文件
               try {
                          BufferedReader in2 = new BufferedReader(new StringReader(s2));
                          PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out" )));
                          int lineCount = 1;
                          while ((s = in2.readLine()) != null
                                     out1.println(lineCount++ + ": " + s);
                          out1.close();
               } catch (EOFException e) {
                          System .err.println("End of stream" );
               }
          }

    }

  对于上面的例子,需要说明的有以下几点:

  1. BufferedReaderReader 的一个子类,它具有缓冲的作用,避免了频繁的从物理设备中读取信息。它有以下两个构造函数:

BufferedReader Reader in)
BufferedReaderReader in, int sz)

  这里的sz是指定缓冲区的大小。

  它的基本方法:

void close(//关闭流

           void mark(int readAheadLimit) //标记当前位置

           boolean markSupported() //是否支持标记

           int read() //继承自Reader的基本方法

           int read(char [] cbuf, int off, int len) //继承自Reader的基本方法

           String readLine() //读取一行内容并以字符串形式返回

           boolean ready() //判断流是否已经做好读入的准备

           void reset() //重设到最近的一个标记

           long skip(long n) //跳过指定个数的字符读取

  2. InputStreamReaderInputStreamReader 之间的桥梁,由于System.in是字节流,需要用它来包装之后变为字符流供给             BufferedReader 使用。

  3. PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out" )));

  这句话体现了Java输入输出系统的一个特点,为了达到某个目的,需要包装好几层。首先,输出目的地是文件IODemo.out,所以最内层包装的是FileWriter,建立一个输出文件流,接下来,我们希望这个流是缓冲的,所以用BufferedWriter 来包装它以达到目的,最后,我们需要格式化输出结果,于是将PrintWriter 包在最外层。

  Java提供了这样一个功能,将标准的输入输出流转向,也就是说,我们可以将某个其他的流设为标准输入或输出流,看下面这个例子:

import java.io.*;

public class Redirecting {

       public static void
main(String [] args) throws IOException {
              PrintStream console = System.out;
              BufferedInputStream in = new BufferedInputStreamnew FileInputStream"Redirecting.java" ));
              PrintStream out = new PrintStream ( new BufferedOutputStream new FileOutputStream"test.out" )));
              System.setIn(in);
              System.setOut(out);

              BufferedReader br = new BufferedReadernew InputStreamReader (System.in));
              String s;
              while ((s = br.readLine()) != null
                     System.out.println(s);
              out.close();
              System.setOut(console);
      }
}

  在这里java.lang.System的静态方法

static void setIn(InputStream in)
static void setOut(PrintStream out)

  提供了重新定义标准输入输出流的方法,这样做是很方便的,比如一个程序的结果有很多,有时候甚至要翻页显示,这样不便于观看结果,这是你就可以将标准输出流定义为一个文件流,程序运行完之后打开相应的文件观看结果,就直观了许多。

  Java流有着另一个重要的用途,那就是利用对象流对对象进行序列化。下面将开始介绍这方面的问题。

  在一个程序运行的时候,其中的变量数据是保存在内存中的,一旦程序结束这些数据将不会被保存,一种解决的办法是将数据写入文件,而Java中提供了一种机制,它可以将程序中的对象写入文件,之后再从文件中把对象读出来重新建立。这就是所谓的对象序列化Java中引入它主要是为了RMI(Remote Method Invocation)和Java Bean所用,不过在平时应用中,它也是很有用的一种技术。

  所有需要实现对象序列化的对象必须首先实现Serializable接口。下面看一个例子:

import java.io.*;
import java.util.*;

public class Logon implements Serializable {

       private Date date = new Date();
       private String username;
       private transient String password;


       Logon(String name, String pwd) {
              username = name;
              password = pwd;
       }


       public String toString() {
              String pwd = (password == null ) ? "(n/a)" : password;
              return "logon info: \n " + "username: " + username + "\n date: " + date + "\n password: " + pwd;
       }


       public static void
main(String[] args) throws IOException , ClassNotFoundException {
              Logon a = new Logon("Morgan" , "morgan83" );
              System .out.println( "logon a = " + a);
              ObjectOutputStream o = new ObjectOutputStreamnew FileOutputStream"Logon.out" ));
              o.writeObject(a);
              o.close();

              int seconds = 5;
              long t = System .currentTimeMillis() + seconds * 1000;
              whileSystem .currentTimeMillis() < t) ;

              ObjectInputStream in = new ObjectInputStreamnew FileInputStream"Logon.out" ));
              System .out.println( "Recovering object at " + new Date());
              a = (Logon)in.readObject();
              System .out.println("logon a = " + a);
       }
}

  类Logon是一个记录登录信息的类,包括用户名和密码。首先它实现了接口Serializable,这就标志着它可以被序列化。之后再main方法里ObjectOutputStream o = new ObjectOutputStreamnew FileOutputStream"Logon.out" ));新建一个对象输出流包装一个文件流,表示对象序列化的目的地是文件Logon.out。然后用方法writeObject 开始写入。想要还原的时候也很简单ObjectInputStream in = new ObjectInputStreamnew FileInputStream"Logon.out" ));新建一个对象输入流以文件流Logon.out为参数,之后调用readObject方法就可以了。

  需要说明一点,对象序列化有一个神奇之处就是,它建立了一张对象网,将当前要序列化的对象中所持有的引用指向的对象 都包含起来一起写入到文件,更为奇妙的是,如果你一次序列化了好几个对象,它们中相同的内容将会被共享写入。这的确是一个非常好的机制。它可以用来实现深 层拷贝。

  关键字transient在这里表示当前内容将不被序列化,比如例子中的密码,需要保密,所以没有被写入文件。

  对Java的输入输出功能,就浅浅的介绍到这里,本文的目的只是开一个好头,希望能让大家对Java输入输出流有个基本的认识。

分享到:
评论
1 楼 markxing 2010-08-27  
不错不错,较详细。我一直搞不明白java的输入输出流,看了楼主的文章后感觉思路清晰多了。 收藏,拜谢!

相关推荐

    精通Java:JDK、数据库系统开发Web开发(实例代码)

    Java高级技术 第15章 字符串处理 第16章 I/O输入输出流 第17章 线程 第18章 网络程序设计 第19章 国际化和本地化 第20章 泛型程序设计 第21章 访问数据库 第22章 获取XML数据 第23章 ...

    JAVA课程教学由简单到复杂

    详解Java,从入门到精通 第一章 计算机编程语言概述 第二章 Java 编程基础 第三章 类和对象 第四章 类的高级特性 ...第六章输入输出流 第七章GUI 编程 第八章线程 第九章Applet与多媒体 第十章 第十一章

    Python变量的输入输出-格式化输出整数变量

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    张孝祥Java就业培训教程.pdf

    如果你想非常轻松就精通Java编程,并期望学完便能参加实际的开发工作,本书就是你非常好的一个选择。 目录: 第1章 Java开发前奏 1.1 Java虚拟机及Java的跨平台原理 1.2 Java开发环境的搭建 1.3 体验Java编程的过程...

    Python变量的输入输出-格式化输出字符串变量

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-提出问题—从控制台输入数字需要两个变量处理

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-格式化输出语法介绍

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-输入和函数的概念

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-格式化输出及小结

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-格式化输出浮点型变量

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-类型转换函数介绍

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-单步执行确认变量数量

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-买苹果增强版演练

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    Python变量的输入输出-input函数的基本使用

    Python还被语言流行指数的编译器Tiobe将它被评为最受欢迎的编程语言,20多年来首次将其置于Java、C和JavaScript之上,真的非常荣幸了 自从20世纪90年代初Python语言诞生至2022年,它已被逐渐广泛应用于系统管理...

    网管教程 从入门到精通软件篇.txt

    网管教程 从入门到精通软件篇 ★一。★详细的xp修复控制台命令和用法!!! 放入xp(2000)的光盘,安装时候选R,修复! Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的...

    精通javascript

    • 9.12.htm 事件流测试 • 9.13.htm DOM2 事件模型基本语法 • 9.14.htm DOM2 鼠标事件 • 9.15.htm 取消默认动作之一 • 9.16.htm 取消默认动作之二 • 9.17....

Global site tag (gtag.js) - Google Analytics