Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 351|回复: 0

[JavaIO学习]浅谈Java的输入输出流

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-31 23:58:02 | 显示全部楼层 |阅读模式
    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 + "
    ";
                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. BufferedReader是Reader的一个子类,它具有缓冲的作用,避免了频繁的从物理设备中读取信息。它有以下两个构造函数:
      
       
       
        BufferedReader(Reader in)
    BufferedReader(Reader 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. InputStreamReader是InputStream和Reader之间的桥梁,由于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 BufferedInputStream( new FileInputStream( "Redirecting.java"));
                   PrintStream out = new PrintStream( new BufferedOutputStream( new FileOutputStream("test.out")));
                   System.setIn(in);
                   System.setOut(out);               BufferedReader br = new BufferedReader( new 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:
    " + "username: " + username + "
    date: " + date + "
    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 ObjectOutputStream( new FileOutputStream("Logon.out"));
                   o.writeObject(a);
                   o.close();               int seconds = 5;
                   long t = System.currentTimeMillis() + seconds * 1000;
                   while(System.currentTimeMillis() < t) ;

                   ObjectInputStream in = new ObjectInputStream( new 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 ObjectOutputStream( new FileOutputStream("Logon.out"));新建一个对象输出流包装一个文件流,表示对象序列化的目的地是文件Logon.out。然后用方法writeObject开始写入。想要还原的时候也很简单ObjectInputStream in = new ObjectInputStream( new FileInputStream("Logon.out"));新建一个对象输入流以文件流Logon.out为参数,之后调用readObject方法就可以了。
      需要说明一点,对象序列化有一个神奇之处就是,它建立了一张对象网,将当前要序列化的对象中所持有的引用指向的对象都包含起来一起写入到文件,更为奇妙的是,如果你一次序列化了好几个对象,它们中相同的内容将会被共享写入。这的确是一个非常好的机制。它可以用来实现深层拷贝。
      关键字transient在这里表示当前内容将不被序列化,比如例子中的密码,需要保密,所以没有被写入文件。
      对Java的输入输出功能,就浅浅的介绍到这里,本文的目的只是开一个好头,希望能让大家对Java输入输出流有个基本的认识。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-25 19:43 , Processed in 0.300521 second(s), 36 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表