JAVASE--04


IO操作


I:输入流:读(眼睛是输入流,从外界读进来)
O:输出流:写
Java标准IO操作
IO是指:Input,Output,即输入与输出 *流按照方向实际是按照功能进行画分,参照方向是我们的程序;输入流用于读取,即从外界进入程序的过程,获取数据输出流用于写出,即程序发送到外界的过程,发送数据

流划分两类:


节点流

又称低级流,是真实连接程序与数据源的"管道",负责实际搬运数据.读写一定是建立在节点流的基础之上进行的


处理流

又称高级流,高级流不能独立存在(没有意义),一定是连接在其他流上使用的,目的是通过其连接的流将数据流经此流时对数据进行加工处理,从而简化我们实际读写的数据加工操作.
在低级流的基础上通过组合多个高级流在读写过程中完成一系列的数据加工操作的过程,称为流的链接,这也是Java标准IO操作的精髓所在(学习重点时学习*如何组建流链接,完成一系列的读写操作)
java.io.InputStream:所有字节输入流的超类,规定了所有输入流都应该具备的读取字节的相关方法
java.io.OutputStream:所有字节输出流的超类,规定了所有输出流都应该具备的写出字节的相关方法
低级流 ,文件流:是一对低级流,用来读写文件数据.FILE
java.io.FileInputStream:文件输入流,用来从文件中读取字节的流
java.io.FileOutputStream:文件输出流,用于向文件中写出字节的流
论功能,与RandomAccessFile一致,但是RAF又能读又能写,而文件流要根据做读或写操作选用输入或输出流进行,并且他们的底层读写操作时不一样的,RAF时基于指针对文件进行读写操作,所以可以通过操作指针进行部分覆盖写操作等.做到对文件数据编辑操作.但是流做不到,因为流是顺序读写操作.所以对于灵活性而言,RAF优于文件流,到那时文件流基于IO操作可以通过链接不同的高级流更轻松的完成复杂的读写操作.
对于读写文件而言:
RAF是基于指针的读写,称为"随机读写".可以移动指针对任意位置读写操作.
文件流是流的读写操作,而流是"顺序读写",只能顺序往后读写操作,是不能回退操作的.

写操作
    /*
     * FileOutputStream写操作
     * 文件输出流创建出来默认是覆盖写操作:
     * 即当操作的文件已经存在,那么在创建好文件输出流时会先将该文件的所有数据清除,
     * 然后通过该流写出的所有数据作为文件数据.
     * 文件流还支持重载构造方法,在第一个参数基础上可以再传入一个Boolean类型的参数,当该值位true时,即为:
     * 追加模式.
     * 文件原数据保留,通过该流写的数据会被追加到文件末尾
     * FileOutputStream fos = new FileOutputStream("./demo/fos.txt",true);追加写操作
     */
    FileOutputStream fos = new FileOutputStream("./demo/fos.txt");
    String line = "是谁带来,一片白云";
    byte[] data = line.getBytes("UTF-8");
    fos.write(data);
    fos.close();
读操作
    /*
     * FileInputStream读操作
     */
    byte[] data = new byte[1024];
    int len = fis.read(data);
    String str = new String(data, 0, len,"UTF-8");
复制功能
    /*
     * 步骤:
     * 1:创建文件输入流用于读取源文件
     * 2:创建文件输出流用于写复制文件
     * 3:顺序从源文件读取字节并复制入到复制文件中完成复制操作
     */
    //从源文件读FileInputStream
    FileInputStream fis = new FileInputStream("./IO/movie.mp4");
    //写到目标文件中FileOutputStream
    FileOutputStream fos = new FileOutputStream("./IO/movie_cpio.mp4");
    byte[] data = new byte[1024];
    int len = -1;
    while((len = fis.read(data)) != -1){
        fos.write(data,0,len);
    }
    fis.close();
    fos.close();


高级流(处理流)


再IO操作中,通常我们会再低级流上链接高级流,这样当数据流经过这些高级流时,他们乐意对数据进行相应 处理加工,可以简化我们对数据的相关操作,而这个过程,称之为流链接操作.
缓冲流BUFFER
缓冲流是一对高级流,作用是提高读写效率.
缓冲流内部维护一个数组,无论我们做随机读写还是块读写操作,最终都会流经缓冲流时改变为块读写操作,从而提高读写效率.

FileInputStream fis = new FileInputStream("./IO/movieIO.avi");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("./IO/movieIO_cp.avi");
BufferedOutputStream bos = new BufferedOutputStream(fos);
long start = System.currentTimeMillis();
int b = -1;
while((b = bis.read()) != -1) {
    bos.write(b);
}
long end = System.currentTimeMillis();
System.out.println("complete:" + (end - start) + "ms");
/*
 * 关闭流时,只需要关闭最外层的高级流即可
 */
bis.close();
bos.close();


关闭流的时候关闭最外层的高级流就可以
及时性需要即使flush(),效率不需要
flush()
close()之前会默认flush(),但是flush()操作需要根据实际情况来判断是否需要手动调用,例如QQ聊天时,就需要手动flush()
缓冲流的flush方法用于强制将缓冲区中刚已经缓存的数据进行一次性写出.频繁调用flush会降低些效率,但是能保证写数据的及时性.


对象流OBJECT


java.io.ObjectOutputStream--对象输出流
java.io.ObjectInputStream---对象输入流
对象流时一对高级流,使用他们可以很方便的进行Java中任何对象的读写操作
当一个类希望被对象流进行读写,那么该类必须实现java.io.Serializable接口
写==对象序列化+持久化
   

 /*
     * 将person对象写入文件"person.obj"
     */
    FileOutputStream fos = new FileOutputStream("./demo/person.obj");
    /*
     * 为方便写出对象,链接对象输出流
     */
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    /*
     * 对象输出流提供的方法:
     * void writeObject()
     * 该方法用于将给定对象转化为一组字节后写出
     * 需要注意:写出的对象必须实现接口:Serializable
     * 该接口没有任何抽象方法,这种接口称为:*签名接口*
     * 虽然再源码中不需要重写方法,但实际上编译器再编译该类为class文件时
     * 会根据当前类结构添加一个方法,用于将当前类实例转换为一组字节
     * 否则会抛出异常java.io.NotSerializableException
     */
    oos.writeObject(person);//Person类必须实现serializable接口
    oos.close();
读==对象的反序列化
    FileInputStream fis = new FileInputStream("./demo/person.obj");
    ObjectInputStream ois = new ObjectInputStream(fis);
    /*
     * 对象流读取的字节必须是对象输出流将一个对象
     * 转换的一组字节,否则读取过程会抛出类没有找到的异常:
     * ClassNotFoundException
     */
    Person person = (Person) ois.readObject();//Object-->Person类型强转
    System.out.println(person);
    ois.close();


对象序列化


将给定的对象转化为一组字节


数据的持久化


将字节写入到文件中


对象反序列化


将一组字节还原为对象的过程
transient:
当一个属性被改关键字修饰后,那么当该类的某个实例被序列化的时候,这个值会被忽略,那么在对象反序泪花时也不回得到该值.忽略某些不重要的属性可以达到对象"瘦身"操作.减少资源消耗
serialVersionUID
当一个类实现了Serializable接口后,编译器会提示我们应该添加一个常量:serialVersionUID
序列化版本号影响着反序列化的结果.当对象输入流在反序列化一个实例会检查该实例于其所属的类的版本号是否一致,不一致则反序列化会抛出版本号不一致的异常.
若一致则成功进行反序列化.自行维护版本号可以主动确定反序泪花的结果.但是若不指定序列化版本号,编译器在便宜当前类时会根据当前类的结构生成一个版本号,但是只要当前类发生改变,则版本号一定会改变!


字符流OSW


java按照读写的数据单位将流划分为两大类:
字节流,字符流
字节流是以字节为单位读写数据的流,由于计算机底层都是2进制,所以字节流可以读任意数据
字符流是以字符为单位读写数据的流,实际底层还是读写字节但是字符流回自动将字节与字符进行对应的转换工作,因此,字符流天生具有字符编解码功能,对此字符流也仅仅适用于读写文本数据
java.io.Reader,java.io.Writer他们是所有字符输入流与字符输出流的超类.规定了读写字符的相关方法.


转换流OSW\ISR

 

java.io.InputStreamReader和java.io.OutputStreamWriter
它们是字符流常用的一对实现类,同时也是一对高级流,在流链接中起到非常重要额一环,承上启下,衔接字节流与其他字符流使用(因为低级流通常都是字节流,而读写字符时我们回使用功能更多的字符高级流,而字符流通常只能链接其他字符流).

/*写*/
FileOutputStream fos = new FileOutputStream("./demo/osw.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
osw.write("我们一起学猫叫``````");
osw.write("喵喵喵");
osw.close();
/*读*/
FileInputStream fis = new FileInputStream("./demo/osw.txt");
InputStreamReader isr= new InputStreamReader(fis, "UTF-8");
int b = -1 ;
/*
 * 字符流提供的读取字符的操作:
 * int read()
 * 该方法回依次读取一个字符,具体实际读取了多少个字节取决于指定的字符集以及对应的字符(字符流回自行判定).
 * 读取字符后还是以int形式返回,若该值为-1依然表示流读取到了末尾.否则该数据表示的就是读取到的对应字符
 * ,转化为char即可.
 */
while((b = isr.read())!=-1){
    char c = (char)b;
    System.out.print(c);
}
isr.close();


PrintWriter

 

java.io.PrintWriter
具有自动行刷新的缓冲字符输出流,特点时可以按行写出字符串,并且可以自动行刷新
java.io.BufferedWriter时缓冲字符输出流,内部有缓冲区可以进行块写操作提高效率,而PrintWriter就是通过链接他实现缓冲功能(PW的很多构造方法内部自动连接它)

/*
 * PW支持两个直接对文件写操作的构造方法:
 * PrintWriter(File f)
 * PrintWriter(String filePath)
 * 以上两种构造方法都支持一个重载,就是再传入一个参数允许我们指定写出字符时的字符集
 */
PrintWriter pw = new PrintWriter("./demo/pw.txt");
pw.println("护花使者--李克勤");
pw.println("这晚在街中偶遇心中的她");
pw.println("两脚决定不听叫唤跟她归家");
pw.close();


/*使用链接形式向文件中写字符串*/
    PrintWriter pw = new PrintWriter(
            new BufferedWriter(
                    new OutputStreamWriter(
                            new FileOutputStream("./demo/pw2.txt"),"UTF-8")
                    )
            );
PrintWriter pw = new PrintWriter(io,true);加上true后,调用
当创建PW时第一个参数为一个流时,那么久可以再传入一个boolean值类型的参数,若该值为true那么当前PW就具备自动行刷新功能,即每当调用println()方法时写出一行字符后就回自动flush()
使用自动行刷新可以提高数据的及时性,但是由于会提高写出次数,必然会导致写效率降低
缓冲字符输入流BufferedReader
java.io.BufferedReader
特点:可以按行读取字符串

FileInputStream fis = new FileInputStream("./src/IO/BRDemo.java");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
/*
 * String readLine()
 * 连续读取若干字符,知道读取了换行符为止,然后将换行符之前的所有字符组成一个字符串返回,
 * 注意返回的字符串中不包含最后读取到的换行符.
 * 当读取到末尾,则返回null
 */
String line = null;
while((line = br.readLine()) != null){
    System.out.println(line);
}
br.close();

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值