标准输入流和标准输出流
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);
package com.io.system;
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 {
//public static final InputStream in: 标准输入流。
// InputStream is = System.in;
// int by;
// while ((by=is.read())!=-1){
// System.out.print((char)by);
// }
//如何把字节流转换为字符流?用转换流
// InputStreamReader isr = new InputStreamReader(is);
//使用字符流一次读取一行数据:字符缓冲输入流的特有方法
// 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);
}
}
输出流
PrintStream ps = System.out;
- System.out的本质是一个字节输出流
- PrintStream类有的方法,System.out都可以使用
package com.io.system;
import java.io.PrintStream;
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();
}
}
打印流
打印流分类:
- 字节打印流:PrintStream
- 字符打印流:PrintWrite
特点:
- 只负责输出数据,不负责写数据
- 有自己的特有方法
字节打印流
- 使用继承父类的方法写数据,查看的时候会转码;使用自己独有数据时,查看的数据原样输出
public PrintStream(String fileName):使用指定的文件名创建新的打印流
package com.io.special.print;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamDemo {
public static void main(String[] args) throws IOException {
//public PrintStream(String fileName):使用指定的文件名创建新的打印流
PrintStream ps = new PrintStream("E:\\study\\JavaSE\\基础语法\\ps.txt");
//写数据
//字节输出流的方法
// ps.write(97);
//使用特有方法写数据
// ps.print(97);
// ps.println();
// ps.print(98);
ps.println(97);
ps.println(98);
//释放资源
ps.close();
}
}
字符打印流
构造方法
public PrintWriter(String fileName):使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新。
public PrintWriter(OutputStream out,boolean autoFlush):从现有的OutputStream创建一个新的PrintWriter。
//out - 输出流
//autoFlush - 一个布尔值 如果为真,则println , printf ,或format方法将刷新输出缓冲区
package com.io.special.print;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriteDemo {
public static void main(String[] args) throws IOException {
//public PrintWriter(String fileName):使用指定的文件名创建一个新的PrintWriter,而不需要自动执行行刷新。
// PrintWriter pw = new PrintWriter("E:\\study\\JavaSE\\基础语法\\pw.txt");
// pw.write("hello");
// pw.write("\r\n");
// pw.flush();
// pw.write("\r\n");
// pw.write("world");
// pw.flush();
// pw.println("hello");
// pw.println("world");
// pw.flush();
//public PrintWriter(OutputStream out,boolean autoFlush):从现有的OutputStream创建一个新的PrintWriter。
//out - 输出流
//autoFlush - 一个布尔值 如果为真,则println , printf ,或format方法将刷新输出缓冲区
// PrintWriter pw = new PrintWriter(new FileWriter("E:\\study\\JavaSE\\基础语法\\pw.txt"),true);
PrintWriter pw = new PrintWriter(new FileWriter("E:\\study\\JavaSE\\基础语法\\pw.txt"),false);
pw.println("hello");
/*
pw.write("hello");
pw.write("\r\n");
pw.flush();
*/
pw.println("world");
pw.close();
}
}
案例
package com.io.special.demo;
import java.io.*;
//需求:复制文件
public class CopyJavaDemo {
public static void main(String[] args) throws IOException {
/*
//1.根据数据源创建字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("E:\\study\\JavaSE\\基础语法\\ps.txt"));
//2.根据目的地创建字符输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\study\\JavaSE\\基础语法\\ps1.txt"));
//3.读写数据,复制文件
String line;
while ((line = br.readLine())!= null){
bw.write(line);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
*/
//1.根据数据源创建字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("E:\\study\\JavaSE\\基础语法\\ps.txt"));
//2.根据目的地创建字符输出流对象
PrintWriter pw = new PrintWriter(new FileWriter("E:\\study\\JavaSE\\基础语法\\ps1.txt"),true);
//3.读写数据,复制文件
String line;
while ((line = br.readLine())!= null){
pw.println(line);
}
br.close();
pw.close();
}
}
对象序列化流
对象序列化流
对象序列化流:ObjectOutputStream
-
ObjectOutputStream将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象。
-
构造方法:
public ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream。
- 序列化对象的方法:
public final void writeObject(Object obj):将指定的对象写入ObjectOutputStream。
- 注意:
- 一个对象想要被序列化,该对象所属的类必须实现Serializable接口
- Serializable是一个标记接口,实现该接口,不需要重写任何方法
package com.io.special.object;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException {
//public ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream。
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("E:\\study\\JavaSE\\基础语法\\oos.txt"));
//创建对象
Student s = new Student("流年",22);
//public final void writeObject(Object obj):将指定的对象写入ObjectOutputStream。
oos.writeObject(s);
//NotSerializableException:抛出一个实例需要一个Serializable接口。 序列化运行时或实例的类可能会抛出此异常
//类的序列化由实现java.io.Serializable接口的类启用。 不实现此接口的类将不会使任何状态序列化或反序列化。
//释放资源
oos.close();
}
}
package com.io.special.object;
import java.io.Serializable;
public class Student implements Serializable {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
}
对象反序列化流
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象。
- 构造方法:
public ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream。
- 反序列化方法:
public final Object readObject():从ObjectInputStream读取一个对象。
package com.io.special.object;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//public ObjectInputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream。
ObjectInputStream ois = new ObjectInputStream(new
FileInputStream("E:\\study\\JavaSE\\基础语法\\oos.txt"));
//public final Object readObject():从ObjectInputStream读取一个对象。
Object obj = ois.readObject();
Student s = (Student) obj;
System.out.println(s.getName() + "," + s.getAge());
ois.close();
}
}
serialVersionUID&transient
1.用对象序列化流序列化一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出现问题?
java.io.InvalidClassException:
当序列化运行时检测到类中的以下问题之一时抛出。
类的串行版本与从流中读取的类描述符的类型不匹配
该类包含未知的数据类型
该类没有可访问的无参数构造函数
com.io.special.object.Student; local class incompatible:
stream classdesc serialVersionUID = 4307522101919733830,
local class serialVersionUID = -3752805270447829666
2.如果出现问题,如何解决呢?
给对象所属的类加一个值:private static final long serialVersionUID = 42L;
3.如果一个对象中的某个成员变量不想被序列化,又该如何实现
给成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
package com.io.special.object;
import java.io.*;
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("E:\\study\\JavaSE\\基础语法\\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("E:\\study\\JavaSE\\基础语法\\oos.txt"));
Student s = new Student("流年",22);
oos.writeObject(s);
oos.close();
}
}
package com.io.special.object;
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;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
Properties
-
是一个Map体系的集合类
-
Properties可以保存到流中或从流中加载
作为Map集合的使用
package com.io.special.properties;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
public static void main(String[] args) {
//创建集合对象
// Properties<String,String> prop = new Properties<String,String>();//错误的
Properties prop = new Properties();
//存储元素
prop.put("xuehao001","流年");
prop.put("xuehao002","冰茶");
prop.put("xuehao003","长岛");
//遍历集合
Set<Object> keySet = prop.keySet();
for (Object key :keySet){
Object value = prop.get(key);
System.out.println(key+","+value);
}
}
}
特有方法
public Object setProperty(String key,String value):调用Hashtable方法put。
public String getProperty(String key):使用此属性列表中指定的键搜索属性。
public Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
package com.io.special.properties;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo002 {
public static void main(String[] args) {
//创建集合对象
Properties prop = new Properties();
//public Object setProperty(String key,String value):调用Hashtable方法put 。
prop.setProperty("xuehao001", "流年001");
prop.setProperty("xuehao002", "流年002");
prop.setProperty("xuehao003", "流年003");
//public String getProperty(String key):使用此属性列表中指定的键搜索属性。
System.out.println(prop.getProperty("xuehao001"));
System.out.println(prop.getProperty("xuehao0011"));
//public 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);
}
System.out.println(prop);
}
}
与IO流相结合
public void store(Writer writer,String comments):将此属性列表(键和元素对)写入此Properties表格中,以适合使用load(Reader)方法的格式将输出字符流写入 。
public void load(Reader reader):以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。
package com.io.special.properties;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo003 {
public static void main(String[] args) throws IOException {
//把集合中的数据保存到文件
myStore();
//把文件数据加载到集合
myLoad();
}
private static void myLoad() throws IOException {
Properties prop = new Properties();
//public void load(Reader reader):以简单的线性格式从输入字符流读取属性列表(关键字和元素对)。
FileReader fr = new FileReader("E:\\study\\JavaSE\\基础语法\\fw.txt");
prop.load(fr);
fr.close();
System.out.println(prop);
}
private static void myStore() throws IOException {
Properties prop = new Properties();
prop.setProperty("xuehao001", "流年001");
prop.setProperty("xuehao002", "流年002");
prop.setProperty("xuehao003", "流年003");
//public void store(Writer writer,String comments):将此属性列表(键和元素对)写入此Properties表格中,以适合使用load(Reader)方法的格式将输出字符流写入 。
FileWriter fw = new FileWriter("E:\\study\\JavaSE\\基础语法\\fw.txt");
prop.store(fw,null);
fw.close();
}
}
案列
package com.io.special.properties;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
/*
需求:写程序实现猜数字小游戏只能实现3次,如果还想玩,给出提示
*/
public class PropertiesTest {
public static void main(String[] args) throws IOException {
//2.从文件中读取数据到Properties集合,用load()方法实现
//game.txt 文件已存在 里面的数据:count = 0
Properties prop = new Properties();
FileReader fr = new FileReader("E:\\study\\JavaSE\\基础语法\\game.txt");
prop.load(fr);
fr.close();
//3.通过Properties集合获取到玩游戏的次数
String count = prop.getProperty("count");
int number = Integer.parseInt(count);
//4.判断是否到达3次
if (number>=3){
//5.给出提示
System.out.println("已玩3次");
}else {
//玩游戏
GuessNumber.start();
//次数加1,重新写回文件,用Properties的start()方法实现
number++;
prop.setProperty("count",String.valueOf(number));
FileWriter fw = new FileWriter("E:\\study\\JavaSE\\基础语法\\game.txt");
prop.store(fw,null);
fw.close();
}
}
}
package com.io.special.properties;
import java.util.Random;
import java.util.Scanner;
//1.写一个游戏类
public class GuessNumber {
private GuessNumber() {
}
public static void start(){
//随机生成要猜的数字
Random random = new Random();
int number = random.nextInt(100);
while (true){
//键盘录入要猜的数字
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要猜的数字:");
int guessNumber = sc.nextInt();
//进行判断
if (guessNumber>number){
System.out.println("你猜的数字"+guessNumber+"大了");
}else if (guessNumber<number){
System.out.println("你猜的数字"+guessNumber+"小了");
}else {
System.out.println("恭喜猜中");
break;
}
}
}
}