23.其他操作流
Posted faded8679
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23.其他操作流相关的知识,希望对你有一定的参考价值。
2.转换流
2.1字符流中和编码解码问题相关的两个类【理解】
-
InputStreamReader:是从字节流到字符流的桥梁,父类是Reader
它读取字节,并使用指定的编码将其解码为字符
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
-
OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer
是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
2.2转换流读写数据【应用】
-
构造方法
-
说明 InputStreamReader(InputStream in) 使用默认字符编码创建InputStreamReader对象 InputStreamReader(InputStream in,String chatset) 使用指定的字符编码创建InputStreamReader对象 OutputStreamWriter(OutputStream out) 使用默认字符编码创建OutputStreamWriter对象 OutputStreamWriter(OutputStream out,String charset) 使用指定的字符编码创建OutputStreamWriter对象 -
小结:
转换流就是来进行字节流和字符流之间转换的
InputStreamReader是从字节流到字符流的桥梁
OutputStreamWriter是从字符流到字节流的桥梁
转换流的使用场景
在JDK11之前,指定编码读写
package com.itheima.convertedio; import java.io.*; import java.nio.charset.Charset; public class ConvertedDemo1 { public static void main(String[] args) throws IOException { //method1(); //method2(); //在JDK11之后,新推出了一个构造,也可以指定编码表 FileReader fr=new FileReader("C:\\Users\\12270\\Desktop\\a.txt", Charset.forName("utf-8")); int ch; while ((ch=fr.read())!=-1){ System.out.println((char) ch); } fr.close(); } public static void method2() throws IOException { //如何解决乱码现象 //文件是什么码表,那么咱们就必须使用什么码表去读取 //我们就要指定使用GBK码表去读取文件 InputStreamReader isr=new InputStreamReader(new FileInputStream("C:\\Users\\12270\\Desktop\\a.txt"),"utf-8"); int ch; while ((ch=isr.read())!=-1){ System.out.println((char) ch); } isr.close(); OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("C:\\Users\\12270\\Desktop\\b.txt"),"utf-8"); osw.write("我爱学习,谁也别打扰我"); osw.close(); } //这个方法直接读取会产生乱码 //因为文件时GBK编码 //而idea默认的是UTF-8编码格式 //所以两者不一致,导致乱码 public static void method1() throws IOException { FileReader fr=new FileReader("C:\\Users\\12270\\Desktop\\a.txt"); int ch; while((ch=fr.read())!=-1){ System.out.println((char)ch); } fr.close(); } }
3.对象操作流
可以把对象以字节的形式写到本地文件,直接打开文件,是读不懂的,需要再次用对象操作流读到内存中。
3.1对象序列化流【应用】
对象操作流分为两类:对象操作输入流和对象操作输出流
对象操作输出流(对象序列化流):就是将对象写道本地文件中,或者在网络中传输对象
对象操作输入流(对象反序列化流):把写到本地文件中的对象读到内存中,或者接收网络中传输的对象
-
对象序列化介绍
-
对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
-
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
-
字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
-
反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
-
-
对象序列化流: ObjectOutputStream
-
将Java对象的原始数据类型和图形写入OutputStream。 可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。 如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象
-
-
构造方法
方法名 说明 ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream -
序列化对象的方法
方法名 说明 void writeObject(Object obj) 将指定的对象写入ObjectOutputStream -
示例代码
User类
package com.itheima.convertedio; import java.io.Serializable; //如果想要这个类的对象能被序列化,那么这个类必须要实现一个接口 //Serializable 接口的意义 //称之为是一个标记性接口,里面没有任何的抽象方法 //只要一个类实现了这个Serializable接口,那么就表示这个类的对象可以被序列化 public class User implements Serializable { private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; } public User() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "username=‘" + username + ‘‘‘ + ", password=‘" + password + ‘‘‘ + ‘}‘; } }
ConvertedDemo3类
package com.itheima.convertedio; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class ConvertedDemo3 { public static void main(String[] args) throws IOException { User user=new User("zhangsan","qwer"); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("a.txt")); oos.writeObject(user); oos.close(); } }
3.2对象反序列化流【应用】
-
对象反序列化流: ObjectInputStream
-
ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
-
-
构造方法
方法名 说明 ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream -
反序列化对象的方法
方法名 说明 Object readObject() 从ObjectInputStream读取一个对象 -
示例代码
package com.itheima.convertedio; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ConvertedDemo4 { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt")); User o = (User)ois.readObject(); System.out.println(o); ois.close(); } }
3.3serialVersionUID&transient【应用】
-
serialVersionUID
-
-
会出问题,会抛出InvalidClassException异常
-
-
如果出问题了,如何解决呢?
-
重新序列化
-
给对象所属的类加一个serialVersionUID
-
private static final long serialVersionUID = 42L;
-
-
-
-
transient
-
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
-
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
-
-
-
示例代码
User类
package com.itheima.convertedio; import java.io.Serializable; //如果想要这个类的对象能被序列化,那么这个类必须要实现一个接口 //Serializable 接口的意义 //称之为是一个标记性接口,里面没有任何的抽象方法 //只要一个类实现了这个Serializable接口,那么就表示这个类的对象可以被序列化 public class User implements Serializable { //serialVersionUID 序列号 //如果我们自己没有定义,那么虚拟机会根据类中的信息自动计算出一个序列号 //问题:如果我们修改了类中的信息,那么虚拟机会再次计算出一个序列号 //第一步:把User对象序列化到本地 ----5824992206458892149 //第二步:修改了javabean类,导致 ---类中序列号4900133124572371851 //第三步:把文件中的对象读到内存,本地中的序列号和类中的序列号不一致了 //解决? //不让虚拟机帮我们自动计算,我们自己手动给出,而且这个值不要变 private static final long serialVersionUID = 1L; private String username; private transient String password; public User(String username, String password) { this.username = username; this.password = password; } public User() { } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "username=‘" + username + ‘‘‘ + ", password=‘" + password + ‘‘‘ + ‘}‘; } }
ConvertedDemo5类
package com.itheima.convertedio; import java.io.*; import java.util.ArrayList; public class ConvertedDemo5 { public static void main(String[] args) throws IOException, ClassNotFoundException { //1.写对象 //2.修改javabean类 //3.读对象 //写对象 ---序列化 //method1(); //读对象 ---反序列化 method2(); } public static void method1() throws IOException { User user=new User("zhangsan","qwer"); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("a.txt")); oos.writeObject(user); oos.close(); } public static void method2() throws IOException, ClassNotFoundException { ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt")); User o = (User)ois.readObject(); System.out.println(o); ois.close(); } }
3.4对象操作流练习【应用】
-
创建多个学生类对象写到文件中,再次读取到内存中
-
实现步骤
-
创建序列化流对象
-
创建多个学生对象
-
将学生对象添加到集合中
-
将集合对象序列化到文件中
-
创建反序列化流对象
-
将文件中的对象数据,读取到内存中
-
-
代码实现
学生类
package com.itheima.convertedio; import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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 + ‘}‘; } }
while循环遍历读出数据
package com.itheima.convertedio; import java.io.*; public class ConvertedDemo6 { public static void main(String[] args) throws IOException, ClassNotFoundException { Student s1=new Student("杜子腾",16); Student s2=new Student("张三",23); Student s3=new Student("李四",24); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("a.txt")); oos.writeObject(s1); oos.writeObject(s2); oos.writeObject(s3); oos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt")); Object obj; while(true){ try { Object o = ois.readObject(); System.out.println(o); } catch (EOFException e) { break; } } ois.close(); } }
用集合存储数据,读出集合然后再遍历输出
package com.itheima.convertedio; import java.io.*; import java.util.ArrayList; public class ConvertedDemo7 { public static void main(String[] args) throws IOException, ClassNotFoundException { Student s1=new Student("杜子腾",16); Student s2=new Student("张三",23); Student s3=new Student("李四",24); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("a.txt")); ArrayList<Student> list=new ArrayList<>(); list.add(s1); list.add(s2); list.add(s3); oos.writeObject(list); oos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt")); ArrayList<Student> list2 = (ArrayList<Student>)ois.readObject(); for (Student student : list2) { System.out.println(student); } ois.close(); } }
4.Properties集合
4.1Properties作为Map集合的使用【应用】
-
Properties介绍
-
是一个Map体系的集合类
- Properties中有跟IO相关的方法
-
Properties可以保存到流中或从流中加载
-
键值对的数据类型基本都定义为字符串
-
-
Properties作为Map集合的使用
-
package com.itheima.propertiesio; import java.util.Map; import java.util.Properties; import java.util.Set; public class PropertiesDemo1 { public static void main(String[] args) { Properties prop=new Properties(); //增 prop.put("小龙女","尹志平"); prop.put("郭襄","杨过"); prop.put("黄蓉","欧阳克"); System.out.println(prop); //删 // prop.remove("郭襄"); //System.out.println(prop); //改 //put ---如果键不存在,那么就添加,如果键存在,那么久修改 prop.put("小龙女","杨过"); System.out.println(prop); //查 Object o = prop.get("黄蓉"); System.out.println(o); //遍历 Set<Object> keys = prop.keySet(); for (Object key : keys) { Object value = prop.get(key); System.out.println(key+"="+value); } System.out.println("===================="); //装的是所有的键值对对象 Set<Map.Entry<Object, Object>> entries = prop.entrySet(); for (Map.Entry<Object, Object> entry : entries) { Object key = entry.getKey(); Object value = entry.getValue(); System.out.println(key+"="+value); } } }
4.2Properties作为Map集合的特有方法【应用】
-
特有方法
方法名 说明 Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put String getProperty(String key) 使用此属性列表中指定的键搜索属性 Set<String> stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 -
示例代码
package com.itheima.propertiesio; import java.util.Properties; import java.util.Set; public class PropertiesDemo2 { public static void main(String[] args) { //Object setProperty(String key, String value) --put // 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put Properties prop=new Properties(); prop.setProperty("江苏","南京"); prop.setProperty("安徽","南京"); prop.setProperty("山东","济南"); System.out.println(prop); //String getProperty(String key) --get // 使用此属性列表中指定的键搜索属性 // String vlaue = prop.getProperty("江苏"); // System.out.println(vlaue); //Set<String> stringPropertyNames() --keyset // 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串 Set<String> keys = prop.stringPropertyNames(); for (String key : keys) { String value = prop.getProperty(key); System.out.println(key+"="+value); } } }
4.3Properties和IO流相结合的方法【应用】
-
和IO流结合的方法
方法名 说明 void load(Reader reader) 从输入字符流读取属性列表(键和元素对) void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流 -
示例代码
package com.itheima.propertiesio; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Properties; public class PropertiesDemo3 { public static void main(String[] args) throws IOException { //void load(Reader reader)从输入字符流读取属性列表(键和元素对) // void store(Writer writer, String comments) // 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流 //读取 Properties prop=new Properties(); FileReader fr=new FileReader("prop.properties"); //调用完了load方法之后,文件中的键值对数据已经在集合中了 prop.load(fr); fr.close(); System.out.println(prop); } }
store保存数据
package com.itheima.propertiesio; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; public class PropertiesDemo4 { public static void main(String[] args) throws IOException { //void load(Reader reader)从输入字符流读取属性列表(键和元素对) // void store(Writer writer, String comments) // 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流 Properties prop=new Properties(); prop.put("zhangsan","123"); prop.put("lisi","456"); prop.put("wangwu","789"); FileWriter fw=new FileWriter("prop.properties"); prop.store(fw,null); fw.close(); } }
4.4Properties集合练习【应用】
-
案例需求
在Properties文件中手动写上姓名和年龄,读取到集合中,将该数据封装成学生对象,写到本地文件
-
实现步骤
-
创建Properties集合,将本地文件中的数据加载到集合中
-
获取集合中的键值对数据,封装到学生对象中
-
创建序列化流对象,将学生对象序列化到本地文件中
-
-
代码实现
学生类
package com.itheima.test; import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = 1L; 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; } @Override public String toString() { return "Student{" + "name=‘" + name + ‘‘‘ + ", age=" + age + ‘}‘; } }
Test类
package com.itheima.test; import java.io.*; import java.util.Properties; public class Test { public static void main(String[] args) throws IOException { //创建Properties集合,将本地文件加载到集合中 Properties prop=new Properties(); FileReader fr=new FileReader("prop.properties"); prop.load(fr); fr.close(); //获取集合中的键值数据,风转到学生对象中 String name = prop.getProperty("name"); int age = Integer.parseInt(prop.getProperty("age")); Student s=new Student(name,age); //创建序列化流对象,将学生对象序列化到本地文件中 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("b.txt")); oos.writeObject(s); oos.close(); } }
以上是关于23.其他操作流的主要内容,如果未能解决你的问题,请参考以下文章
java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段
onActivityResult 未在 Android API 23 的片段上调用