JAVA之IO流

使用场景 

按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。

节点流

可以从或向一个特定的地方(节点)读写数据。如 FileReader

  • 文件:FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流
  • 数组:ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
  • 字符:StringReader StringWriter 对字符串进行处理的节点流
  • 管道:PipedInputStream PipedOutputStream PipedReader PipedWriter 对管道进行处理的节点流

处理流

是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如 BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

  • 缓冲流:BufferedImputStream BufferedOutputStream BufferedReader BufferedWriter 需要父类作为参数构造,增加缓冲功能,避免频繁读写硬盘,可以初始化缓冲数据的大小,由于带了缓冲功能,所以就写数据的时候需要使用 flush 方法咯
  • 转换流:InputStreamReader OutputStreamWriter 要 InputStream 或 OutputStream 作为参数,实现从字节流到字符流的转换
  • 数据流:DataInputStream DataOutputStream 提供将基础数据类型写入到文件中,或者读取出来,为什么要有这个流呢?看这样的分析,如果没有这种流的话,有一个 long,本身只占 8 个字节,如果我要写入到文件,需要转成字符串,然后在转成字符数组,那空间会占用很多,但是有了这种流之后就很方便了,直接将这 8 个字节写到文件就完了。是不是既节约了内存空间有让程序写起来更加方便简单了呐。写倒是很简单,但是读取的时候就注意了,根据读取的数据类型,指针会往下移,所以你写的顺序必须要和读的顺序一致才能完成你正确的需求

IO流概述和分类

按照数据的流向分为:

输入流:读数据

输出流:写数据

按照数据类型来分:

字节流:字节输入流,字节输出流

字符流:字符输入流,字符输出流

那么这两种流都在什么情况下使用呢?

如果数据通过window自带的记事本软件打开,我们还可以读懂里面的内容,就使用字符流,否则使用字节流。如果你不知道该使用哪种流,就使用字节流。

字节流

 字节流写入的方式:

一次写一个字节

int b;

while((b=fis.read())!=-1)

{

   fos.write(b);

}

效率太慢,改为字节数组方式,

byte[] bytes=new byte[1024];

int len;

while((len=fis.read(bytes))!=-1)

{

fos.write(bytes,0,len);

}

 字节流写入的两个问题:

 1、字节流写数据如何实现换行呢?

  写完数据后,加换行符:

  windows:\r\n

  linux:\n

  mac:\r

2、字节流写数据如何实现追加写入呢?

  public FileOutputStream(String name,boolean append)

 创建文件输出流以指定的名称写入文件,如果第二个参数为true,则字节将写入文件的末尾而不是开头。

字节流写数据加异常处理

FileOutStream fos=null;

try{

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

  fos.write("hello".getBytes());

}catch(IOException e){

   e.printStackTrace();

 }finally{

   if(fos!=null){

   fos.close();

}

}

字节缓冲流

BufferOutputStream:字节缓冲输出流

BufferInputStream:字节缓冲输入流

构造方法 BufferOutputStream(OutputStream out)  BufferInputStream(InputStream in)

字节缓冲流仅仅提供的是缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作

一次读一个字节原理:一次读8192个字节的数据放入缓冲输入流的数组中,然后一个字节一个字节的输出到缓冲输出流的数组中。然后通过write方法将数组中的数据一个字节一个字节写道文件中。

字符流

字符流出现的原因:

由于字节流操作中文不是特别方便,字节流读中文,每次只能读一部分,容易出现乱码,所以java提供字符流

字符流=字节流+编码表

字节流复制文本文件时,文本文件也会有中文,但是没有问题,原因是最终底层操作会自动进行

字节拼接成中文,如何识别中文的呢?汉字在存储时,无论选择哪种编码存储,第一个字节都是负数。

一个汉字存储,如果是gbk编码,占用2个字节

如果是utf-8编码,占用3个字节

写数据方法 写一个字符write(int c), 写出一个字符数组write(char[] buff),写一个字符串 write(String str),写一个字符数组的一部分 write(char[] buff,int off,int len),写字符串的一部分 write(String str,int off,int len)

flush()和close()的区别,flush是刷新流,执行完后还能继续执行写操作。close()执行后也会执行刷新流,但是不能继续执行写操作。

读方法 一次读一个字符 

int ch;

while((ch=fr.read())!=-1)

{

  System.out.println((char)ch);

}

一次读多个字符

char[] chars=new char[1024];

int len;

while((len=fr.read(chars))!=-1)

{

  System.out.println(new String(chars,0,len));

}

编码表

基础知识:计算机中存储的信息都是用二进制数表示的,我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果

按照某种规则,把字符存储到计算机中,称之为编码,反之将存储在计算机中的二进制数按照某种规则解析显示出来,称之为解码。这里强调一下:按照A编码存储,必须按照A编码解析出来,这样才能显示正确的文本符号。否则就会导致乱码的出现。字符编码:就是一套自然语言的字符与二进制数之间的对应规则

转换流

InputStreamReader是从字节流到字符流的桥梁,它读取字节,并使用指定的charset将其解码为字符。

OutputStreamWriter是从字符流到字节流的桥梁,使用指定的charset将写入的字符编码为字节。

对象序列化流

对象序列化就是将对象保存到磁盘中,或者在网络中传输对象,这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息。反之,该字节序列还可以从文件中读取出来,重构对象,对他进行反序列化。

对象序列化流:ObjectOutputStream,对象需要实现Serializable,它是一个标记接口,实现该接口不需要重写任何方法。

对象反序列化流:ObjectInputStream

标准输入流 System.in,通常该流对应于键盘输入

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

写起来太麻烦,于是换SCanner sc=new SCanner(System.in)

标准输出流 System.out,通常该流对应于显示输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值