Java系列(十八)__Java IO(2)

Java系列(十八)__Java  IO(2)

1、System类对IO支持

对于System.out.println()实际上是一个非常熟悉的语法了,但是下面来看一下,在System类之中定义的三个常量:

                   · 错误输出:public static final PrintStream err;

                   · 系统输出:public static final PrintStream out;

                   · 系统输入:public static final InputStream in。

         实际上之前一直使用的系统打印输出,都是调用的IO操作完成的,利用PrintStream类完成。

1、   错误输出:System.err

package cn.mldn.demo;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        try {

            Integer.parseInt("abc") ;

        } catch (Exception e) {

            System.err.println(e) ;

            System.out.println(e) ;

        }

    }

}

         最早设计两个输出的目的在于:err是输出不希望用户看见的错误信息,而out是输出用户可以看见的信息,但是对于err意义不大,因为所有的异常打印都使用printStackTrace()方法完成。

2、   系统输出:System.out

         System.out对应的是标准输出设备 —— 显示器,其默认就是表示向显示器屏幕上显示数据。

范例:做一个荒唐的功能,利用OutputStream实现屏幕输出

package cn.mldn.demo;

import java.io.OutputStream;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        OutputStream output = System.out // 系统输出

        output.write("Hello World.".getBytes());    // 向屏幕上输出

    }

}

         现在的OutputStream的输出位置完全由实例化它的对象来决定。

3、   系统输入:System.in

         在很多语言里面都支持有键盘输入功能,但非常遗憾的是Java没有直接提供,而且要想实现键盘的输入数据,则只能够利用System.in完成,System.in对应着标准输入设备 —— 键盘。

范例:实现键盘输入

package cn.mldn.demo;

import java.io.InputStream;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        InputStream input = System.in; // 由键盘输入而来

        System.out.print("请输入数据:");

        byte data[] = new byte[1024]; // 保存输入数据

        int len = input.read(data); // 接收键盘数据

        System.out.println(new String(data, 0, len));

        input.close();

    }

}

         但是这个时候的键盘输入是存在有问题的,因为有长度限制。发现超过长度外的数据就不接收了,这个问题如何解决呢?

范例:不设置读取长度

package cn.mldn.demo;

import java.io.InputStream;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        InputStream input = System.in; // 由键盘输入而来

        System.out.print("请输入数据:");

        StringBuffer buf = new StringBuffer();

        int temp = 0 ;  // 保存每次读取的数据

        while ((temp = input.read()) != -1) {

            if (temp == '\n') {

                break ;

            }

            buf.append((char) temp);

        }

        System.out.println(buf);

        input.close();

    }

}

         此时已经解决了长度的限制,但是如果输入中文发现是不可能正常完成的。






2、BufferedReader

如果要想进行中文的处理肯定使用字符流操作是最方便的,那么在输入数据的时候不能按照字节输入,应该将所有输入的内容保存在一个缓冲区之中,而后一次性的从该缓冲区里面读取数据,这样才能更好的避免掉中文输入问题,所以就必须使用BufferedReader类来实现键盘输入。那么首先来观察一下此类的继承结构。

java.lang.Object

         java.io.Reader

                   java.io.BufferedReader

         此类的构造方法:public BufferedReader(Reader in);

         在此类之中还定义了一个读取一行数据的方法:public String readLine() throws IOException,此方法返回的是String型数据,那么就意味着可以向任意的数据类型转换,可以使用正则进行验证。

范例:实现键盘输入

package cn.mldn.demo;

import java.io.BufferedReader;

import java.io.InputStreamReader;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        // System.in是InputStream类对象,而BufferedReader需要接收的是Reader类对象;

        // InputStreamReader是Reader的子类,此类构造可以接收InputStream类对象

        BufferedReader buf = new BufferedReader(

                new InputStreamReader(System.in));

        System.out.print("请输入数据:");

        String msg = buf.readLine() ;   // 读取数据

        System.out.println(msg);

        buf.close() ;

    }

}

         以上的代码就形成了一个键盘输入数据的操作,可以感觉到实在是很麻烦。

范例:现在由键盘输入一个生日数据

package cn.mldn.demo;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.text.SimpleDateFormat;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        // System.in是InputStream类对象,而BufferedReader需要接收的是Reader类对象;

        // InputStreamReader是Reader的子类,此类构造可以接收InputStream类对象

        BufferedReader buf = new BufferedReader(

                new InputStreamReader(System.in));

        System.out.print("请输入生日(yyyy-mm-dd):");

        String msg = buf.readLine() ;   // 读取数据

        if (msg.matches("\\d{4}-\\d{2}-\\d{2}")) {

            System.out.println(new SimpleDateFormat("yyyy-MM-dd")

                    .parse(msg));

        } else {

            System.out.println("输入错误!");

        }

        buf.close() ;

    }

}

         如果键盘接收的数据返回的是String一定要使用。

 

 





3、Scanner

在JDK 1.5之后增加了一个新的类:java.util.Scanner类,此类专门负责处理输入数据的操作,此类的处理要比BufferedReader更加简单,那么在这个类之中主要关心如下几个方法:

                   · 构造方法:public Scanner(InputStream source);

                   · 设置读取分割符:public Scanner useDelimiter(String pattern);

                   · 判断是否有数据:public boolean hasNextXxx();

                   · 取数据:public 数据 nextXxx()。

范例:利用Scanner实现键盘输入

package cn.mldn.demo;

import java.util.Scanner;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        Scanner scan = new Scanner(System.in) ;

        scan.useDelimiter("\n") ;

        System.out.print("请输入信息:");

        if (scan.hasNext()) {   // 有数据

            String data = scan.next() ;

            System.out.println(data);

        }

        scan.close() ;

    }

}

范例:输入整型数据,直接提供有数据判断

package cn.mldn.demo;

import java.util.Scanner;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        Scanner scan = new Scanner(System.in) ;

        System.out.print("请输入年龄:");

        if (scan.hasNextInt()) {    // 输入的是int型数据

            System.out.println(scan.next());

        } else {

            System.out.println("输入的数据有错误!");

        }

        scan.close() ;

    }

}

范例:输入日期,只能够自己编写正则验证,自己转型

package cn.mldn.demo;

import java.text.SimpleDateFormat;

import java.util.Scanner;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        Scanner scan = new Scanner(System.in) ;

        System.out.print("请输入生日:");

        if (scan.hasNext("\\d{4}-\\d{2}-\\d{2}")) { // 输入的是int型数据

            System.out.println(new SimpleDateFormat("yyyy-mm-dd").parse(scan

                    .next()));

        } else {

            System.out.println("输入的数据有错误!");

        }

        scan.close() ;

    }

}

         以上的操作除了中间的判断和接收数据有用之外,其它的代码意义不大,那么下面使用Scanner实现一个文件数据的读取操作。

范例:读取文件

package cn.mldn.demo;

import java.io.File;

import java.io.FileInputStream;

import java.util.Scanner;

public class TestDemo {

    public static void main(String[] args) throws Exception {

        Scanner scan = new Scanner(new FileInputStream(new File("D:"

                + File.separator + "my.txt")));

        scan.useDelimiter("\n") ;

        while (scan.hasNext()) {

            System.out.println(scan.next());

        }

        scan.close() ;

    }

}

结论:第八个代码模型

         · 如果由程序输出内容那么使用打印流(PrintStream或PrintWriter);

         · 如果程序输入数据使用Scanner(如果有时候Scanner不好使的时候使用BufferedReader)。

 

 





4、对象序列化

对象序列化指的是将保存在内存中的对象转化为二进制数据的形式,这样就可以将对象保存在文件之中或者是进行网络传输。但是如果要想实现对象序列化的操作,有一个要求:对象所在的类一定要实现java.io.Serializable接口,此接口没有任何的方法,所以是一个标识接口。

范例:定义可以被序列化的对象

@SuppressWarnings("serial")

class Person implements Serializable // 此类对象可以被序列化

}

         如果在开发之中,用户只关心这个接口的实现,而具体如何实现序列化和反序列化可以暂时不理会,那么下面将通过代码演示序列化和反序列化的操作。

         这两个操作要分别使用两个类完成:ObjectOutputStream、ObjectInputStream,来观察这两个类的继承结构和构造方法

对象序列化:ObjectOutputStream

对象反序列化:ObjectInputStream

java.lang.Object

         java.io.OutputStream

                   java.io.ObjectOutputStream

java.lang.Object

         java.io.InputStream

                   java.io.ObjectInputStream

public ObjectOutputStream(OutputStream out)

throws IOException

public ObjectInputStream(InputStream in) throws IOException

public final void writeObject(Object obj) throws IOException

public final Object readObject()

throws IOException, ClassNotFoundException

范例:对象序列化

@SuppressWarnings("serial")

class Person implements Serializable { // 此类对象可以被序列化

    private String name;

    private int age;

    public Person(String name, int age) {

        this.name = name;

        this.age = age;

    }

    @Override

    public String toString() {

        return "姓名:" + this.name + ",年龄:" + this.age;

    }

}

public class TestDemo {

    public static void main(String[] args) throws Exception {

        File file = new File("D:" + File.separator + "person.ser");

        ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(file)) ;

        output.writeObject(new Person("张三",20));

        output.close();

    }

}

范例:读取对象 —— 反序列化

public class TestDemo {

    public static void main(String[] args) throws Exception {

        File file = new File("D:" + File.separator + "person.ser");

        ObjectInputStream input = new ObjectInputStream(new FileInputStream(file)) ;

        System.out.println(input.readObject());

        input.close();

    }

}

         但是在默认情况下,一个对象之中的所有属性都被序列化了,如果现在希望某些属性不被序列化,则在属性声明时可以加上transient关键字。

    private transient String name;

         而你们需要放心的时候,对于序列化和反序列化日后会有机制帮助用户自动完成。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值