美文网首页
JAVA 的输入输出

JAVA 的输入输出

作者: 旦暮何枯 | 来源:发表于2019-02-21 16:33 被阅读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

    • InputStreamReader 的子类,所有方法都从父类中继承而来。

    • FileReader(File file)

      • 在给定从中读取数据的 File 的情况下创建一个新 FileReader
    • FileReader(String fileName)

      • 在给定从中读取数据的文件名的情况下创建一个新的 FileReader
    • FileReader 不能指定编码转换方式。

    格式化输入输出

    输出

    PrintWriter

    • format("格式",。。。);
    • printf("格式",。。。);
    • print(各种基本类型);
    • println(各种基本类型);

    输入

    Scnner

    • 在 InputStream 或 Reader 上简历一个 Scanner 对象可以从流中文本解析出以文本表达的各种基本类型
    • next...()
    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();
            }
        }
    }
    
    • 因为 read()函数是阻塞的,在督导所需的内容之前会停下来
      • 使用read() “高级”的函数,入nextInt()、readLine()都是同样的
      • 所以常用单独的线程来做 socket 读的等待,或使用 nio 的channel 选择机制
    • 对于socket,可以设置 SO 时间
      • setSoTimeout(int timeOut)

    对象串行化

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

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

    • ObjectInpuStream 类
      • readObject()
    • ObjectOutputStream 类
      • writeObject()
    • Serializable 接口
    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();
            }
        }
    }
    

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

    相关文章

      网友评论

          本文标题:JAVA 的输入输出

          本文链接:https://www.haomeiwen.com/subject/hdcdyqtx.html