Java基础 | IO流(五)

本文涉及的产品
系统运维管理,不限时长
简介: Java中的IO流讲解

(七)特殊操作流

1.标准输入流

System类中有两个静态的成员变量

  • public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
  • public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标

自己实现键盘录入数据:

  • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

写起来太麻烦,Java就提供了一个类实现键盘录入

  • Scanner sc = new Scanner(System.in);

代码演示:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;

public class SystemInDemo {
    public static void main(String[] args) throws IOException {
        /*
        InputStream is = System.in;

        //如何把字节流转换为字符流?用转换流
        InputStreamReader isr = new InputStreamReader(is);
        //如何使用字符流一次读一行数据
        //需要使用字符缓冲输入流的特有方法
        BufferedReader br = new BufferedReader(isr);
         */

        //简化上述三行代码
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("请输入一个字符串:");
        String ss = br.readLine();
        System.out.println("你输入的字符串是:" + ss);
        System.out.println("请输入一个整数:");
        int i = Integer.parseInt(br.readLine());
        System.out.println("你输入的整数为:" + i);
        //这样想要的数据类型代码太麻烦了,所以Java提供了Scanner类来简化代码
        Scanner sc = new Scanner(System.in);
        int i1 = sc.nextInt();
    }
}

(ps:当我学到这里,我感觉我整个人精神了,当这一节出现System.in时我就在想,这个东西跟InputStream什么的乱七八糟的有什么关系???学完了之后真是眼前焕然一新,Scanner 没错就是它,太牛了,绕来绕去又绕回来了,以前刚开始接触Java使用 Scanner键盘录入的时候压根没想过它到底为什么这么写,就觉得键盘录入固定格式就应该这样,随着学习的深入,很多谜团都解开了,原来万物都有个由来。太想记录此刻的心情了哈哈,这些都是我的笔记,在未来我可能会有写博客的习惯,然后将笔记一点点分享到博客中,期待未来我的粉丝们嘿嘿,继续学习了,加油!)
(泪目了家人们,上面是一年前刚学Java时傻乎乎的自己记录的感受,今天2022.9.5我也是最近开始了自己的博客创作之旅,能看到这里的不论是路人还是粉丝,谢谢你们的支持,我会继续努力,持续将我的全部Java笔记分享到博客中,以供大家学习参考)


2.标准输出流

public static final PrintStream out:标准输出流。通常该流对应于显示输出或由主机环境或用户指定的另一个输出目标

输出语句的本质:是一个标准的输出流

  • PrintStream ps = System.out;
  • PrintStram类有的方法,System.out都可以使用

注意:其中println方法可以没有参数,但是print方法中必须要传参,因为没有无参的print方法

代码演示:

import java.io.PrintStream;

public class SystemOutDemo {
    public static void main(String[] args) {
        PrintStream ps = System.out;
        ps.println("hello");
        ps.println();
        ps.print();//此处报错,因为print方法必须要有参数
        //System.out的本质是一个字节输出流
    }
}

3.打印流

打印流的特点

  • 只负责输出数据,不负责读取数据
  • 有自己的特有方法
(1)字节打印流(PrintStream)
  • PrintStream(String fileName):使用指定的文件名创建新的打印流
  • 使用继承父亲的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出

代码演示:

import java.io.FileNotFoundException;
import java.io.PrintStream;

public class PrintStreamDemo {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("src\\TEMP\\TEMP28\\ps.txt");

        //使用继承父亲的方法
        ps.write(97);//a
        //使用自己特有的方法
        ps.print(97);//97

        ps.println();//换行
        ps.print(98);//98
        ps.println(99);//99
    }
}

(2)字符打印流(PrintWriter)

在这里插入图片描述

代码演示:

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        //PrintWriter(String FileName)
        PrintWriter pw = new PrintWriter("src\\TEMP\\TEMP28\\pw.txt");
        //继承的方法
        pw.write("hello");
        pw.write("\r\n");
        pw.flush();
        pw.write("world");
        pw.write("\r\n");
        pw.flush();

        //特有的方法
        pw.println("hello");
        pw.flush();
        pw.println("world");
        pw.flush();

        //PrintWriter(Writer out,boolean autoFlush)
        PrintWriter pw2 = new PrintWriter(new FileWriter("src\\TEMP\\TEMP28\\pw.txt"),true);
        pw.println("hello");
        pw.println("world");
    }

4.复制Java文件(打印流改进版)

import java.io.*;

public class CopyFileDemo {
    public static void main(String[] args) throws IOException {
        //创建输入流对象
        BufferedReader br = new BufferedReader(new FileReader("src\\TEMP\\TEMP27\\Student.txt"));
        //创建输出流对象
        PrintWriter pw = new PrintWriter(new FileWriter("src\\TEMP\\TEMP28\\copyStudent.txt"),true);
        //读写数据,复制文件
        String line;
        while((line = br.readLine())!=null){
            pw.println(line);
        }
        //释放资源
        br.close();
        pw.close();
    }
}

5.对象序列化流

对象序列化流:就是讲对象保存到磁盘中,或者在网路中传输对象

这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的模型、对象的数据和对象中存储的属性等信息

字节序列写到文件之后,相当于文件中持久保存了一个对象的信息

反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化

要实现序列化和反序列化就要使用对象序列化流和对象反序列化流:

  • 对象序列化流:ObjectOutputStream
  • 对象反序列化流:ObjectInputStream
(1)对象序列化流

对象序列化流:ObjectOutputStream

  • 将Java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取(重构)对象。可以通过使用流的文件来实现对象的持久存储。如果流是网路套接字流,则可以在另一个主机上或另一个进程中重构对象

构造方法:

  • ObjectOutputStream(OutputStream out):创建一个写入指定的OutStream的ObjectOutputStream

序列化对象的方法:

  • void writeObject(Object obj):将指定的对象写入ObjectOutputStream

注意:

  • 一个对象要想被序列化,该对象所属的类必须实现Serializable接口
  • Serializable是一个标记接口,实现该接口,不需要重写任何方法

代码演示:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //ObjectOutputStream(OutputStream out):创建一个写入指定的OutStream的ObjectOutputStream
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\TEMP\\TEMP28\\oos.txt"));
        //创建对象
        Student s = new Student("学生1",20);
        //void writeObject(Object obj):将指定的对象写入ObjectOutputStream
        oos.writeObject(s);
        //释放资源
        oos.close();
    }
}

(2)对象反序列化流

对象反序列化流:ObjectInputStream

  • ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象

构造方法

  • ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream

反序列化对象的方法:

  • Object readObject():从ObjectInputStream读取一个对象

代码演示:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectInputStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\TEMP\\TEMP28\\oos.txt"));
        //读取对象
        Object obj = ois.readObject();
        //向下转型
        Student s = (Student)obj;
        //输出
        System.out.println(s.getName()+", "+s.getAge());
        //释放资源
        ois.close();
    }
}
(3)对象序列化的三个问题

在这里插入图片描述


6.Properties

Properties概述:(Properties继承了Hashtable,Hashtable与HashMap相似)

  • 是一个Map体系的集合类
  • Properties可以保存到流中或从流中加载

练习:Properties作为Map集合的使用

import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {
    public static void main(String[] args) {
        //Properties集合的构造方法中没有泛型<> 所以默认类型都是Object
        Properties prop = new Properties();
        //存储元素
        prop.put("19103200", "学生1");
        prop.put("19103201", "学生2");
        prop.put("19103202", "学生3");
        //遍历集合
        Set<Object> keySet = prop.keySet();
        for (Object key : keySet) {
            Object value = prop.get(key);
            System.out.println(key + ", " + value);
        }
    }
}

Properties集合的特有方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ICutkkd-1662344106255)(https://cdn.jsdelivr.net/gh/BoBooY-GitHub/JavaSE_imgs@main/imgs/202209012120816.png)]

代码演示:

import java.util.Properties;
import java.util.Set;

public class PropertiesDemo2 {
    public static void main(String[] args) {
        Properties prop = new Properties();

        //Object setProperty(String key,String value)
        prop.setProperty("19103200", "学生1");
        prop.setProperty("19103201", "学生2");
        prop.setProperty("19103202", "学生3");

        //Set<String> StringPropertyNames()
        Set<String> names = prop.stringPropertyNames();
        //遍历集合(Properties集合特有的遍历方法)
        for (String key : names) {
            //String getProperty(String key)
            String value = prop.getProperty(key);
            System.out.println(key + ", " + value);
        }
    }
}

7.Properties与IO流结合的方法

在这里插入图片描述

代码演示:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo3 {
    public static void main(String[] args) throws IOException {
        //把集合中的数据保存到文件
        myStore();
        //把文件中的数据加载到集合
        myLoad();
    }

    private static void myLoad() throws IOException{
        Properties prop = new Properties();
        //void Load(Reader reader)
        FileReader fr = new FileReader("src\\TEMP\\TEMP28\\prop3.txt");
        prop.load(fr);
        fr.close();

        System.out.println(prop);//{19103200=学生1, 19103201=学生2, 19103202=学生3}
    }

    private static void myStore() throws IOException {
        Properties prop = new Properties();
        //存入数据
        prop.setProperty("19103200", "学生1");
        prop.setProperty("19103201", "学生2");
        prop.setProperty("19103202", "学生3");
        //void store(Writer writer,String comments)
        FileWriter fw =new FileWriter("src\\TEMP\\TEMP28\\prop3.txt");
        prop.store(fw,null);//第二个参数为对文件的描述,没有描述则可以写null
        fw.close();
    }
}

8.案例(游戏次数)

需求:请写程序实现猜数字小游戏只能试玩3次,如果还想玩,提示:游戏试玩已结束,想玩请充值(www.BoBooY.com)

代码实现:

创建一个游戏类:

import java.util.Random;
import java.util.Scanner;

public class GuessNumber {
    private GuessNumber() {
    }

    public static void start() {
        Random r = new Random();
        int num = r.nextInt(100) + 1;
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个数字:");
        while (true) {
            int UserNum = sc.nextInt();
            if (UserNum > num) {
                System.out.println("您输入的数字大了,请重新输入:");
            } else if (UserNum < num) {
                System.out.println("您输入的数字小了,请重新输入:");
            } else if (UserNum == num) {
                System.out.println("猜对了!");
                break;
            }
        }

    }
}

创建游戏测试类:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo {
    public static void main(String[] args) throws IOException {
        //创建集合对象
        Properties prop = new Properties();

        //读取文件中的数据
        FileReader fr = new FileReader("smallDemo\\src\\PropertiesModel\\game.txt");
        prop.load(fr);
        //释放资源
        fr.close();
        //获取count键对应的值
        String count = prop.getProperty("count");
        //将String类型转为int类型
        int number = Integer.parseInt(count);
        //判断游戏次数
        if (number >= 3) {
            System.out.println("试玩结束,请充值!");
        } else {
            GuessNumber.start();
            //游戏结束,试玩次数记录加1
            number++;
            //将int类型数据重新打包为String类型
            prop.setProperty("count",String.valueOf(number));
            //将数据重新写入文件中记录保存
            FileWriter fw = new FileWriter("smallDemo\\src\\PropertiesModel\\game.txt");
            prop.store(fw,null);
            //释放资源
            fw.close();
        }
    }
}

其中已经存在的文件game.txt

count = 0

目录
相关文章
|
1月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
2月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
14天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
8天前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
24天前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
1月前
|
Java 数据处理
Java IO 接口(Input)究竟隐藏着怎样的神秘用法?快来一探究竟,解锁高效编程新境界!
【8月更文挑战第22天】Java的输入输出(IO)操作至关重要,它支持从多种来源读取数据,如文件、网络等。常用输入流包括`FileInputStream`,适用于按字节读取文件;结合`BufferedInputStream`可提升读取效率。此外,通过`Socket`和相关输入流,还能实现网络数据读取。合理选用这些流能有效支持程序的数据处理需求。
28 2
|
1月前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
|
1月前
|
缓存 Java
【IO面试题 一】、介绍一下Java中的IO流
Java中的IO流是对数据输入输出操作的抽象,分为输入流和输出流,字节流和字符流,节点流和处理流,提供了多种类支持不同数据源和操作,如文件流、数组流、管道流、字符串流、缓冲流、转换流、对象流、打印流、推回输入流和数据流等。
【IO面试题 一】、介绍一下Java中的IO流
|
1月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
37 2
|
1月前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
133 1