java中字节流与字符流的区别
字节流
在I/O类库中,java.io.InputStream和java.io.OutputStream分别表示字节输入流和字节输出流,它们都是抽象类,不能实例化,数据流中的最小单位是字节,所以叫做字节流。
一、InputStream中的读取数据的方法如下:
1 、int read()
功能:读取一个字节的数据,并且返回读到得数据,如果返回-1,则表示读到输入流的末尾。
2、int read(byte[] b)
功能:从输入流中读取一定量的字节,并将其存储在字节数组b中,返回实际读取的字节数,如果返回-1,则表示读到输入流的末尾。
3、int read(byte[] b, int off, int len)
功能:将数据读入一个字节数组,同时返回读取的实际字节数,如果返回-1,则表示读到输入流的末尾。off指定在数组b中存放数据的起始偏移位置,len指定读取的最大字节数。
4、available()
功能:返回此输入流下一个方法调用可以不受阻塞地从此输入流读取或跳过的估计字节数。
5、close()
功能:关闭输入流,释放这个流的相关资源。
二、OutputStream中写入数据的方法如下:
1 、int write(int b)
功能:将b的最低的一个字节写入此输入流,其他三个字节丢弃。
2、int write(byte[] b)
功能:将指定的字节数组b写入此输入流。
3、int write(byte[] b, int off, int len)
功能:将指定byte数组中从偏移量off开始的len个字节写入输入流。
4、flush()
功能:刷新此输入流并强制写出所有缓冲的输出字节数。
5、close()
功能:关闭输出流,释放这个流的相关资源。
字符流
是以字符为单位进行IO操作的,一个字符为两个字节,最大的两个父类为Writer和Reader这两个抽象类。
当就字节流与字符流抽象类中的方法来看其实方法名,返回值类型等都很相似,只是在传入参数部分字节流的write()方法需要传入的是字节数组字符流的write()方法需要传入的是字符数组(String也算字符数组?)
但是我们都知道字符数组和字节数组是很容易通过getBytes()和new String()来互换的
字节流和字符流的主要区别是什么呢?
一.字节流在操作时不会用到缓冲区(内存),是直接对文件本身进行操作的。而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。
二.在硬盘上的所有文件都是以字节形式存在的(图片,声音,视频),而字符值在内存中才会形成。
解析:
针对第一点,
如果一个程序频繁对一个资源进行IO操作,效率会非常低。此时,通过缓冲区,先把需要操作的数据暂时放入内存中,以后直接从内存中读取数据,则可以避免多次的IO操作,提高效率
针对第二点,
真正存储和传输数据时都是以字节为单位的,字符只是存在与内存当中的,所以,字节流适用范围更为宽广
三.注意: 字符流其实是通过转换流变化为字节流再进行IO操作
我们知道Reader和Writer都是抽象类,要进行具体的操作,都需要通过多态,利用具体实现的类中具体实现的方法进行操作
package com.lw.InputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* 将一张图片拷贝到另外一个地方。 */ public class Demo3 { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub copeImage(); } public static void copeImage() throws IOException{ //一遍读取一遍写入。 //无论你是是使用的输出流还是输入流,操作的一定是文件。 //1.读取数据 //输入字节流 //1.找到需要复制的图片 File file = new File("D:\\images\\01.jpg"); // NotFoundException FileInputStream inputStream = new FileInputStream(file); File file1 = new File("D:\\01.jpg"); FileOutputStream outputStream = new FileOutputStream(file1); byte[] b = new byte[1024]; //int count = 0; while(inputStream.read(b)!=-1){ //2.写入数据 //输出字节流 outputStream.write(b); } //关闭流 关闭流的原则: 先开后关 后开的先关。 outputStream.close(); inputStream.close(); } }
1 package com.lw.InputStream; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 public class Demo1 { 8 9 /** 10 * @param args 11 * @throws IOException 12 */ 13 public static void main(String[] args) throws IOException { 14 // TODO Auto-generated method stub 15 16 getFile4(); 17 } 18 19 //方式四:通过创建缓冲区和循环的方式来读取 20 public static void getFile4() throws IOException{ 21 //获取起始时间: 22 long startTime = System.currentTimeMillis(); 23 //1.找目标文件 24 File file = new File("D:\\images\\01.jpg"); 25 //2.建立通道 26 FileInputStream fileInputStream = new FileInputStream(file); 27 //3.创建一个缓冲区 28 //3k 29 byte[] b = new byte[1024]; // 一般写1024倍数 理论上设置的缓冲区越大 读取的效率越高 30 //4.读取数据 31 int count = 0; 32 while((count = fileInputStream.read(b))!=-1){ 33 34 System.out.println(new String(b,0,count)); 35 } 36 //5.关闭资源 37 fileInputStream.close(); 38 //结束时间 39 long endTime = System.currentTimeMillis(); 40 41 System.out.println("所花时间:"+(endTime - startTime));//399 接近20多倍 42 }