Java——Contents3 (special operation flow, Object, Properties)

special operation flow

standard input and output stream

There are two static member variables in the System class:

  • public static final InputStream in: standard input stream. Usually this stream corresponds to keyboard input or another input source specified by the host environment or the user
  • public static final PrintStream out: Standard output stream. Usually this stream corresponds to display output or the host environment or another output destination specified by the user

Realize keyboard input data by yourself:

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

It is too troublesome to write, Java provides a class to realize keyboard entry

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

Usage of the standard input stream:

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

/*
public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
*/
public class SystemInDemo {
    
    
	public static void main(String[] args) throws IOException {
    
    
		//public static final InputStream in:标准输入流
		//		InputStream is = System.in;

		//		int by;
		//		while((by=is.read())!=-1) {
    
    
		//			System.out.print((char)by);
		//		}
		/*
		a
		a
		b
		b
		中
		??
		 */

		//如何把字节流转换为字符流?用转换流
		//		InputStreamReader isr=;
		//使用字符流能不能够实现一次读取一行数据呢?可以
		//但是,一次读取一行数据的方法时字符缓冲输入流的特有方法
		//		BufferedReader br=new BufferedReader(isr);

		//用一步来实现
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		System.out.println("请输入一个字符串");
		String line = br.readLine();
		System.out.println("你输入的字符串是:" + line);

		System.out.println("请输入一个整数:");
		int i = Integer.parseInt(br.readLine()); //要得到什么类型的字符串,就要用它对应的包装类的方法转换
		System.out.println("你输入的整数是:" + i);

		//自己实现键盘录入数据太麻烦了,所以Java就提供了一个类供我们使用
//		Scanner sc = new Scanner(System.in);

	}
}

operation result:
insert image description here

The essence of the output statement: it is a standard output stream

  • PrintStream ps=System.out;
  • The methods of the PrintStream class can be used by System.out

Usage of the standard output stream:


import java.io.PrintStream;

/*
public static final PrintStream out:标准输出流。通常该流对应于显示输出或主机环境或用户指定的另一个输出目标
*/
public class SystemOutDemo {
    
    
	public static void main(String[] args) {
    
    
		// public static final PrintStream out:标准输出流
		PrintStream ps = System.out;

		// 能够方便地打印各种数据值
//		ps.print("hello");
//		ps.print(100);

//		ps.println("hello");
//		ps.println(100);

		// System.out的本质是一个字节输出流
		System.out.println("hello");
		System.out.println(100);

		System.out.println();
//		System.out.print();//报错

	}
}

operation result:
insert image description here

print stream

Print stream classification:

  • Byte print stream: PrintStream
  • Character printing stream: PrintWriter

Print Stream Features:

  • Only responsible for outputting data, not for reading data
  • has its own unique method

byte print stream

  • PrintStream(String fileName): Creates a new print stream with the specified filename
  • Use the method of inheriting the parent class to write data, and it will be transcoded when viewing; use your own unique method to write data, and the viewed data will be output as it is

Byte print stream usage:


import java.io.IOException;
import java.io.PrintStream;

/*
打印流特点:
	只负责输出数据,不负责读取数据
	有自己的特有方法

字节打印流
	PrintStream(String fileName):使用指定的文件名创建新的打印流
*/

public class PrintStreamDemo {
    
    
	public static void main(String[] args) throws IOException {
    
    
		// PrintStream(String fileName):使用指定的文件名创建新的打印流
		PrintStream ps = new PrintStream("..\\hello java\\ps.txt");

		// 写数据
		// 字节输出流有的方法
//		ps.write(97);//a

		// 使用特有方法
//		ps.print(97);//97
//		ps.println();//换行
//		ps.print(98);//98

		ps.println(97);
		ps.println(98);

		// 释放资源
		ps.close();
	}
}

Running result:
insert image description here
The construction method of the character printing stream PrintWriter:

method name illustrate
PrintWriter (String fileName) Creates a new PrintWriter with the specified filename without automatically performing a refresh
PrintWriter(Writer out,boolean autoFlush) Create a new PrintWriter 1.out: character output stream 2.antoFlush: A Boolean value, if true, the println, printf, or format method will flush the output buffer

Character print stream usage:

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

/*
字符打印流PrintWriter的构造方法:

PrintWriter (String fileName)使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新

PrintWriter(Writer out,boolean autoFlush)创建一个新的PrintWriter 
		1.out:字符输出流 
		2.antoFlush:一个布尔值,如果为真,则println,printf,或format方法将刷新输出缓冲区
*/
public class PrintWriterDemo {
    
    
	public static void main(String[] args) throws IOException {
    
    
		// PrintWriter (String fileName)使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新
//		PrintWriter pw=new PrintWriter("..\\hello java\\pw.txt");

//		pw.write("hello");
//		pw.write("\r\n");//加换行符
//		pw.flush();//字符流,需要刷新,否则不出来
//		
//		pw.write("world");
//		pw.write("\r\n");
//		pw.flush();

//		pw.println("hello");
		/*相当于:
			pw.write("hello");
			pw.write("\r\n");
		*/
//		pw.flush();//还是需要刷新,比较麻烦
//		pw.println("world");
//		pw.flush();

		// PrintWriter(Writer out,boolean autoFlush)创建一个新的PrintWriter
		PrintWriter pw = new PrintWriter(new FileWriter("..\\hello java\\pw.txt"), true);// 实现自动刷新
//		PrintWriter pw=new PrintWriter(new FileWriter("..\\hello java\\pw.txt"),false);

		pw.println("hello");
		/*相当于:
			pw.write("hello");
			pw.write("\r\n");
			pw.flush();
		 */
		pw.println("world");

		pw.close();

	}
}

operation result:
insert image description here

Case: Copying Java files (improved version of print stream)

Requirement: Copy PrintStreamDemo.java in the module directory to Copy.java in the module directory

Ideas:

  1. Create a character input stream object from a data source
  2. Create a character output stream object according to the destination
  3. Read and write data, complex-valued files
  4. release resources

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

/*
案例:复制Java文件(打印流改进版)

需求:把模块目录下的PrintStreamDemo.java复制到模块目录下的Copy.java

思路:
	 1. 根据数据源创建字符输入流对象
	 2. 根据目的地创建字符输出流对象
	 3. 读写数据,复值文件
	 4. 释放资源
*/
public class CopyJavaDemo {
    
    
	public static void main(String[] args) throws IOException {
    
    
		/*//1. 根据数据源创建字符输入流对象
		BufferedReader br=new BufferedReader(new FileReader("..\\hello java\\PrintStreamDemo.java"));
		//2. 根据目的地创建字符输出流对象
		BufferedWriter bw=new BufferedWriter(new FileWriter("..\\hello java\\Copy.java"));
		//3. 读写数据,复值文件
		String line;
		while((line=br.readLine())!=null) {
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		//4. 释放资源
		br.close();
		bw.close();*/

		// 1. 根据数据源创建字符输入流对象
		BufferedReader br = new BufferedReader(new FileReader("..\\hello java\\PrintStreamDemo.java"));
		// 2. 根据目的地创建字符输出流对象
		PrintWriter pw = new PrintWriter(new FileWriter("..\\hello java\\Copy.java"), true);

		String line;
		while ((line = br.readLine()) != null) {
    
    
			pw.println(line);
		}
		// 4. 释放资源
		br.close();
		pw.close();

	}
}

Running result:
insert image description here
insert image description here
object serialization stream

Object serialization: It is to save the object to the disk, or to transmit the object in the network.
This mechanism is to use a sequence of bytes to represent an object, which contains: the type of the object, the data of the object and the attributes stored in the object. Waiting for information
After the byte sequence is written to the file, it is equivalent to persistently saving the information of an object in the file.
Conversely, the byte sequence can also be read back from the file to reconstruct the object and deserialize it

To implement serialization and deserialization, use object serialization stream and object deserialization stream:

  • Object serialization stream: ObjectOutputStream
  • Object deserialization stream: ObjectInputStream

object serialization stream

Object serialization stream: ObjectOutputStream

  • Write primitive data types and graphics of Java objects to an OutputStream. Objects can be read (reconstructed) using ObjectInputStream. Persistent storage of objects can be achieved through files using streams. If the stream is a network socket stream, the object can be reconstructed on another host or in another process

Construction method:

  • ObjectOutputStream(OutputStream out): Creates an ObjectOutputStream written to the specified OutputStream

Methods for serializing objects:

  • void writeObject(Object obj): write the specified object to ObjectOutputStream

Notice:

  • For an object to be serialized, the class to which the object belongs must implement the Serializable interface
  • Serializable is a marker interface that implements this class interface without rewriting any methods

Usage of object serialization:

import java.io.Serializable;

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

	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}

	public int getAge() {
    
    
		return age;
	}

	public void setAge(int age) {
    
    
		this.age = age;
	}

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

	public Student() {
    
    
		super();
	}

}

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

/*
对象序列化流
构造方法:

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

序列化对象的方法:

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

	NotSerializableException:抛出一个实例需要一个Serializable接口。序列化运行时或实例的类可能会抛出此异常
	类的序列化由实现java.io.Serializable接口的类启用。不实现此接口的类将不会使用任何状态序列化或反序列化
	
*/
public class ObjectOutputStreamDemo {
    
    
	public static void main(String[] args) throws IOException {
    
    
		// ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("..\\hello java\\oos.txt"));

		// 创建对象
		Student s = new Student("小白", 12);

		// void writeObject(Object obj):将指定的对象写入ObjectOutputStream
		oos.writeObject(s);

		oos.close();
	}
}

Running result:
insert image description here
object deserialization stream: ObjectInputStream

  • ObjectInputStream deserializes raw data and objects previously written using ObjectOutputStream

Construction method:

  • ObjectInputStream(InputStream in): Creates an ObjectInputStream that reads from the specified InputStream

The method to deserialize the object:

  • Object readObject(): read an object from ObjectInputStream

Usage of object deserialization:

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

/*
对象反序列化流:ObjectInputStream

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

构造方法:

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

反序列化对象的方法:

- Object readObject():从ObjectInputStream读取一个对象
*/
public class ObjectInputStreamDemo {
    
    
	public static void main(String[] args) throws IOException, ClassNotFoundException {
    
    
		// ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("..\\hello java\\oos.txt"));

		// Object readObject():从ObjectInputStream读取一个对象
		Object obj = ois.readObject();// 抛出异常

		Student s = (Student) obj;// 向下转型
		System.out.println(s.getName() + "," + s.getAge());// 小白,12

		ois.close();
	}
}

Running Results:
insert image description here
Three Questions

After serializing an object with the object serialization stream, if we modify the class file to which the object belongs, will there be any problems reading the data?

  • There will be problems, and an InvalidClassException will be thrown

If something goes wrong, how to solve it?

  • Add a seriaLVersionUID
    to the class to which the object belongs private static final long seriaLVersionUID=42L;

If the value of a member variable in an object does not want to be serialized, how to achieve it?

  • Add the transient keyword to the member variable, and the member variable marked by this keyword does not participate in the serialization process
import java.io.Serializable;

public class Student implements Serializable {
    
    
	private static final long serialVersionUID = 42L;
	private String name;
//	private int age;
	private transient int age;// 被transient关键字修饰的成员变量,不参与序列化过程

	public String getName() {
    
    
		return name;
	}

	public void setName(String name) {
    
    
		this.name = name;
	}

	public int getAge() {
    
    
		return age;
	}

	public void setAge(int age) {
    
    
		this.age = age;
	}

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

	public Student() {
    
    
		super();
	}

	// 修改了类文件
	@Override
	public String toString() {
    
    
		return "Student [name=" + name + ", age=" + age + "]";
	}

}

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

/*
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
	java.io.InvalidClassException: 
		当序列化运行时检测到类中的以下问题之一时抛出。
			类的串行版本与从流中读取的类描述符的类型不匹配
			该类包含未知的数据类型
			该类没有课访问的无参数构造函数
			
	Contents2.Student; local class incompatible: 
	stream classdesc serialVersionUID = -7792934128464322290,
	local class serialVersionUID = -394614500484104815
	序列化版本号不同
	
如果出问题了,如何解决呢?
	给对象所属的类加一个值:private static final long seriaLVersionUID=42L;

如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
	private transient int age;

*/

public class ObjectStreamDemo {
    
    
	public static void main(String[] args) throws IOException, ClassNotFoundException {
    
    
//		write();
		read();

	}

	// 反序列化
	private static void read() throws IOException, ClassNotFoundException {
    
    
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("..\\hello java\\oos.txt"));
		Object obj = ois.readObject();
		Student s = (Student) obj;
		System.out.println(s.getName() + "," + s.getAge());
		ois.close();

	}

	// 序列化
	private static void write() throws IOException {
    
    
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("..\\hello java\\oos.txt"));
		Student s = new Student("小白", 12);
		oos.writeObject(s);
		oos.close();

	}

}

Properties

Properties overview:

  • It is a collection class of Map system
  • Properties can be saved to or loaded from streams

Exercise: Use of Properties as a Map collection

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

/*
Properties概述:

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

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

*/
public class PorpertiesDemo {
    
    
	public static void main(String[] args) {
    
    
		// 创建集合对象
//		Properties<String,String> prop=new Properties<String,String>();//错误写法
		Properties prop = new Properties();

		// 存储元素
		prop.put("hello1", "小白");
		prop.put("hello2", "小黑");
		prop.put("hello3", "小红");

		// 遍历集合
		Set<Object> keySet = prop.keySet();
		for (Object key : keySet) {
    
    
			Object value = prop.get(key);
			System.out.println(key + "," + value);
		}

	}
}

operation result:
insert image description here

Properties as a collection of unique methods:

method name illustrate
Object setProperty(String key,String value) Set the key and value of the collection, both are of String type, and the bottom layer calls the Hashtable method put
String getProperty(String key) Searches for properties using the keys specified in this property list
Set< String > stringPropertyNames() Returns an unmodifiable set of keys from this property list, where the keys and their corresponding values ​​are strings
import java.util.Properties;
import java.util.Set;

/*
Properties作为集合的特有方法:
	Object setProperty(String key,String value) 
		设置集合的键和值,都是String类型,底层调用Hashtable方法put
		
	String getProperty(String key)
		使用此属性列表中指定的键搜索属性
		
	Set< String > stringPropertyNames()
		从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
*/
public class PorpertiesDemo2 {
    
    
	public static void main(String[] args) {
    
    
		// 创建集合对象
		Properties prop = new Properties();

		// Object setProperty(String key,String value)
		// 设置集合的键和值,都是String类型,底层调用Hashtable方法put
		prop.setProperty("hello1", "小白");
		prop.setProperty("hello2", "小黑");
		prop.setProperty("hello3", "小红");

		// String getProperty(String key)使用此属性列表中指定的键搜索属性
//		System.out.println(prop.getProperty("hello1"));//小白
//		System.out.println(prop.getProperty("hello11"));//null

		// System.out.println(prop);

		// Set< String > stringPropertyNames()从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
		Set<String> names = prop.stringPropertyNames();
		for (String key : names) {
    
    
//			System.out.println(key);
			String value = prop.getProperty(key);
			System.out.println(key + "," + value);
		}

	}
}

operation result:
insert image description here

The method of combining Properties and IO stream:

method name illustrate
void load(InputStream inStream) Reads a property list (key and element pair) from an input byte stream
void Load(Reader reader) Reads a property list (key and element pair) from an input character stream
void store(OutputStream out,String comments) Writes this list of properties (key and element pairs) into this Properties table, in a format suitable for use with the load(InputStream) method to an output byte stream
void store(Writer writer,String comments) Writes this list of properties (key and element pairs) into this Properties table, in a format suitable for use with the load(Reader) method to an output character stream
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

/*
Properties和IO流结合的方法:
	
	void Load(Reader reader)
		从输入字符流读取属性列表(键和元素对)
	
	void store(Writer writer,String comments)
		将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式写入输出字符流 
*/
public class PorpertiesDemo3 {
    
    
	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("..\\hello java\\fw.txt");
		prop.load(fr);
		fr.close();

		System.out.println(prop);

	}

	private static void myStore() throws IOException {
    
    
		Properties prop = new Properties();

		prop.setProperty("hello1", "小白");
		prop.setProperty("hello2", "小黑");
		prop.setProperty("hello3", "小红");

		// void store(Writer writer,String comments)
		FileWriter fw = new FileWriter("..\\hello java\\fw.txt");
		prop.store(fw, null);
		fw.close();

	}

}

operation result:
insert image description here
insert image description here

Case: Number of games

Requirements: Please write a program to realize the number guessing game. You can only try it for 3 times. If you still want to play, prompt: the game trial is over. If you want to play, please recharge (www.baidu.com)

Ideas:

  1. Write a game class with a small game of guessing numbers
  2. Write a test class. There is a main() method in the test class. In the main() method, follow the steps below:
  • Read data from the file to the Properties collection, use the load() method to achieve
    A. The file already exists: game.txt
    B. There is a data value in it: count=0
  • Get the number of times you played the game through the Properties collection
  • Judging whether the number of times has reached 3 times
    A. If it has reached, give a reminder: the game trial is over, please recharge if you want to play (www.baidu.com)
    B. If it is less than 3 times:
    play the game
    times +1, write back File, implemented with the store() method of Properties
    insert image description here
import java.util.Random;
import java.util.Scanner;

// 1. 写一个游戏类,里面有一个猜数字的小游戏

public class GuessNumber {
    
    
	private GuessNumber() {
    
    
	}

	public static void start() {
    
    
		// 生成随机数1到100
		Random r = new Random();
		int number = r.nextInt(100) + 1;

		while (true) {
    
    
			// 键盘输入猜的数字
			Scanner sc = new Scanner(System.in);

			System.out.println("请输入你猜测的数字:");
			int gn = sc.nextInt();

			// 比较录入的数字和系统产生的数据
			if (gn > number) {
    
    
				System.out.println("猜大了!");
			} else if (gn < number) {
    
    
				System.out.println("猜小了!");
			} else {
    
    
				System.out.println("猜对了!");
				break;
			}

		}
	}
}

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

/*
案例:游戏次数

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

思路:
	 1. 写一个游戏类,里面有一个猜数字的小游戏
	 
	 2. 写一个测试类,测试类中有main()方法,main()方法中按照下面步骤完成:
	 	1.从文件中读取数据到Properties集合,用load()方法实现:
			A.件已经存在:game.txt
			B.里面有一个数据值:count=0
			
	 	2.通过Properties集合获取到玩游戏的次数
	 	
	 	3.判断次数是否到3次了:
			A.如果到了,给出提示:游戏试玩已结束,想玩请充值(www.baidu.com)
			B.如果不到3次:
				玩游戏
				次数+1,重新写回文件,用Properties的store()方法实现
*/

public class PropertiesTest {
    
    
	public static void main(String[] args) throws IOException {
    
    
		// 1.从文件中读取数据到Properties集合,用load()方法实现
		Properties prop = new Properties();

		FileReader fr = new FileReader("..\\hello java\\game.txt");
		prop.load(fr);
		fr.close();

		// 2.通过Properties集合获取到玩游戏的次数
		String count = prop.getProperty("count");
		int number = Integer.parseInt(count);// 类型转换

		// 3.判断次数是否到3次了
		if (number >= 3) {
    
    
			// A.如果到了,给出提示:游戏试玩已结束,想玩请充值(www.baidu.com)
			System.out.println("游戏试玩已结束,想玩请充值(www.baidu.com)");
		} else {
    
    
			// 玩游戏
			GuessNumber.start();
			// 次数+1,重新写回文件,用Properties的store()方法实现
			number++;
			prop.setProperty("count", String.valueOf(number));// string中有一个valueOf方法把int类型转为字符串

			FileWriter fw = new FileWriter("..\\hello java\\game.txt");
			prop.store(fw, null);
			fw.close();

		}

	}
}

Running results:
first run:
insert image description here
insert image description here
second run:
insert image description here
insert image description here
third run:
insert image description here
insert image description here
fourth run:
insert image description here

Guess you like

Origin blog.csdn.net/weixin_47678894/article/details/119736142