【JavaSE学习笔记】IO流06_其他常用流(基本数据类型流、内存操作流、打印流、标准流、随机访问流、合并流、序列化与反序列化流)、属性集合类Properties

来源:互联网 发布:尤克里里和吉他知乎 编辑:程序博客网 时间:2024/05/16 17:18

IO流06

A.其他常用流

1)操作基本数据类型的流Data

1.DataOutputStream:数据输出流

import java.io.DataOutputStream;import java.io.FileOutputStream;public class Demo01 {public static void main(String[] args) throws Exception {// 创建数据输出流DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));// 写数据dos.writeByte(10);dos.flush();dos.writeShort(100);dos.flush();dos.writeInt(1000);dos.flush();dos.writeLong(10000L);dos.flush();dos.writeFloat(12.34F);dos.flush();dos.writeDouble(12.56);dos.flush();dos.writeBoolean(true);dos.flush();dos.writeChar('A');dos.flush();// 释放资源dos.close();}}

最后输出txt里肯定是看不懂的乱码,但只要计算机能看懂就行了

接下来读取到控制台上

2.DataInputStream:数据输入流

import java.io.DataInputStream;import java.io.FileInputStream;public class Demo02 {public static void main(String[] args) throws Exception {// 创建数据输入流对象DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));// 读数据byte b = dis.readByte();short s = dis.readShort();int i = dis.readInt();long l = dis.readLong();float f = dis.readFloat();double d = dis.readDouble();boolean flag = dis.readBoolean();char c = dis.readChar();dis.close();System.out.println(b);System.out.println(s);System.out.println(i);System.out.println(l);System.out.println(f);System.out.println(d);System.out.println(flag);System.out.println(c);}}

2)内存操作流

用来存储内存中的临时信息,程序结束的时候,内存流就消失了!

1.字节数组操作内存流

ByteArrayInputStream

ByteArrayOutputStream

2.字符数组操作的内存流

CharArrayReader

CharArrayWriter

3.字符串操作的内存流

StringReader

StringWritwe

import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;public class Demo01 {public static void main(String[] args) throws IOException {// 创建针对字节数组操作的内存输出流对象ByteArrayOutputStream baos = new ByteArrayOutputStream();// 写一个for循环for (int i = 0; i < 10; i++) {// 写数据baos.write(("hello" + i).getBytes());}// 关闭资源// public void close() throws IOException {}// 通过查看API原码:发现该流的close方法没有任何 的操作,该流可以不用关闭:// 该流本身就是内存流,存储内存中临时信息,当程序结束,跟该流有关的资源也就自动消失了// baos.close();// 字节内存输入流:public ByteArrayInputStream(byte[] buf)// public byte[] toByteArray()创建一个新分配的 byte 数组// 将字节数组内存操作输出流对象转换成字节数组byte[] bys = baos.toByteArray();// 创建字节数组内存操作输入流对象ByteArrayInputStream bais = new ByteArrayInputStream(bys);// 既然是字节流:就可以使用基本字节流读数据的方法// 一次读取一个字节int by = 0;while ((by = bais.read()) != -1) {System.out.print((char) by);}}}

3)打印流Print

1.字节打印流

import java.io.IOException;import java.io.PrintWriter;public class Demo01 {public static void main(String[] args) throws IOException {// 创建打印流PrintWriter pw = new PrintWriter("a.txt");// 写数据pw.write("hello");pw.write("world");pw.write("java");pw.flush();pw.close();}}

2.字符打印流

可以写任何数据类型:

PrintStream ps = System.out; 字节打印流

ps.println();

ps.print(数据类型);

字符打印流的一个构造方法:可以进行自动刷新

public PrintWriter(Writer out, boolean autoFlush)

如果想要是自动刷新,那么第二个参数的值为:true

换行还要使用字符打印流中的:println();

import java.io.FileWriter;import java.io.PrintWriter;public class Demo02 {public static void main(String[] args) throws Exception {PrintWriter pw = new PrintWriter(new FileWriter("pw.txt"), true);pw.println("hello");pw.println(100);pw.print(12.34F);pw.close();}}

该流:不能操作数据源,只能操作目的的数据:该流只能写数据,不能读数据

该流可以自动刷新

该流还可以针对文本数据进行操作

(只要构造方法中有File对象或者String类型的路径都是可以对文本进行操作的)

需求:将当前项目下的a.txt文件复制到当前项目下的b.txt文件中

import java.io.BufferedReader;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter;public class Demo03 {public static void main(String[] args) throws IOException {// 数据源BufferedReader br = new BufferedReader(new FileReader("a.txt"));// 目的PrintWriter pw = new PrintWriter(new FileWriter("b.txt"));// 写数据String line = null;while ((line = br.readLine()) != null) {pw.println(line);}pw.close();br.close();}}

4)标准流

1.标准输入流:public static final InputStream in

2.标准输出流:public static final PrintStream out

3.字节数如流:InputStream = System.in

4.字节输出流:PrintStream = System.out

import java.io.PrintStream;public class Demo01 {public static void main(String[] args) {// 我们一直使用的输出语句,其实就是采用流的一种进行:字节打印流进行输出System.out.println("hello world");PrintStream ps = System.out;// 返回的是字节打印流对象ps.println("hello world");ps.println();}}
直接使用标准输出流:和刚才使用字符缓冲输入流封装字输入流一样,输出数据

import java.io.BufferedOutputStream;import java.io.IOException;public class Demo02 {public static void main(String[] args) throws IOException {// 和刚才使用字符缓冲输入流封装字输入流一样,输出数据BufferedOutputStream bos = new BufferedOutputStream(System.out);bos.write("hello".getBytes());bos.write("world".getBytes());bos.write("java".getBytes());bos.close();}}
需求:用字符缓冲输入流包装字节输入流,进行录入数据!(键盘录入)

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Demo03 {public static void main(String[] args) throws IOException {// 1)使用输入流的方式将标准输入流包装起来,进行录入数据// InputStream is = System.in;// 字节流对象:// 可以获取一行数据吗?// 可以:readLine()这个方法哪个流里面的?属于字符缓冲输入流里面的方法,// BufferReader():底层应该也是用字节流进行实现,所有可以用它封装一下// BufferedReader br = new BufferedReader(is);// 字符缓冲流只能针对字符流进行操作,并不直接针对字节流操作// 2)哪个流可以将字节流转换成字符流// InputStreamReader isr = new InputStreamReader(is);//// 转换输入流=字节流+编码格式(gbk)// 3)在用字符缓冲输入流封装当前的转换流// 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("请输入一个整数:");String s = br.readLine();int i = Integer.parseInt(s);System.out.println("整数是:" + i);}}

5)随机访问流RandomAccessFile

并不是实际意义的流

public RandomAccessFile(String name,String mode):

mode:里面的模式:只记住:常用的就:rw:既可以读,也可以写

读数据

import java.io.IOException;import java.io.RandomAccessFile;public class Demo01 {public static void main(String[] args) throws IOException {RandomAccessFile raf = new RandomAccessFile("a.txt", "rw");byte b = raf.readByte();System.out.println(b);// public long getFilePointer(),返回此文件的偏移量System.out.println("当前指移动到的位置是:" + raf.getFilePointer());char ch = raf.readChar();System.out.println(ch);System.out.println("当前指移动到的位置是:" + raf.getFilePointer());// String s = raf.readUTF();// System.out.println(s);// System.out.println("当前指移动到的位置是:" + raf.getFilePointer());// public void seek(long pos)throws IOException// 设置到此文件开头测量到的文件指针偏移量// 从第四个字符开始raf.seek(3);char c = raf.readChar();System.out.println(c);raf.close();}}
写数据

import java.io.IOException;import java.io.RandomAccessFile;public class Demo02 {public static void main(String[] args) throws IOException {RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");raf.writeByte(100);raf.writeChar('A');raf.writeUTF("中国");raf.close();}}

6)合并流SequenceInputStream

合并流,将一些输入流合并起来,对输出流没有作用,表示其他输入流的逻辑串联

复制文件:a.txt--->b.txt,c.txt--->d.txt

合并流:a.txt+b.txt---->c.txt中

1.public SequenceInputStream(InputStream s1,InputStream s2)

需求:将当前项目下的a.txt文件和b.txt文件中的内容复制到当前项目下的c.txt文件中

import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;public class Demo01 {public static void main(String[] args) throws IOException {// 将数据源封装成合并流SequenceInputStream sis = new SequenceInputStream(new FileInputStream("a.txt"), new FileInputStream("b.txt"));// 创建字节缓冲输出流对象BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c.txt"));// 读写操作byte[] bys = new byte[1024];int len = 0;while ((len = sis.read(bys)) != -1) {bos.write(bys, 0, len);}bos.close();sis.close();}}

2.public SequenceInputStream(Enumeration e)

可以将两个以上文件合并

需求:将当前目录下的a.txt和b.txt和c.txt文件合并到d.txt文件中

import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.SequenceInputStream;import java.util.Enumeration;import java.util.Vector;public class Demo02 {public static void main(String[] args) throws IOException {// 观察合并流构造方法中有一个:Enumration这个类型,和Vecotr集合有关系// 首先创建Vector集合对象Vector<InputStream> v = new Vector<InputStream>();InputStream s1 = new FileInputStream("a.txt");InputStream s2 = new FileInputStream("b.txt");InputStream s3 = new FileInputStream("c.txt");v.add(s1);v.add(s2);v.add(s3);Enumeration<InputStream> en = v.elements();// 创建合并流对象SequenceInputStream sis = new SequenceInputStream(en);// 创建字节缓冲流输出对象BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d.txt"));byte[] bys = new byte[1024];int len = 0;while ((len = sis.read(bys)) != -1) {bos.write(bys, 0, len);bos.flush();}bos.close();sis.close();}}

7)序列化流和反序列化流

序列化流:

将对象按照流的形式(在网络进行传输等等)封装成流数据:对象--->流数据:ObjectOutputStream

反序列化流:

将网络传输中的流数据又封装成了一个对象: 流数据-->对象   ObjectInputStream

Person类

若没有实现Serializable会怎样?java.io.NotSerializableException: xxx.Person

告诉我们:当前自定义的类并没有实现序列化接口

类通过实现 java.io.Serializable 接口以启用其序列化功能

未实现此接口的类将无法使其任何状态序列化或反序列化。

Serializable接口:

通过查看API:发现Serializable接口中没有字段,构造方法,成员方法

所有如果一个接口中没有任何的方法或者他的字段,将这种接口叫标记接口!

Person

import java.io.Serializable;public class Person implements Serializable {// 默认的:default srial Version ID:默认版本ID// Person有黄色警告线,点击,生成下面的代码,获取IDprivate static final long serialVersionUID = 1L;// 成员变量private String name;private int age;// transient int age;public Person() {super();// TODO Auto-generated constructor stub}public Person(String name, int age) {super();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;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}}

测试类

import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Demo01 {public static void main(String[] args) throws Exception {// 序列化ObjectOutputStream oot = new ObjectOutputStream(new FileOutputStream("oot.txt"));Person p = new Person("张三", 20);oot.writeObject(p);oot.close();//反序列化ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oot.txt"));Object obj = ois.readObject();ois.close();System.out.println(obj);}}
1.只进行序列化

2.将序列化注释掉,

3.修改Person类中的成员变量private int age ----> int age

4.再进行反序列化

结果:java.io.InvalidClassException: 

local class incompatible: stream classdesc serialVersionUID = -3059867121192605950, 

local class serialVersionUID = -1219396793646518298

原因:

序列化流和反序列化流

刚才已经手动写了,并且运行了一次

每一次在加载Person.class文件的时候,都会生成一个ID

比如:第一次没有修改Person类中文件:class文件

Person.class ---->ID = 100 ;

private String name --->ID =100

prvate int age ------->ID = 100 

后面修改了class文件中的内容

Person.class------>ID= 200

private String name --->ID =100

int age ------->ID = 100

这样的话:ID版本号不匹配:就出现了刚才这个异常:

实际开发中,可能有时候需要用到以前的数据

所以就需要我们将当前的这个class文件要生成固定ID

这样的话就不会报异常了

当前的这个类有黄色警告线,点击黄色警告线生成ID

如果在一个类中,该类的成员变量比较多

有时候为了让成员变量不被序列化

加一个关键字:transient

这样:如果是 String name,输出的是null;int age,输出的是0

B.属性集合类Properties

1)概述

这个类是Hashtbale的子类,而Hashtable也Map下面的双列集合

注意:Properties:不带泛型!

import java.util.Properties;import java.util.Set;public class Demo01 {public static void main(String[] args) {Properties prop = new Properties();prop.put("1001", "张三");prop.put("1002", "李四");prop.put("1003", "王五");// 遍历Set<Object> set = prop.keySet();for (Object key : set) {Object value = prop.get(key);System.out.println(key + "---" + value);}}}

2)特殊功能

public Object setProperty(String key,String value):和添加相关的

public Set<String> stringPropertyNames():获取所有的键的集合

public String getProperty(String key):获取指定的属性集合中的键的值

import java.util.Properties;import java.util.Set;public class Demo02 {public static void main(String[] args) {Properties prop = new Properties();prop.setProperty("张三", "20");prop.setProperty("李四", "21");prop.setProperty("王五", "22");// 获取所有键集合Set<String> set = prop.stringPropertyNames();for (String key : set) {// 获取指定的值String value = prop.getProperty(key);System.out.println(key + "---" + value);}}}

3)功能

public void load(Reader reader):将文本文件的数据读取集合中

public void store(Writer writer, String comments):将集合中的数据保存到文本文件中

comments:属性列表的描述

import java.io.FileReader;import java.io.FileWriter;import java.io.Reader;import java.io.Writer;import java.util.Properties;public class Demo03 {public static void main(String[] args) throws Exception {Properties prop = new Properties();prop.setProperty("张三", "21");prop.setProperty("李四", "22");prop.setProperty("王五", "23");// 将集合中的数据保存到文件中Writer w = new FileWriter("name.txt");prop.store(w, "Person");// 将文件中的数据读取集合中Reader r = new FileReader("name.txt");prop.load(r);r.close();w.close();System.out.println(prop);}}

4)练习

我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。

请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100”

1.先将文件中的数据加载到集合中

2.获取键的集合,遍历键的集合

判断:如果"lisi"就是里面的key

是的话就修改

3.重新将集合中的数据保持到文件中


import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.util.Properties;import java.util.Set;public class Demo04 {public static void main(String[] args) throws IOException {Properties prop = new Properties();prop.load(new FileReader("user.txt"));Set<String> set = prop.stringPropertyNames();for (String key : set) {if ("李四".equals(key)) {prop.setProperty("李四", "100");System.out.println("匹配到结果,并完成修改,请查看user.txt");break;}}prop.store(new FileWriter("user.txt"), "user");}}



阅读全文
2 0
原创粉丝点击