什么是java包装流_JAVA笔记整理-File文件类-包装流

一、包装流

定义: 在原始字节流或字符流的基础性,为了提高读写效率进行再次处理的流, 称为包装流/处理流

1、缓存字节流 BufferedInputStream 、BufferedOutputStream

​ 由于原始流在文件读写时 效率比较低(操作文件本身占用资源较多),可以通过创建缓冲区的方式提高读写效率, 将读取/写出的数据线放入缓冲区,到达一定数量后再次冲缓冲区读取/写出

​ mark(readLimit) 与 reset()用法

其中reset不能单独使用,必须mark(readLimit) ,readLimit表示标记后最多读取的上限,但是这里标记后读取的内容与BufferedInputStream的缓冲大小有关,比由上限决定,也就是说读取的内容超出上限可以继续重置到mark的位置。

public static void main(String[] args) throws IOException {

//创建缓冲流

InputStream is = new FileInputStream("d:/myfile.txt");

BufferedInputStream bis = new BufferedInputStream(is);

//是否支持mark 或 reset

System.out.println(bis.markSupported());

System.out.println((char)bis.read());//97

//重置

bis.mark(3); // pos标记往后退三个 最多可以读取字节上限

System.out.println("再次读取:"+(char)bis.read());

System.out.println("再次读取:"+(char)bis.read());

System.out.println("再次读取:"+(char)bis.read());

System.out.println("再次读取:"+(char)bis.read());

bis.reset(); // 这里 重置后 退回到3个以前的位置

// 重置后输出

int n =0;

while( (n = bis.read()) !=-1){

System.out.println("重置后;"+(char)n);

}

//关闭流

bis.close();

is.close();

}

2、缓存字符流 (BufferedReader 、BufferedWriter)

public static void main(String[] args) throws IOException {

// 缓冲字符流 可以一行一行读取 、写出

BufferedReader br = new BufferedReader(new FileReader("d:/小众网站.txt"));

//读一行

// System.out.println(br.readLine());

// System.out.println(br.readLine());

// System.out.println(br.readLine());

String s = null; //读的数据为空 则不需要读

while( (s = br.readLine()) !=null){

System.out.println(s);

}

br.close();

//缓冲写出流

FileOutputStream pw = new FileOutputStream("d:/abcd.txt");

//由于字节流不能直接放入 字符缓冲区,需要将它转成字符流 使用转换流并可以指定编码格式

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(pw));

bw.newLine();// 开启新一行(换行)

bw.write("这是测试转换流的方式");

bw.close();

}

3、打印流(输出流) PrintWriter 、PrintStream

public static void main(String[] args) throws FileNotFoundException {

// 打印流 ,提供一些打印输出方法

PrintWriter pw = new PrintWriter("d:/abcd.txt");

pw.print(100);

pw.println('a');//换行打印

pw.print("hello");

pw.close();

//System.out 字节打印流 PrintStream

4、数据字节流DataInputStream、DataOutputStream

它们用于读入写出Java基本数据类型的数据到文件或其他设备端,它们也属于包装流

DataOutputStream 常用方法

​ writerByte(byte):写一个字节到设备或文件

​ writerChar(char):写一个字符到设备或文件

​ writerInt(int):写一个4个字节的int到设备或文件

​writer(boolean):写一个boolean类型到设备或文件

​writerDouble(double):写一个double类型到设备或文件

​writerFloat(float):写一个float类型到设备或文件

​writerLong(long):写一个long类型到设备或文件

​writerShort(short):写一个short类型到设备或文件

​writerUTF(String):写一个字符串类型到设备或文件

DataInputStream: 读指定文件的数据,可以读数据类型

​ int readInt() :读一个int类型

​ short readShort():读一个short类型

readByte():读一个字节类型

​read():读一个字节类型

​readDouble(): 读一个double类型

​readFloat():读一个float类型

​readChar():读一个字符类型

​readBoolean():读一个boolean类型

​readLong() :读一个long类型

public static void main(String[] args) throws IOException {

//创建数据写出流

DataOutputStream dos = new DataOutputStream(

new FileOutputStream("d:/data.txt"));

//写一个int类型 依次写出4个字节

dos.writeInt(100);

dos.writeBoolean(true);

//关闭

dos.close();

//读取文件 创建数据读入流 ,需要按写的顺序读进来

DataInputStream dis = new DataInputStream(

new FileInputStream("d:/data.txt"));

//读一个int类型 (依次读4个字节)

int num = dis.readInt();

System.out.println("读取的数据:"+ num);

System.out.println("读的数据:"+dis.readBoolean());

dis.close();

}

5、转换流

​ 转换流是将字节流转成字符流的桥梁, 也可以在转换时指定编码格式。 InputStreamReader 和 OutputStreamWriter

public static void main(String[] args) throws IOException {

// 字节流转成字符流

InputStream is = new FileInputStream("d://小众网站.txt");

InputStreamReader isr = new InputStreamReader(is);

//缓冲流 读取数据

BufferedReader br = new BufferedReader(isr);

//读一行

String str =null;

while( (str= br.readLine()) !=null){

System.out.println(str);

}

//关闭流

br.close();

isr.close();

is.close();

}

public static void main(String[] args) throws IOException {

// 创建 字节转成字符的 写出流 FileOutputStream os =

FileOutputStream fos = new FileOutputStream("d://data.txt");

//指定编码 GBK 格式一个汉字占2个字节 UTF-8 格式一个汉字占3个字节

OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");

//缓冲形式的

BufferedWriter bw = new BufferedWriter(osw);

bw.write("你好");

bw.newLine();

bw.write("我不好");

bw.close();

}

6、随机字节流

RandomAccessFile 是随机字节流,它是一个可读可写的流 ,在文件操作时指定该对象的模式(model)后,可以读数据或写数据

实现 DataInputStream和DataOutputStream类

构造器:

RandomAccessFile rm = new RandomAccessFile(File ,mode);

​ RandomAccessFile rm = new RandomAccessFile(String ,mode);

mode表示对象的模式

r: 表示该对象只能读 不能写

rw/rws/rwd :表示该 对象是可读可写的;

public static void main(String[] args) throws IOException {

//创建可读 的流

RandomAccessFile reader = new RandomAccessFile("d://data.txt","r");

//创建可读可写的 的流

RandomAccessFile writer = new RandomAccessFile("d://data-1.txt","rw");

// 读和写的过程和之前一样

byte [] b= new byte[10];

int len=0;

while( (len = reader.read(b)) !=-1){

writer.write(b , 0 , len);

}

System.out.println("复制成功");

//关闭流

writer.close();

reader.close();

}

skipByte 和 seek的区别

// 跳字节读取

RandomAccessFile raf = new RandomAccessFile("d:/data.txt","rw");

// 跳过2个字节

raf.skipBytes(2);

System.out.println((char)raf.readByte()); //3

System.out.println("当前偏移量:"+raf.getFilePointer());//3

// 又丢弃1个字节 从当前位置 往后偏移1位

raf.skipBytes(1);

System.out.println("修改后的偏移量"+raf.getFilePointer());//4

System.out.println("偏移后的读取数据:"+(char)raf.readByte()); //5

raf.close();

// seek用法

RandomAccessFile raf2 = new RandomAccessFile("d:/data.txt","rw");

// 设置当前读取的位置 ,从0开始计算 ,指定n ,就从n的下一个字节 读取

raf2.seek( );

System.out.println("seek后的数据:"+(char)raf2.readByte());//3

raf2.seek(1); // 又从0开始 设置偏移量为1

System.out.println("修改后的偏移量"+raf.getFilePointer());//1

System.out.println("seek后的数据:"+(char)raf2.readByte())//2

raf2.close();

7、对象序列化流

​ 对象流也称为序列化流,用于存储对象和读取对象的字节流,也是属于包装流

序列化和反序列化

​ 将内存中的对象(Object,集合类等)保存到磁盘、网络介质、其他设置的过程,并在合适的时间能获取磁盘文件/网络的数据 ,这个过程就是对象的序列化和反序列化。

b081ca62d8585a6695ca65c28e88c936.png

为什么需要序列化和反序列化呢?

​ 在之前文件中存储的文本信息,这样不便于对数据的分类和操作,如果可以做到直接对对象的读和写这样可大大提高编程效率,并最大程度保证对象的完整性。

Java-IO中实现对象序列化的两种方式:

实现Serializable接口

实现Externalizable接口

Serializable接口

对象需要实现该接口,但是它没有任何需要实现的方法,只有一个用于标记该类可序列化的唯一标识。 任何类需要序列化都必须标记该变量

public class User implements Serializable {

// 对于能区分其他类的唯一表示

private static final long serialVersionUID = 1L;

private int uid;

private String name;

private String password;

// 有一部分属性不能序列化

public int getUid() {

return uid;

}

public void setUid(int uid) {

this.uid = uid;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

@Override

public String toString() {

return "User{" +

"uid=" + uid +

", name='" + name + '\'' +

", password='" + password + '\'' +

'}';

}

}

//创建序列化的对象流 从内存到文件

ObjectOutputStream oos = new ObjectOutputStream(

new FileOutputStream("d:/user.txt"));

User user= new User();

user.setUid(1001);

user.setName("admin");

user.setPassword("123456");

//序列化对象

oos.writeObject(user);

//关闭流

oos.close();

// 反序列化: 将文件中的数据 再读入到内存中 ,需要一个读的流 ObjectInputStream

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d://user.txt"));

// 反序列化尽量只读一次 (也可以读多次, 如何写出就如何读入)

Object obj = ois.readObject();

if(obj instanceof User){

User u = (User)obj;

System.out.println("反序列化的结果:"+u);

}

//关闭流

ois.close();

public interface Externalizable extends java.io.Serializable

Externalizable接口

public class Student implements Externalizable {

private int id;

private String name;

private String sex;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSex() {

return sex;

}

public void setSex(String sex) {

this.sex = sex;

}

// 自定义可序列化的属性

@Override

public void writeExternal(ObjectOutput out) throws IOException {

out.writeInt(this.id);

out.writeUTF(this.name);

}

@Override

public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

this.id = in.readInt();

this.name = in.readUTF();

}

public Student(int id, String name, String sex) {

this.id = id;

this.name = name;

this.sex = sex;

}

public Student( ) {

}

@Override

public String toString() {

return "Student{" +

"id=" + id +

", name='" + name + '\'' +

", sex='" + sex + '\'' +

'}';

}

}

public static void main(String[] args) throws IOException, ClassNotFoundException {

// 创建序列化类

ObjectOutputStream oos = new ObjectOutputStream(

new FileOutputStream("d:/stu.txt"));

//创建学生

List list = new ArrayList<>();

list.add(new Student(1001,"张飞","男"));

list.add(new Student(1002,"刘备","男"));

list.add(new Student(1003,"小乔","女"));

// 将集合序列化

oos.writeObject(list);

//关闭

oos.close();

// 反序列化

ObjectInputStream ois = new ObjectInputStream(

new FileInputStream("d:/stu.txt"));

//读

Object obj = ois.readObject();

if(obj instanceof List){

List list2 = (List)obj;

for(Student s : list2){

System.out.println(s);

}

}

//关闭流

ois.close();

}

问题: 能否自定义序列化的属性 :

这里可以采用方式二,实现Externalizable,

并重写两个方法 接口继承而来,

在其基础上新增了两个未实现方法:readExternal(ObjectInputStream)和 writeExternal(ObjectOutputStreawm)

自定义需要序列化的属性

问题: 哪些属性不能实现序列化 ?

1、类中的static修饰的属性不能序列化

2、类中属性被transient修饰的不能序列化 例如 transient private Integer age = null;

3、实现Externalizable接口的类的属性不能全部序列化,必须手动写可序列化的属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值