Java的输入输出流

news/2024/7/4 1:33:00 标签: java, string, date, import, null, class
class="baidu_pl">
class="article_content clearfix">
class="htmledit_views"> Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作, 网络上的数据流,字符串流,对象流,zip文件流....本文的目的是为大家做一个简要的介绍。

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

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



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

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

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">
class="unnamed1">intclass="unnamed1"> read()
int read(char cbuf[])
int read(char cbuf[], int offset, int length)

  而OutputStream和Writer也是如此:

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">
class="unnamed1">intclass="unnamed1"> write(int c)
int write(char cbuf[])
int write(char cbuf[], int offset, int length)

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

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

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">

class="unnamed1">class="tags" href="/tags/IMPORT.html" title=import>importclass="unnamed1"> class="tags" href="/tags/JAVA.html" title=java>java.io.*;

  1. class="unnamed1" align="left">public class IOStreamDemo {

          public void samples() throws IOException {

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

    class="unnamed1" align="left">           //2. 这是从文件中逐行读入数据

    class="unnamed1" align="left">           BufferedReader in = new BufferedReader(new FileReader("IOStreamDemo.class="tags" href="/tags/JAVA.html" title=java>java"));
               String s, s2 = new String();
               while((s = in.readLine())!= class="tags" href="/tags/NULL.html" title=null>null
                          s2 += s + "/n"
               in.close();

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

    class="unnamed1">           //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()) != class="tags" href="/tags/NULL.html" title=null>null
                                     out1.println(lineCount++ + ": " + s);
                          out1.close();
               } catch(EOFException e) {
                          System.err.println("End of stream");
               }
          }

    }

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

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

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">
class="unnamed1">BufferedReaderclass="unnamed1">(Reader in)
BufferedReaderReader in, int sz)

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

  它的基本方法:

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">
class="unnamed1">voidclass="unnamed1"> 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提供了这样一个功能,将标准的输入输出流转向,也就是说,我们可以将某个其他的流设为标准输入或输出流,看下面这个例子:

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">

class="unnamed1">class="tags" href="/tags/IMPORT.html" title=import>importclass="unnamed1"> class="tags" href="/tags/JAVA.html" title=java>java.io.*;

class="unnamed1" align="left">public class Redirecting {

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

class="unnamed1">              BufferedReader br = new BufferedReadernew InputStreamReader(System.in));
              String s;
              while((s = br.readLine()) != class="tags" href="/tags/NULL.html" title=null>null
                     System.out.println(s);
              out.close();
              System.setOut(console);
      }
}

  在这里class="tags" href="/tags/JAVA.html" title=java>java.lang.System的静态方法

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">
class="unnamed1">static voidclass="unnamed1"> setIn(InputStream in)
static void setOut(PrintStream out)

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

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

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

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

class="code" bgcolor="#ffffff" border="0" cellpadding="0" cellspacing="2" width="100%">

class="unnamed1">class="tags" href="/tags/IMPORT.html" title=import>importclass="unnamed1"> class="tags" href="/tags/JAVA.html" title=java>java.io.*;
class="tags" href="/tags/IMPORT.html" title=import>import class="tags" href="/tags/JAVA.html" title=java>java.util.*;

class="unnamed1" align="left">public class Logon implements Serializable {

       private Date class="tags" href="/tags/DATE.html" title=date>date = new Date();
       private String username;
       private transient String password;

class="unnamed1" align="left">
       Logon(String name, String pwd) {
              username = name;
              password = pwd;
       }

class="unnamed1" align="left">
       public String toString() {
              String pwd = (password == class="tags" href="/tags/NULL.html" title=null>null) ? "(n/a)" : password;
              return "logon info: /n " + "username: " + username + "/n class="tags" href="/tags/DATE.html" title=date>date: " + class="tags" href="/tags/DATE.html" title=date>date + "/n password: " + pwd;
       }

class="unnamed1" align="left">
       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();

class="unnamed1">              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输入输出流有个基本的认识。


http://www.niftyadmin.cn/n/1153023.html

相关文章

Linux Shell常用脚本整理

轮询检测Apache状态并启用钉钉报警◆ #!/bin/bashshell_user"root" shell_domain"apache"shell_list"/root/ip_list" shell_rowcat $shell_list |wc -lfunction trans_text(){ text$1curl https://oapi.dingtalk.com/robot/send?access_tokenb4…

CSS3中动画属性transform、transition 和 animation

CSS3中和动画有关的属性有三个 transform、transition 和 animation。下面来一一说明: transform 从字面来看transform的释义为改变&#xff0c;使…变形&#xff1b;转换 。这里我们就可以理解为变形。那都能怎么变呢&#xff1f; none 表示不进行变换&#xff1b; rotate 旋…

一个有用的从Reader向InputStream转换的类

public class ReaderInputStream extends InputStream {protected Reader reader;protected ByteArrayOutputStream byteArrayOut;protected Writer writer;protected char[] chars;protected byte[] buffer;protected int index, length;/*** 带Reader参数构造函数** param re…

2019.01.04 洛谷P4719 【模板】动态dp(链分治+ddp)

传送门ddpddpddp模板题。 题意简述&#xff1a;给你一棵树&#xff0c;支持修改一个点&#xff0c;维护整棵树的最大带权独立集。 思路&#xff1a; 我们考虑如果没有修改怎么做。 貌似就是一个sbsbsb树形dpdpdp&#xff0c;fi,0f_{i,0}fi,0​表示不选iii的最大值&#xff0c;f…

五大分布式缓存技术

2019独角兽企业重金招聘Python工程师标准>>> 在开发中大型Java软件项目时&#xff0c;很多Java架构师都会遇到数据库读写瓶颈&#xff0c;如果你在系统架构时并没有将缓存策略考虑进去&#xff0c;或者并没有选择更优的缓存策略&#xff0c;那么到时候重构起来将会是…

1.9-while循环

while 多用于死循环#!/bin/bash#每隔3秒&#xff0c;输出系统时间while : :作为永恒帧dodate %Tsleep 3done#!/bin/bash#当n小于等于10时&#xff0c;n1&#xff0c;并显示变量的值n0 不用&#xff1a;永恒帧时&#xff0c;先赋予可执…

关闭页面时,写入日志的问题

在大家的帮助下&#xff0c;搞定拉。。记录下来。。/** 关闭页面时&#xff0c;写入日志 auther: wully **/window.onbeforeunload handler_closePage; /** 通用&#xff0c;当是会有网络负担 var url "http://" document.domain; **///var url "http://....l…

zTree基础

zTree使用 zTree 是一个依靠 jQuery 实现的多功能 “树插件”&#xff0c; 而且拥有较好的浏览器兼容性&#xff0c;有着丰富的功能以及可以自定义样式&#xff0c;足以满足大部分业务的开发。 第一步先导入css及js文件 <link rel"stylesheet" type"text/css…