黑马程序员 Java基础之IO流<二>IO流概述及InputStream字节流

来源:互联网 发布:sql server 2005介绍 编辑:程序博客网 时间:2024/05/16 06:29

-----------android培训java培训、java学习型技术博客、期待与您交流! ------------

<>IO

 

一、IO流:即Input Output的缩写。数据流是一串连续不断的数据的集合,就像水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流.

数据写入程序可以使一段一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流.

二、特点:

1IO流用来处理设备间的数据传输。

2Java对数据的操作是通过流的方式。

3Java用于操作流的对象都在IO包中。

4)流按操作数据分为两种:字节流和字符流。

5)流按流向分为:输入流和输出流。

注意:流只能操作数据,而不能操作文件。

三、IO流的常用基类:

1)字节流的抽象基流:InputStreamOutputStream

2)字符流的抽象基流:ReaderWriter

注:此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能;如InputStream子类FileInputStreamReader子类FileReader

所有流都继承于以下四种抽象流类型的某一种:(抽象流)

 

 

.字节流与字符流区别

二者仅仅是操作单位不一样。

InputStreamReader所有输入流的基类,他们都是抽象类,本身不能创建实例,但是他们是所有输入流的模板。

一般来说处理字符或字符串时使用字符流,处理字节或二进制对象时应使用字节流

备注:字符流必须关闭资源,因为它中间有缓冲区!而字节流不需要!但是一般都会(最后)关闭资源!

 

字节流

字节流主要是操作byte(字节)的类型数据:

字节输出流:OutputStream

字节输入流:InputStream

 

字符流

Java中的字符是Unicode编码,是双字节的,1个字符等于 2个字节;

使用字节来处理字符文本就不太方便了,此时可以考虑使用字符流;

字符流主要是操作char的类型数据:

字符输出流:Writer

字符输入流:Reader

 

字节流和字符流在使用上的代码结构都是非常类似的,但是其内部本身也是有区别的,因为在进行字符流操作的时候会使用到缓冲区(内存中),而字节流操作的时候是不会使用到缓冲区的。

在输出的时候,OutputStream类即使最后没有关闭内容也可以输出。但是如果是Writer的话,则如果不关闭,最后一条内容是无法输出的,因为所有的内容都是保存在了缓冲区之中,每当调用了close()方法就意味着清空缓冲区了。那么可以证明字符流确实使用了缓冲区:

字节流:程序文件

字符流:程序缓冲区(内存中)文件

 

如果现在字符流即使不关闭也可以完成输出的话,则必须强制性清空缓冲区:

方法:public void flush() throws IOException

我的总结:

两者相比,肯定使用字节流更加的方便,而且在程序中像图片、MP3等都是采用字节的方式的保存,那么肯定字节流会比字符流使用的更广泛。

但是需要说明的是,但是如果要是想操作中文的话,字符流肯定是最好使的。(字节流的话可能会出现乱码(一个汉字分成了两份)!)

 

<>字节流

一、概述:

1、字节流和字符流的原理是相似的,只不过字节流可以对媒体进行操作。

2、由于媒体数据中都是以字节存储的,所以,字节流对象可直接对媒体进行操作,而不用再进行刷流动作。

3、读写字节流:InputStream     --->  输入流(读)

                              OutputStream  --->  输出流(写)

4、为何不用进行刷流动作:

     因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。可直接将字节写入到指定文件中,但是需要在写代码的时候,如果有字符串,要将字符串转为字节数组再进行操作。

5、特有方法:

      int available() --->  放回数据字节的长度,包含终止符

在定义字节数组长度的时候,可以用到这个方法:byte[] = new byte[fos.available()]  fos为字节流对象)

但是,对于这个方法要慎用,如果字节过大(几个G),那么如此大的数组就会损坏内存,超过jvm所承受的大小(指定内存为64M)。

二、拷贝文件例子:

1、思路:

1)用字节流读取流对象和媒体文件相关联

2)用字节写入流对象,创建一个媒体文件,用于存储获取到的媒体文件数据

3)通过循环读写,完成数据的存储

4)关闭资源

Ex.

import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class FileInputStreamDemo2 {public static void main(String[] args) throws IOException {File file=new File("templist//fis.txt");if(!file.exists()){file.createNewFile();}FileInputStream fis=new FileInputStream(file);byte[] buf=new byte[1024];int len=0;while((len=fis.read(buf))!=-1){System.out.println(new String(buf,0,len));}fis.close();}}01.import java.io.*;  class CopyPic  {      public static void main(String[] args)      {          //创建流对象引用           FileOutputStream fos = null;          FileInputStream fis = null;          try{              //创建读写流对象               fos = new FileOutputStream("2.gif");              fis = new FileInputStream("1.gif");              int len = 0;              //定义字节数组,存储读取的字节流               byte[] arr = new byte[1024];              //循环读写流,完成数据存储               while((len=fis.read(arr))!=-1){                  fos.write(arr,0,len);             }          }catch (IOException e){              throw new RuntimeException("复制图片失败");          }          //最终关闭资源           finally{              if(fos!=null){                 try{                      fos.close();                  }catch (IOException e){                      throw new RuntimeException("写入流关闭失败");                 }              }              if(fos!=null){                  try{                      fis.close();                  }catch (IOException e){                      throw new RuntimeException("读取流关闭失败");                  }                     }          }      }  }

三、字节流缓冲区:

1、读写特点:

read():会将字节byte型值提升为int型值

write():会将int型强转为byte型,即保留二进制数的最后八位。

2、原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。

1)先从数据中抓取固定数组长度的字节,存入定义的数组中,再通过然后再通过read()方法读取数组中的元素,存入缓冲区

2)循环这个动作,知道最后取出一组数据存入数组,可能数组并未填满,同样也取出包含的元素

3)每次取出的时候,都有一个指针在移动,取到数组结尾就自动回到数组头部,这样指针在自增

4)取出的时候,数组中的元素再减少,取出一个,就减少一个,直到减到0即数组取完

5)到了文件的结尾处,存入最后一组数据,当取完数组中的元素,就会减少到0,这是全部数据就取完了

3、示意图:

4、自定义字节流缓冲区:

思路:
1
、定义一个固定长度的数组
2
、定义一个指针和计数器用于读取数组长度,和计数数组元素是否取完为0
3
、每次将字节数据存入元素要先将数组中的元素取完


注:取出的是byte型,返回的是int型,这里存在提升的动作,
byte中的八位全为1的时候是byte-1,提升为int类型,就变为int型的-1,,read循环条件就结束了
变为-1的原因是由于在提升时,将byte的八位前都补的是1,即32位的数都是1,即为int型的-1了。
如何保证提升后的最后八位仍为1呢?就需要将前24位补0,就可以保留原字节数据不变,又可以避免转为int型出现-1的情况;
那么要如何做呢?
这就需要将提升为int的数据和前24位为0,后八位仍为原字节数据的这个值做与运算。即和255做与运算即可

import java.io.*;  class MyBufferedInputStream  {      private InputStream in;      byte[] by = new byte[1024*4];     private int pos=0,count=0;     //传入加强的类       MyBufferedInputStream(InputStream in)     {          this.in = in;      }      //自定义读取方法      public int myRead()throws IOException      {          //先判断计数器           if(count==0)          {              //计数器为0则存入数据              count = in.read(by);              //计数器为负则返回-1,说明结束数据读取              if(count<0)                 return -1;              //每次从数组中读取数据完,指针要归零,重新移动指针               pos = 0;              //获取存入数组的元素,并需要让指针和计数器相应变化              byte b = by[pos];              count--;              pos++;             //返回读取的值,需要与运算               return b&255;          }         //计数器大于零时,不需要存数据,只需读取          else if(count>0)          {              byte b = by[pos];             count--;              pos++;              return b&0xff;         }         //为-1时即到数据结尾          return -1;     }     public void myClose()throws IOException      {          in.close();      }  }
0 0
原创粉丝点击