JAVA 的输入输出

2019-02-21  本文已影响0人  旦暮何枯

处理输入输出的方式称为流。

Stream(流)的特性是一维的,单方向的。

流的基础类

InputStream
OutputStream

标准输入/出流

字节层面的流传输。

System.out.println("Text")

System.in

Scanner in = new Scanner(System.in);

文件流

字节层面的流传输
FileOutputStream
FileInputStream

FileOutputStream 示例:

public class File_Stream {
    public static void main(String[] args) {
        System.out.println("hello world");
        byte[] buf = new byte[10];
        for (int i=0; i<buf.length;i++){
            buf[i] = (byte)i;
        }
        try {
            FileOutputStream out = new FileOutputStream("a.dat");
            out.write(buf);
            out.close();
        }
        catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

流过滤器

以介质流对象为基础层构建过滤器流,最终形成的流对象能在数据的输入输出过程中,逐层使用过滤器流的方法来读写数据。

DataInput(Output)Stream 类可以进行基本数据类型的传输。

(字节流)fileInpitStream | bufferedInputStream | DataInputStream | 基本数据类型

下文代码就增加了 buffer 和 data 两个流过滤器。
因为流过滤器需要在文件流的基础上进行再次封装,所以引用文件流程的代码进行修改:

try {
            DataOutputStream out = new DataOutputStream(
                    new BufferedOutputStream(
                    new FileOutputStream("b.dat")));
//            FileOutputStream out = new FileOutputStream("a.dat");
//            out.write(buf);
            int i = 0xcafebabe;
            out.writeInt(i);
            out.close();
        }

需要注意的是 DataOutputStream 是将存储在内存中的数据,保存到文件中;并没有转换成自然语言,所以读取也需要通过相应的方式进行 DataInputStream的 封装;

try {
            DataOutputStream out = new DataOutputStream(
                    new BufferedOutputStream(
                    new FileOutputStream("b.dat")));
//            FileOutputStream out = new FileOutputStream("a.dat");
//            out.write(buf);
            int i = 0xcafebabe;
            out.writeInt(i);
            out.close();
            
            DataInputStream in = new DataInputStream(
                    new BufferedInputStream(
                            new FileInputStream("b.dat")));
            int j = in.readInt();
            System.out.println(j);
        }

文本流

Reader/Writer

reader/Writer 本身是处理 Unicode 字符的。但在使用场景上,因为有多种文本编码格式,所以需要借助流来打开文件,用流过滤器来建立 Reader/Writer 来进行输入和输出。

//            Reader/Writer
            PrintWriter out_p = new PrintWriter(
                    new BufferedWriter(
//                            OutputStreamWriter 构建了 Stream 和 Writer 之间的桥梁
                            new OutputStreamWriter(
                                    new FileOutputStream("a.txt"))));
            int k = 123456;
//            文本流中的 print 表示打印到文件中?
            out_p.print(k);
            out_p.close();
//            读文件
            BufferedReader in_r = new BufferedReader(
                    new InputStreamReader(
                            new FileInputStream("src/../a.txt")));
            String line;
            while ((line=in_r.readLine()) != null){
                System.out.println(line);
            }

常用 BufferedReader 来读文件, readLine()来获取内容。
LineNumberReader 读文件可以得到行号, getLineNumber()。

FileReader

格式化输入输出

输出

PrintWriter

输入

Scnner

image.png

流的应用

使用 sicket 活的流数据。
本地调式需在 mac 本地输入命令 nc -l 12345

public class SocketStream {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket(InetAddress.getByName("localhost"),12345);
            PrintWriter out = new PrintWriter(
                    new BufferedWriter(
                            new OutputStreamWriter(
                                    socket.getOutputStream())));
            out.println("Hello");
//            若不刷新缓存,服务端不会显示 hello
            out.flush();
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(
                            socket.getInputStream()));

            String line;
            while ((line=reader.readLine())!=null) {
                System.out.println(line);
            }
            out.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

对象串行化

对象通过写出描述自己状态的数值来记录自己 ,这个过程叫对象的串行化(Serialization) 。串行化的主要任务是写出对象实例变量的数值。如果变量是另一对象的引用,则引用的对象也要串行化。这个过程是递归的,串行化可能要涉及一个复杂树结构的单行化,包括原有对象、对象的对象、对象的对象的对象等等。对象所有权的层次结构称为图表(graph)。

自己写的类对象写到文件里。

class Student implements Serializable {
    private String name;
    private int age;
    private int grade;

    public Student(String name, int age, int grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", grade=" + grade +
                '}';
    }
}
public class ObjectStream {
    public static void main(String[] args) {
        try {
            Student s1 = new Student("John",18,8);
            System.out.println(s1);
//            obj stream 写到文件
            ObjectOutputStream out = new ObjectOutputStream(
                    new FileOutputStream("obj.dat"));
            out.writeObject(s1);
            out.close();
//          obj stream 读
            ObjectInputStream in = new ObjectInputStream(
                    new FileInputStream("src/../obj.dat"));
            Student s2 = (Student) in.readObject();
            System.out.println(s2);
            in.close();
            System.out.println(s1==s2);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

读回来的虽然内容一致,但对象新造的不同对象。

上一篇下一篇

猜你喜欢

热点阅读