黑马程序员_<<字节流(含子类)和字节缓冲流(InputStream,OutputStream,BufferedInputStream,BufferedOutputStream)>>

时间:2023-02-16 17:55:56

--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------


1.字节流

字符流:Writer,Reader 主要是用来操作的是文本文件

字节流:InputStream,OutputStream主要是用来操作的是媒体文件,例如:图片,音乐,电影…等。但是也可以操作文件。

 

如果用字符流操作媒体文件的话,复制文件的话:也能复制,只是复制后的图片不能看,因为查看的编码是不一样的,

不管是读还是写,都不需要刷新缓冲,除非用到了缓冲对象。

2. FileOutStream

     操作文件,向文本文件中写入数据,其没有写入字符串耳朵方法,有字节数组的写入,所以我们要把字符串转换成数组。然后写入。

 

 

importjava.io.FileNotFoundException;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.OutputStream;

public classOutStreamDemo {
public static void main(String[]args) {
OutputStream out=null;
try {
out=new FileOutputStream("F:\\demo.txt");
out.write("helloworld".getBytes());//写入数据,把字符串转换为字节数组
} catch (IOException e) {
e.printStackTrace();
}finally{
if(out!=null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

}


3.     FileInputStream

读取文件,有三种方法,

第一种:一个一个字符的读取,

第二种:字节数组的读取。

第三种:使用available()方法,读取到文件的总大小,然后定义相同大小的字节数组,读取一次即可,但是加入文件过大,大于了虚拟的内存的大小,那么就会加载不进去,所以最好的办法是定义恰当合适的数组,然后循环读取。
 

          1.  单个字节读取

使用的read()方法,进行循环读取。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamDemo {
public static void main(String[] args) {
InputStream in = null;
try {
in = new FileInputStream("F:\\demo.txt");
/* 这个为一个一个的读取,使用read()方法,然后读取到的字符的ASCII码,到结尾就返回-1*/
int r = -1;
while ((r = in.read()) != -1) {//开始读取
System.out.print((char) r);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(in!=null){
try {
in.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

}


         2.  字节数组读取

定义恰当的数组,然后循环读取 使用的read(byte [] b)
然后转换成字符串,返回。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamDemo {
public static void main(String[] args) {
InputStream in= null;
try {
in= new FileInputStream("F:\\demo.txt");
/* 使用字节数组读取,然后转成字符串。到结尾就返回-1*/
byte [] b=new byte[1024];
int len=-1;
while ((len = in.read(b)) != -1) {//开始读取
System.out.print(new String(b,0,len));
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(in!=null){
try {
in.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

}


 

           3.  固定数组大小

使用的available()方法,读取到文件的大小,然后定义相应的大小的字节数组,如果文件小的话,可以这样使用,但是文件很大,超过了虚拟机的申请的内存,那么就会导致加载不进入,所以最好的方法是是哟第二种方法,定义合适的字节数组的大小。
 

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputStreamDemo {
public static void main(String[] args) {
InputStream in = null;
try {
in = new FileInputStream("F:\\demo.txt");
/* 使用字节数组读取,数组的大小用:available()方法定,然后转成字符串。到结尾就返回-1 */
byte[] b = new byte[in.available()];
int len = in.read(b);
System.out.print(new String(b, 0,len));

} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();// 关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

}


 

4. 复制图片

     使用的InputStream和OutputStream

     步骤:

     1.使用读取流InputStream,与要读取的图片关联。

     2.定义写入流,定义好复制到的位置和图片的名称。

     3.然后一边读取一边写入,循环读取和循环写入。使用的是数组读取和写入。

     4.最后关闭流。

   扩展:复制后的文件名称可以改变也可以不变,格式也可以改变,jpg或者bmp.或者其他的格式都可以

 

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class OutAndInputStreamDemo {
public static void main(String[] args) {
InputStream in = null;// 读取流字节流
OutputStream out = null;// 写入流字节流
try {
in = new FileInputStream("F:\\A\\1.jpg");// 与复制的图片关联起来
out = new FileOutputStream("F:\\B\\1.bmp");// 与复制到的目的关联起来,这里的图片的名称可以与原来的相同,也可以不一样
byte[] b = new byte[1024];// 定义字节数组,并指定长度
int l = -1;
while ((l = in.read(b)) != -1) {// 读取
out.write(b, 0, l);// 写入,读多少写入多少,所以用 write(b,0,len)
}
System.out.println("复制成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();// 关闭读取流
} catch (IOException e) {
System.out.println("读取流关闭失败");
}
if (out != null) {
try {
out.close();// 关闭写入流
} catch (IOException e) {
System.out.println("写入流关闭失败");
}
}
}

}
}

}
结果:
复制成功


5. 字节流的缓冲

      字符流:Writer,Reader

             BufferedWriter和BufferedReader

字节流:InputStream,OutputStream体文

                    BufferedInputStream和BufferedOutputStream

 

字节流的缓冲和字符流的花冲使用方法是类似的,用的对象是BufferedInputStream和BufferedOutputStream,他们增强了字节流的读取和写入效率。

         1.  利用缓冲对象复制MP3文件

 

package www.fuxi.IO;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedStreamDemo {
public static void main(String[] args) {
BufferedInputStream bis = null;// 读取缓冲流
BufferedOutputStream bos = null;// 写入缓冲流
try {
bis = new BufferedInputStream(new FileInputStream("F:\\A\\1.mp3"));// 要复制的MP3文件
bos = new BufferedOutputStream(new FileOutputStream("F:\\B\\1.mp3"));// 复制到的目的地
byte[] b = new byte[1024];
int len = 0;
while ((len = bis.read(b)) != -1) {// 读取
bos.write(b, 0, len);// 写入
}
System.out.println("复制成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();// 关闭读取缓冲对象流
} catch (IOException e) {
e.printStackTrace();
}
if (bos != null) {
try {
bos.close();// 关闭写入缓冲对象流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

}
结果:
复制成功


         2.  模拟读取缓冲区

 黑马程序员_<<字节流(含子类)和字节缓冲流(InputStream,OutputStream,BufferedInputStream,BufferedOutputStream)>>

import java.io.IOException;
import java.io.InputStream;

public class MyBufferedInputStream {
privateInputStream in = null;
private intcount = 0;// 计数器
private intpos = 0;// 指针
private byte[]bu = new byte[1024];// 封装的字节数组

publicMyBufferedInputStream(InputStream in) {
this.in =in;
}

public intMyRead() throws IOException {

if (count== 0) {// 说明此时缓冲区中没有数据,可能是缓冲区中还没有开始读取,或者是缓冲区中数据读取完毕
count= in.read(bu);// 向缓冲区中读取数据
if(count < 0) {
return-1;// 这里返回的是int类型的-1
}
pos=0;//每次把指针都初始化
byteb = bu[pos];
count--;//计数器减一
pos++;//指针加一
returnb & 0xff;// 这里b是byte类型,自动提升为整形,但是前面补充的是全是1,为了防止当读取道德byte数据为11111111时,&上0xff,那么使前面的是0,那么这样额可以是原数据不变,又能避免字节数据是-1的情况

} elseif(count>0){
byteb = bu[pos];
count--;//计数器减一
pos++;//指针加一
returnb & 0xff;// 这里b是byte类型,自动提升为整形,但是前面补充的是全是1,为了防止当读取道德byte数据为11111111时,&上0xff,那么使前面的是0,那么这样额可以是原数据不变,又能避免字节数据是-1的情况
}
return-1;
}

public voidmyClose() throws IOException {
in.close();
}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
*测试类,也是复制MP3*/
public class BufferedStreamDemo {
public static void main(String[] args) {
MyBufferedInputStream bis = null;// 读取缓冲流
BufferedOutputStream bos = null;// 写入缓冲流
try {
bis = new MyBufferedInputStream(new FileInputStream("F:\\A\\1.mp3"));// 要复制的MP3文件
bos = new BufferedOutputStream(new FileOutputStream("F:\\B\\1.mp3"));// 复制到的目的地
// byte[] b = new byte[1024];
int r = 0;
while ((r = bis.MyRead()) != -1) {// 读取
bos.write(r);// 写入
}
System.out.println("复制成功");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.myClose();// 关闭读取缓冲对象流
} catch (IOException e) {
e.printStackTrace();
}
if (bos != null) {
try {
bos.close();// 关闭写入缓冲对象流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

}

结果:复制成功


 

注意点:在MyRead()方法中return 返回的必须写b&0xff,因为这样byte类型的提升为整形后,可以保证原数据保持不变,把原来的数据前面相当于添加的0.

例如:

byte  : 11111111  这是-1

自动提升为整形后的数据是

        1111111111111111 11111111 11111111 此时这是-1

那么当byte类型的数据是八个1的时候,那么直接返回b,那么提升为整形后是四个八个1,那么还是-1,所以程序直接结束,读取完毕,解决方法是,要是在前面补充的是全是0的话,那么原数据不变没这样也避免的读取-1的情况。

      1111111111111111 11111111 11111111

&     00000000 00000000 00000000 11111111 这是255,

-----------------------------------------------------------------

      0000000000000000 00000000 11111111

 

所以这样结果就是我们想要的数据,既避免了读取byte是11111111的缺点,同时还保证了原数据不变。

Read方法是byte类型的提升,从1个字节提升为整形为四个字节。Write方法是把4个字节变成了1个字节,值去最后的一个字节。所以复制后的文件的大小和原来的大小一下,而不是其4倍的大小。

6. 键盘读取

  

   import java.io.IOException;
import java.io.InputStream;

public class ClassDemo {
public static void main(String[] args) throws IOException {
/*
* InputStream in“标准”输入流:读取的设备是键盘 PrintStream out“标准”输出流。输出到控制台
*/
/*
* 我们可以循环输入,当输入为over时候,结束输入
*/
InputStream in = System.in;
StringBuilder bu= new StringBuilder();
while (true) {
int ch = in.read();
if (ch == '\r')
continue;
if (ch == '\n') {
String s = bu.toString();
if ("over".equals(s))// 如果输入的是over,那么结束输入
break;
System.out.println("输入的内容是:" + s);
bu.delete(0,bu.length());
} else
bu.append((char) ch);
}

}

}
结果:
aa
输入的内容是:aa
bb
输入的内容是:bb
cc
输入的内容是:cc
over

 


--------------------ASP.Net+Android+IOS开发.Net培训、期待与您交流! --------------------