学习日志day15(2021-07-28)(1、IO流 2、字节流 3、字符流 4、转换流 5、装饰者模式 )

学习内容:学习JavaSE(Day15)

1、IO流
2、字节流
3、字符流
4、转换流
5、装饰者模式


1、IO流

(1)流:从处理的数据单位不同可分为字节流和字符流;
从数据流方向不同可分为输入流和输出流。

字节流:是用来操作字节文件,但也可以操作字符文件。
字符流:用来操作字符文件。
转换流:将字节流转换为字符流。

输入流:从外部存储空间数据读到内存中(内存中的数据都是临时数据,关机或程序执行完毕,数据就没了,不能永久保存下来)。
输出流:从内存中将输入写到外部存储空间(硬盘、U盘、CD、DVD这些设备中的数据是永久保存下来的,不会自动消失)。

(2)所有字节输入流的超类是:InputStream(抽象类),它的子类有FileInputStream、ObjectInputStream、FilterInputStream。BufferedInputStream和DataInPutStream是FilterInputStream的子类。

所有字节输出流的超类是:OutputStream(抽象类),它的子类有FileoutputStream、ObjectOutputStream、FilterOutputStream。BufferedOutputStream和DataOutPutStream是FilterOutputStream的子类。

所有字符输入流的超类是:Reader(抽象类),它的子类有BufferedReader、InputStreamReader。FileReader是InputStreamReader的子类。

所有字符输出流的超类是:Writer(抽象类),它的子类有BufferedWriter、OutputStreamWriter。FileWriter是OutputStreamWriter的子类。

将字节输入流转换为字符输入流:InputStreamReader。
将字节输出流转换为字符输出流:OutputStreamWriter。

2、Java的字节流

(1)使用FileInputStream和FileOutputStream类实现文件的复制粘贴。

public static void main(String[] args) throws IOException {
    File file = new File("d:/myPic/1.jpg");
    //输入流对象
    FileInputStream fis = new FileInputStream(file);
    File file1 = new File("d:/pic/2.jpg");
    //输出流对象
    FileOutputStream fos = new FileOutputStream(file1);
    int len = -1;
    //read返回下一个数据字节;如果已到达文件末尾,则返回 -1
    while((len = fis.read()) != -1){
        fos.write(len);
    }
    //释放资源 关闭流
    fis.close();
    fos.close();
}

每次读取和写入一个字节的效率很慢,可以使用传参为byte数组的read(byte[ ] b)方法和write(byte[ ] b)方法每次读取和写入一个制定大小的数组。

byte[] buffer = new byte[512];
int len = -1;
while((len = fis.read(buffer)) != -1){
	//可以写成fos.write(buffer),但是当剩余字节小于数组大小时,
	//还需要调用一次buffer数组,即512字节,效率不高
    fos.write(buffer,0,len);//最后一次调用时len等于剩下的小于512字节
}
fis.close();
//不再是每次读取一个字节,而是数组,会先把数据存到缓冲区,再继续读取
//写入会在缓冲区中找到数据,并写入输出流,如果不刷新就关闭,缓冲区中的
//数据可能没有及时被写入,造成数据损失。
fos.flush();//刷新
fos.close();

(2)BufferedInputStream和BufferedOutputStream类可以创建自带缓冲区的输入输出流。

public static void main(String[] args) throws IOException {
    File file = new File("d:/myPic/1.jpg");
    FileInputStream fis = new FileInputStream(file);
    BufferedInputStream bis = new BufferedInputStream(fis);
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("d:/pic/3.jpg")));
    int len = -1;
    while((len = bis.read()) != -1){
        bos.write(len);
    }
    bis.close();
    bos.flush();
    bos.close();
}

(3)DataInputStream和DataOutputStream类可以创建Java基本数据类型的输入输出流。

public static void main(String[] args) throws IOException {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("d:/pic/1.data")));
    dos.writeInt(12);
    dos.writeDouble(13.0);
    dos.writeUTF("Hello");
    dos.writeBoolean(true);
    dos.flush();//写的时候需要刷新,不管有没有缓冲区要养成良好习惯
    dos.close();

    DataInputStream dis = new DataInputStream(new FileInputStream("d:/pic/1.data"));
    System.out.println(dis.readInt());
    System.out.println(dis.readDouble());
    System.out.println(dis.readUTF());
    System.out.println(dis.readBoolean());
    dis.close();//读的时候不需要使用flush功能刷新
}

(4)ObjectOutputStream 将 Java 对象的基本数据类型和图形写入OutputStream。只能将支持 java.io.Serializable 接口的对象写入流中,即序列化后的对象。
ObjectInputStream对写入的基本数据和对象进行反序列化。 只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

把一个Java对象写入外部文件的过程叫做 :序列化。
IDEA自动生成序列化ID:点击左上方文件,选择设置,选择检查,选择Java,勾选Serializable class without ‘serialVersionUID’。之后在实现序列化接口的实体类类名处Alt+回车,就可以自动添加序列化ID。

public class User implements Serializable { //实现序列化接口
	//实现序列化ID
    private static final long serialVersionUID = 4178671492450283301L;
    private int age;
    private String userName;
    private String address;
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
    User user = new User(12,"Rose","shanghai");
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/pic/user.obj"));
    oos.writeObject(user);
    oos.flush();
    oos.close();
	//反序列化,将对象读取到内存
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/pic/user.obj"));
    User o = (User)ois.readObject();
    System.out.println(o.getAge());
    ois.close();
}

当实体类User实现序列化后,如果调用了其它实体类P的对象,那么使用输入输出流时不能调用属性p,除非对象P也实现了序列化接口。

public class User implements Serializable {
    private static final long serialVersionUID = 4178671492450283301L;
    private P p;
}

(5)1. 参与序列化与反序列化的类必须实现java.io. Serializable接口,并推荐生成序列化ID
2. 静态属性不参与序列化与反序列化操作
3. 父类可以序列化,那么子类必然可以序列化,无论子类是否实现java.io.Serializable接口
4. 类序列化时,属性引用的对象也会被序列化
5. 不参与序列化操作的属性需要标记为transient

3、Java的字符流

(1)FileWriter用于写入输出字符流,FileReader用于读取输入字符流。

FileWriter fileWriter = new FileWriter(new File("d:/pic/1.txt"));
fileWriter.write("Hello");
fileWriter.flush();
fileWriter.close();

FileReader fileReader = new FileReader("d:/pic/1.txt");
StringBuffer stringBuffer = new StringBuffer();
int len = -1;
while((len = fileReader.read()) != -1){
    stringBuffer.append((char) len);
}
System.out.println(stringBuffer);

(2)BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("d:/pic/2.txt"));
bufferedWriter.write("Hello World");
bufferedWriter.flush();
bufferedWriter.close();

BufferedReader bufferedReader = new BufferedReader(new FileReader("d:/pic/2.txt"));
int len = -1;
while((len = bufferedReader.read()) != -1){
     System.out.println(len);
}
bufferedReader.close();

readLine() :一次可以读取一整行,当到达流末尾时返回null。

BufferedReader bufferedReader = new BufferedReader(new FileReader("d:/pic/2.txt"));
String len = null;
while((len = bufferedReader.readline()) != null){
     System.out.println(len);
}
bufferedReader.close();

read(char[] cbuf, int off, int len):将字符读入数组的某一部分。

BufferedReader bufferedReader = new BufferedReader(new FileReader("d:/pic/2.txt"));
int len = -1;
String str = "";
char[] buffer = new char[512];
while((len = bufferedReader.read(buffer)) != -1){
     str = new String(buffer,0,len);
}
bufferedReader.close();
System.out.println(str);

4、转换流

(1)将字节输入流转换为字符输入流:InputStreamReader。
将字节输出流转换为字符输出流:OutputStreamWriter。

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/pic/3.txt"));
osw.write("Hello");
osw.flush();
osw.close();

InputStreamReader isr = new InputStreamReader(new FileInputStream("d:/pic/3.txt"));
StringBuffer stringBuffer = new StringBuffer();
int len = -1;
while ((len = isr.read()) != -1) {
    stringBuffer.append((char) len); 
}
isr.close();

5、装饰者模式

(1)装饰者模式:允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

IO流中的包装类使用到了装饰者模式:
BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter,InputStreamReader,OutPutStreamWriter等。

比如BufferedWriter 使用装饰者模式对 Writer子实现类进行了增强,添加了缓冲区,提高了写数据的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值