文件的各种流

来源:互联网 发布:淘宝订单进度条 编辑:程序博客网 时间:2024/05/23 18:51

一.输入流与输出流,流只有单向的

输入:读,从外界获取信息

输出:写,把数据写到外面

 

节点流(低级流):可以从或向一个特定的地方(节点)读写数据,真实搬运数据

处理流(高级流):是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写,不独立存在,去处理另一个流,简化操作,加工低级流,也可以加工高级流

 

数据源:数据的源头,读的数据是数据源,输出的数据发送到的地方也称为数据源

 

二.文件流

FileOutputStream:文件字节输出流

              // 默认的构造方法时覆盖写操作

              // 即若要写出的文件已经存在,会先将该文件中的原有数据全部清除,然后通过该流写出新的数据

              // FileOutputStream fos= new FileOutputStream("fos.txt");

               * 追加写操作,该构造方法需要传入第二个参数,该参数为一个boolean,若为true就可以追加写操作那么该流写出的内容会被追加到该文件末尾

              FileOutputStreamfos =new FileOutputStream("fos.txt",true);

              fos.write("简单点,说话的方式简单点".getBytes());

              System.out.println("写出完毕");

              fos.close();

FileInputStream:文件字节输入流

       FileInputStreamfis = new FileInputStream("fos.txt");

              byte[]data = newbyte[30];

              intlen = fis.read(data);

              Stringstr = new String(data, 0,len, "GBK");

              System.out.println(str);

              fis.close();

* 使用文件流完成文件复制操作

               * 使用FIS读取源文件,使用FOS向目标文件写数据,依次从源文件中读取字节然后写入目标文件完成复制操作

              FileInputStreamsrc =new FileInputStream("sucai.rar");

              FileOutputStreamdesc =new FileOutputStream("sucai_p.rar");

 

              byte[]data = newbyte[30];

              intlen = src.read(data);

              if (len != -1) {

                     desc.write(data, 0,len);

              }

              System.out.println("复制完毕!");

              src.close();

              desc.close();

 

三.缓冲流

* 缓冲流,作用,提高读写效率缓冲流是一对高级流,使用它们进行读写的效率是比较高的

public class CopyDemo2 {

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

              FileInputStreamsrc =new FileInputStream("sucai.rar");

              // bis装到src上就可以高效率

              BufferedInputStreambis =new BufferedInputStream(src);

              FileOutputStreamdesc =new FileOutputStream("sucai_p.rar");

              BufferedOutputStreambos =new BufferedOutputStream(desc);

              intlen = bis.read();

               * 缓冲流内部维护了一个缓冲区,当我们调用下面

               * read()方法读取一个字节时,实际上缓冲流会让fis读取一组字节并存入到缓冲流自身内部的字节数组中,

               * 然后将第一个字节返回,当我们再次调用read()方法读取一个字节时,缓冲流会直接将数组中第二个字节返回,

               * 以此类推,知道该数组中所有字节都被读取过后才会再次读取一组自节,所以实际上还是通过提高每次读取数据的数量

               * 来减少读取次数提高读取效率

              while (len != -1) {

                     bos.write(len);

              }

              System.out.println("复制完毕!");

              bis.close();

              bos.close();   }

}

* 缓冲输出流写出数据

//通过缓冲输出流写出的字节并不会立刻被写入文件,会先存入其内部的字节数组,直到数组满了,才会一次性写出所有数据,这样做等同于提高写出数据量减少写出次数,提高写出效率

FileOutputStream fos = new FileOutputStream("bos.txt");

              BufferedOutputStreambos =new BufferedOutputStream(fos);

              bos.write("我爱wy".getBytes());

              System.out.println("写出完毕!");

//flush方法可以强制将缓冲区已有数据一次性写出,这样可以提高及时性,但是频繁操作会导致效率降低      

              bos.flush();//我爱wy 由于字节不够BufferedOutputStream缓冲区的长度,所以不会输出,需要借助flush

close()本身包含flush

四.对象流

* java.io.ObjectOutputStream

 * 对象输出流,是一个高级流,作用是可以直接将java中的一个对象转化为一组字节后输出,这组字节的格式有OOS维护

public class OOSDemo {

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

              Personp = new Person();

              p.setName("wy");

              p.setAge(18);

              p.setGender("");

 

              List<String>otherInfo =newArrayList<String>();

              otherInfo.add("是一个女生");

              otherInfo.add("在苏州");

              otherInfo.add("快要20");

              p.setOtherInfo(otherInfo);

              System.out.println(p);

               * OOSwriteObject方法的作用:将给定的java对象转换为一组字节后写出

               * 这里由于OOS是装在FOS上的,所以转换的这组字节最终通过FOS写入到文件person.obj

               * 若洗完该对象可以被写出,那么前提是该对象所属类必须实现Serializable接口      

              FileOutputStreamfos =new FileOutputStream("person.obj");

              ObjectOutputStreamoos =new ObjectOutputStream(fos);

* 该方法涉及到了两个操作

               * 1.将对象转换为一组字节,称为对象序列化

               * 2.将该组字节写入到文件中(硬盘上)à数据持久化

              oos.writeObject(p);

              System.out.println("写出完毕!");

              oos.close();

       }

}

 

 

对象的反序列化:

 *java.io.ObjectInputStream 对象输入流,是一个高级流,作用是可以读取一组字节然后将其还原为描述的对象

 * 需要注意,读取的这些字节必须是有ObjectOutputStream将一个对象转换的字节,否则会抛出异常

public class OISDemo {

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

              FileInputStreamfis =new FileInputStream("person.obj");

              ObjectInputStreamois =new ObjectInputStream(fis);

//将一组字节还原为对象的过程称为反序列化

              Personp = (Person)ois.readObject();

              System.out.println(p);

              ois.close();

       }

}

* 序列化版本号:当一个类实现了Serializable接口后,该类会有一个常量表示这个类的版本号,版本号影响这对象反序列化的结果,建议自行维护版本号(自己定义该常量并给定值),若不指定,编译器会根据当前类的结构生成一个版本号,结构不变版本号不变,但是结构变了(属性类型,名字变化)都会导致版本号改变

* 反序列化对象时,会检查该对象的版本号与当前类现在的版本号是否一致,一致可以还原,不一致则反序列化失败,版本号一致时,就算反序列化的对象与当前类的对象结构有出入,也会采取兼容模式,即:仍然有得属性进行还原,没有的属性被忽略

       private static final long serialVersionUID = 1L;

       private Stringname;

       private int age;

       private Stringgender;

       /**

        * transient关键字的作用是修饰一个属性,那么当这个类的某个实例进行序列化时,该属性不会被包含在序列化后的字节中,从而达到

        * 瘦身目的

       private transient List<String> otherInfo;//对象在()序列化的时候不含有这个属性

签名接口

public interface Serializable {}

 

只要版本不变,反序列一定成功,如果结构改变,反序列化的时候,结构被改变的项就不会还原,只还原还有的项。

0 0