IO<字节流>FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream

来源:互联网 发布:windows 7刷机 编辑:程序博客网 时间:2024/04/29 01:25

字节流

基类InputStream:此抽象类是表示字节输入流的所有 类的超类。

  OutputStream:此抽象类是表示输出字节流的所 有类的超类,输出流接受输出字节并将这些字节发 送到某个接收器。

字节输入流的特有方法available(),估计输入流要读取的字节数,在读取小文件时,使用此方法可以定义合适的数组长度,不用再循环的读取。但是当文件较大时,不建议使用,因为文件过大,会爆出内存溢出异常,此时还是建议定义数组长度时,定义为1024的整数倍。

程序演示:

public class FileStream {

public static void main(String[] args) {

FileInputStream fis=null;//创建字节流输入对象

FileOutputStream fos=null;//创建字节流输出对象

//初始化字节流输出对象,并创建目的文件

try {

fos=new FileOutputStream("D:\\Test3.java");

fis=new FileInputStream("D:\\Test1.java");

//使用输入字节流中的特有方法available定义刚刚好的数组长度,不用再循环读取和写入

byte[] buf=new byte[fis.available()];

fis.read(buf);

fos.write(buf);

catch (IOException e) {

e.printStackTrace();

}

}

}

练习:复制一个图片。

思路:1、用字节读取流对象和图片关联

          2、用字节写入流对象创建一个图片文件,用于存储  获取到的图片数据。

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

           4、关闭资源。

  程序:

public class FileStream {

public static void main(String[] args) {

FileInputStream fis=null;//创建字节流输入对象

FileOutputStream fos=null;//创建字节流输出对象

try {

//初始化字节流输出对象,并创建目的文件

fos=new FileOutputStream("D:\\2.jpg");

//初始化字节流输入对象,并关联要操作的文件

fis=new FileInputStream("D:\\1.jpg");

//定义字节型数组,存放读取的字节数据

byte[] buf=new byte[1024];

int len=0;

while((len=fis.read(buf))!=-1){

fos.write(buf);//将读取存放在数组中的字节数据写入到目的文件中

}

catch (IOException e) {

e.printStackTrace();

}finally{

if(fis!=null)

try {

fis.close();

catch (IOException e) {

e.printStackTrace();

}

if(fos!=null)

try {

fos.close();

catch (IOException e) {

e.printStackTrace();

}

}

}

}

字节流的缓冲区:

演示MP3的复制,通过缓冲区

思路:1、创建字节输入流缓冲区对象,传入字节输入流对象,并关联要操作的MP3文件

   2、创建字节输出流缓冲区对象,传入字节输出流对象,并创建一个MP3文件,用于存储读取的数据

   3、循环读写MP3文件

   4、关闭缓冲资源

程序:

public static void CopMp3(){

BufferedInputStream bufis=null;//创建字节输入流缓冲对象

BufferedOutputStream bufos=null;//创建字节输出流缓冲对象

try {

//初始化字节输入流缓冲对象

bufis=new BufferedInputStream(new FileInputStream("d:\\1.mp3"));

//初始化字节流输出缓冲对象

bufos=new BufferedOutputStream(new FileOutputStream("d:\\2.mp3"));

int by=0;

while((by=bufis.read())!=-1){//读取一个字节

bufos.write(by);//将读取的字节数据通过缓冲区写入目的文件

}

catch (IOException e) {

e.printStackTrace();

}finally{

if(bufos!=null)

try {

bufos.close();

catch (IOException e) {

e.printStackTrace();

}

if(bufis!=null)

try {

bufis.close();

catch (IOException e) {

e.printStackTrace();

}

}

}

自定义字节流的缓冲区

1、通过缓冲区复制文件,每次向目标文件中写入的数据,都是从缓冲区(数组中)获取的,而缓冲区中的数据,是通过调用流对象从硬盘中获取的,所以自定义缓冲区,首先要有流对象。

2、然后通过流对象的read方法从硬盘中读取数据,存放到数组中,并且用计数器,计算数组中数据的个数,根据指针读取数组中的数据,每读取一个数据,指针向前移动一个,计数器自动减1.直到所有读取完毕,当计数器为0时,再次从硬盘中获取数据,然后重复读取数组中数据的步骤

3、当计数器的值为-1时,表示硬盘及数组中的所有数据读取完毕。

程序演示:

public class MyBufferedInputStream {

private InputStream in;

private byte[] buf=new byte[1024];

private int pos=0;

private int count=0;//用于计数,数组中存放的字

public MyBufferedInputStream(InputStream in){

this.in=in;

}

//一次读一个字节,从缓冲区(字节数组中)获取

public int myRead() throws IOException{//返回值为int是为了避免读取到的8个二进制位都是1,这样可能会出现文件读取不完整,

//所以返回int,提升用32位存储8位,在多余位补0,保证了原字节数据不变,又避免了-1的出现

//通过in对象,从硬盘上读取数据,并存储在by中

if(count==0)

{

count=in.read(buf);//当数组中的字节数为0时,再次从硬盘中读取数据

if(count<0)//当从硬盘中读取到的是-1时,数据读取完毕,返回-1

return -1;

pos=0;//数组中的数据读取完毕,再次从数组中读取新的数据

byte b=buf[pos];

count--;//读取一个字节,数组中的字节数-1

pos++;//将指针指向要读取的下一个字节

return b&255;//&255是实现在空位补0,

}else if(count>0){//在数组中字节数据没有读取完时,继续读取

byte b=buf[pos];

count--;

pos++;

return b&255;

}

return -1;

}

public void myClose() throws IOException{

in.close();

}

}

总结:myRead方法的返回值类型是int型,这样是为了避免-1的出现,

即将读取的字节类型数据提升并在空位补0(由返回值与255实现),而write方法在写入数据时,

由于接受的是int型数据,而实际数据应该是一个字节,所以在写的过程中write方法对数据进行了强转,

保证了原字节数据的不变。

 

0 0