【JavaSE学习笔记】IO(五)其他流

时间:2022-10-26 21:36:38

本期知识点:

数据操作流

内存操作流

打印流

标准输入输出流

随机访问流

合并流

序列化流

Properties


1.数据操作流

a.可以操作基本类型的数据


b.操作基本数据类型的流:
DataInputStream :数据输入流
DataOutputStream:数据输出流
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;

//(1)可以操作基本类型的数据
//(2)流对象名称
//DataInputStream
//DataOutputStream
public class Demo1 {
public static void main(String[] args) throws IOException{
Write();
Read();
}

public static void Read() throws IOException{
DataInputStream dis = new DataInputStream
(new FileInputStream("数据操作流.txt"));

//读数据
System.out.println(dis.readByte());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
System.out.println(dis.readChar());

dis.close();
}

public static void Write() throws IOException {
DataOutputStream dos = new DataOutputStream
(new FileOutputStream("数据操作流.txt"));
dos.writeByte(10);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000L);
dos.writeFloat(12.34F);
dos.writeDouble(12.56);
dos.writeBoolean(true);
dos.writeChar('A');

dos.close();
}
}


2.内存操作流

a.概述:

用来存储内存中的临时信息,程序结束的时候,内存流就消失了
有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。

b.字节数组操作内存流:

ByteArrayInputStream
ByteArrayOutputStream

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

CharArrayReader
CharArrayWriter

d.字符串

StringReader
StringWriter
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import sun.awt.image.ByteArrayImageSource;

/*内存操作流:用来存储内存中的临时信息,程序结束的时候,内存流就消失了!
字节数组操作内存流:
ByteArrayInputStream
ByteArrayOutputStream
字符数组操作的内存流
CharArrayReader,
CharArrayWriter
字符串
StringReader,
StringWriter
*/
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 []a = baos.toByteArray();
//创建字节数组内存操作输入流对象
ByteArrayInputStream bais = new ByteArrayInputStream(a);
//既是字节流,就可以使用基本自己流读取数据的方法
//一次读取一个字节
int b = 0;
while((b=bais.read())!=-1){
System.out.print((char)b);
}

}
}


3.打印流

a.分为

字节打印流:PrintStream
字符打印流:PrintWriter

b.特点

i.只操作目的地,不操作数据源
ii.可以操作任意类型的数据
iii.如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新

iv.可以直接操作文件


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

public PrintWriter(Writer out, boolean autoFlush)
如果想要是自动刷新,那么第二个参数的值为:true

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


d.问题:哪些流可以直接操作文件?

FileOutPutStream
FileInputStream
FilerWriter
FileReader
BufferedReader
BufferedWriter
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;

public class Demo01 {

public static void main(String[] args) throws IOException {
//创建打印流对象
PrintWriter pw = new PrintWriter("pw.txt");
//写数据
pw.write("hello");
pw.write("world");
pw.write("love");

pw.flush();

pw.close();
}

}

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

public class Demo02 {

public static void main(String[] args) throws IOException {
//创建字符打印流对象,使用自动刷新的构造方法
PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"),true);
//写数据
//直接使用println()方法换行
pw.println("hello");
pw.println(100);
pw.println(12.34F);

pw.close();
}

}


4.标准输入输出流

a.System类下面有这样的两个字段

in 标准输入流
out 标准输出流

b.三种键盘录入方式

i:main方法的args接收参数


ii:System.in通过BufferedReader进行包装

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


iii:提供了Scanner类:文本扫描器
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
System.out.println(line);

c.输出语句的原理和如何使用字符流输出数据

i:原理
System.out.println("helloworld");
PrintStream ps = System.out;
ps.println("helloworld");
ii:把System.out用字符缓冲流包装一下使用
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

5.随机访问流

a.随机访问流,并不是实际意义的流

b.类的实例支持对随机访问文件的读取和写入融合了InputStream和OutputStream两个类

c.构造方法:

public RandomAccessFile(String name,String mode):
mode:里面的模式:只记住:常用的就:rw:既可以读,也可以写

d.随机访问流读数据的方法:

public long getFilePointer返回此文件的偏移量

public void seek(long pos) throws IOException 设置到此文件开头测量到的文件指针偏移量

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Demo01 {

public static void main(String[] args) throws IOException {
//write();
read();
}
//随机访问流读数据
public static void read() throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt","rw");

byte a =raf.readByte();
System.out.println(a);

//public long getFilePointer, 返回此文件的偏移量
System.out.println("当前指针的移到的位置是:"+raf.getFilePointer());

char b = raf.readChar();
System.out.println(b);
System.out.println("当前指针的移到的位置是:"+raf.getFilePointer());

String c = raf.readUTF();
System.out.println(c);
//System.out.println("当前指针的移到的位置是:"+raf.getFilePointer());

//public void seek(long pos)
// throws IOException设置到此文件开头测量到的文件指针偏移量

////现在想从字符A开始
raf.seek(3);
b = raf.readChar();
System.out.println(b);
//关闭资源
raf.close();
}
//随机访问流写数据
public static void write() throws IOException {
//创建随机访问流
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
//写数据
raf.writeByte(100);
raf.writeChar('a');
raf.writeUTF("我爱你");

raf.close();
}

}


6.合并流

a.把多个输入流的数据写到一个输出流中。

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

b.构造方法:

SequenceInputStream(InputStream s1, InputStream s2)
SequenceInputStream(Enumeration<? extends InputStream> e)
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;

public class 合并流Demo1 {
public static void main(String[] args) throws IOException {
//需求:将当前项目的合并Demo1和合并Demo2的内容复制到Copy.txt
InputStream is1 = new FileInputStream("合并流Demo1.txt");
InputStream is2 = new FileInputStream("合并流Demo2.txt");
//创建合并流对象
SequenceInputStream sis = new SequenceInputStream(is1,is2);
//创建输出流对象 (字符缓冲流)
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.txt"));

byte []a = new byte[1024];
int len = 0 ;
while((len=sis.read(a))!=-1){
bos.write(a, 0, len);
}
sis.close();
bos.close();

}
}

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
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 合并流Demo2 {
public static void main(String[] args) throws IOException {
//观察合并流构造方法中有一个:Enumration这个类型,和Vecotr集合有关系
//首先:创建Vector集合对象
Vector<InputStream> v = new Vector<InputStream>();
//使用字节输入流封装三个文件
InputStream is1 = new FileInputStream("合并流Demo1.txt");
InputStream is2 = new FileInputStream("合并流Demo2.txt");
InputStream is3 = new FileInputStream("合并流Demo3.txt");
//添加到集合
v.add(is3);
v.add(is2);
v.add(is1);
//创建迭代器
Enumeration<InputStream> e = v.elements();
//创建合并流对象
SequenceInputStream sis = new SequenceInputStream(e);
//创建字节缓冲输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.txt"));
//读写
byte []a = new byte[1024];
int len = 0;
while((len=sis.read(a))!=-1){
bos.write(a, 0, len);
}
sis.close();
bos.close();
}
}


7.序列化流

a.序列化流:
将对象按照流的形式(在网络进行传输等等)封装成流数据:对象--->流数据:ObjectOutputStream
b.反序列化流:
将网络传输中的流数据又封装成了一个对象: 流数据-->对象 ObjectInputStream
c.如何实现序列化呢?
让被序列化的对象所属类实现序列化接口(Serializable接口)。
该接口是一个标记接口。没有功能需要实现。
d.注意:
实际开发中,可能有时候需要用到以前的数据,所有就需要我们将当前的这个class文件要生成固定ID,这样的话就不会报异常了
当前的这个类有黄色警告线,点击黄色警告线生成ID;
如果在一个类中,该类的成员变量比较多,有时候为了让成员变量不被序列化,所有加一个关键字:transient
import java.io.Serializable;

public class Person implements Serializable{
private static final long serialVersionUID = 1L;
//成员变量
private String name;
private int age;
public Person() {
super();
}
public Person(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 "Person [name=" + name + ", age=" + age + "]";
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;

/*
序列化流:将对象按照流的形式(在网络进行传输等等)封装成流数据:对象--->流数据:ObjectOutputStream
反序列化流:将网络传输中的流数据又封装成了一个对象: 流数据-->对象 ObjectInputStream
*/
public class Demo {
public static void main(String[] args) throws Exception {
//write();
read();
}

public static void read() throws Exception{
//创建反序列化流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("序列化.txt"));
ArrayList<Person> ro = (ArrayList<Person>) ois.readObject();
for (Person person : ro) {
System.out.println(person);
}
}

public static void write() throws IOException {
//创建序列化流对象
ObjectOutputStream oos = new ObjectOutputStream
(new FileOutputStream("序列化.txt"));
//写数据
ArrayList<Person> a = new ArrayList<Person>();

Person p1 = new Person("Ash",21);
Person p2 = new Person("Glaz",23);
Person p3 = new Person("Root",22);

a.add(p1);
a.add(p2);
a.add(p3);

oos.writeObject(a);

oos.close();
}
}


8.Properties

a.概述:

是一个集合类,Hashtable的子类
注意:Properties:不带泛型!

b.特殊功能:

public Object setProperty(String key,String value):和添加相关的:
public Set<String> stringPropertyNames():获取所有的键的集合
public String getProperty(String key):获取指定的属性集合中的键的值

c.和IO流结合的方法

i.把键值对形式的文本文件内容加载到集合中
public void load(Reader reader)
public void load(InputStream inStream)
ii.把集合中的数据存储到文本文件中
public void store(Writer writer,String comments)
public void store(OutputStream out,String comments)

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

/*
Properties :属性集合类(用作txt格式的配置文件)
这个类是Hashtbale的子类,而Hashtable也Map下面的双列集合
put()方法,添加元素

注意:Properties:不带泛型!*/
public class Demo01 {
public static void main(String[] args) {
//创建属性集合对象
Properties p = new Properties();
//添加元素
p.put("Ash", "21");
p.put("Glaz", "21");
p.put("Fuze", "23");

//System.out.println("p:"+p);//p:{Fuze=23, Ash=21, Glaz=21}
//遍历元素
Set<Object> set = p.keySet();
for (Object key : set) {
Object value = p.get(key);
System.out.println(key+"---"+value);
}
}
}

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

/*
Properties里面的特殊功能:
public Set<String> stringPropertyNames():获取所有的键的集合
public Object setProperty(String key,String value):和添加相关的:
public String getProperty(String key):获取指定的属性集合中的键的值
*/
public class Demo02 {
public static void main(String[] args) {
//创建属性集合对象
Properties p = new Properties();
//添加元素
p.setProperty("Ash", "21");
p.setProperty("Glaz", "21");
p.put("Fuze", "23");
//public Set<String> stringPropertyNames():获取所有的键的集合
Set<String> sp = p.stringPropertyNames();
for (String key : sp) {
//public String getProperty(String key):获取指定的属性集合中的键的值
Object value = p.get(key);
System.out.println(key+"---"+value);
}
}

}
import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.Reader;import java.io.Writer;import java.util.Properties;public class Demo03 {public static void main(String[] args) throws IOException {Store();Load();}//将集合中的数据保存到文本文件中public static void Store() throws IOException {//创建属性集合类对象Properties p = new Properties();//添加元素p.setProperty("list", "10");p.setProperty("Ash", "20");p.setProperty("Root", "30");p.setProperty("Glaz", "40");//public void store(Writer writer, String comments)://将集合中的数据保存到文本文件中Writer w = new FileWriter("Key.txt");p.store(w, "names");w.close();}//将文本文件的数据读取集合中public static void Load() throws IOException {//创建属性集合对象Properties p = new Properties();Reader r = new FileReader("p.txt");// public void load(Reader reader)://将文本文件的数据读取集合中p.load(r);r.close();System.out.println(p);}}
import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.Reader;import java.io.Writer;import java.util.Properties;import java.util.Set;/*我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100”  1)先将文件中的数据加载到集合中 2)获取键的集合,遍历键的集合 判断:如果"lisi"就是里面的key, 是的话就修改 3)重新将集合中的数据保持到文件中*/public class test {public static void main(String[] args) throws IOException {//将文件中的数据加载到集合中Properties p = new Properties();Reader r = new FileReader("user.txt");p.load(r);r.close();//获取所有键的集合Set<String> set = p.stringPropertyNames();for (String key : set) {//获取到每一个键 ,然后判断if("list".equals(key)){//修改p.setProperty(key, "100");break;}}//重新保存Writer w = new FileWriter("user.txt");p.store(w, null);w.close();}}