Java基础知识点总结(二) 关于字节流字符流,缓冲字节流字符流
????目录
文章目录
????关于字节流和字符流的区别
什么是流?
Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列。和水流一样,Java中的流也具有一个“流动的方向”,通常可以从中读入一个字节序列的对象被称为输入流;能够向其写入一个字节序列的对象被称为输出流。
实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。
例子
下面以两个写文件的操作为主进行比较,但是在操作时字节流和字符流的操作完成之后都不关闭输出流。
范例:使用字节流不关闭执行
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("复习\\test.txt");
byte[] bytes = {97,98,99,100};
fos.write(bytes);
}
文本内的数据:
此时没有关闭字节流操作,但是文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的。而下面继续使用字符流完成,再观察效果。
范例:使用字符流不关闭执行
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("复习\\test.txt"));
osw.write("abcd");
}
程序运行结果:
程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而 在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。
提问:什么叫缓冲区?
在很多地方都碰到缓冲区这个名词,那么到底什么是缓冲区?又有什么作用呢?
回答:缓冲区可以简单地理解为一段内存区域。
可以简单地把缓冲区理解为一段特殊的内存。
某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。
在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。
如果想在不关闭时也可以将字符流的内容全部输出,则可以使用Writer类中的flush()方法完成。
范例:刷新缓冲区
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("复习\\test.txt"));
osw.write("abcd");
osw.flush();
}
程序运行结果:
此时,文件中已经存在了内容,更进一步证明内容是保存在缓冲区的。这一点在读者日后的开发中要特别引起注意。
????各种流
JDK文档简介
InputStream
public abstract class InputStream extends Object implements Closeable
这这个抽象类是表示输入字节流的所有类的超类。
一些InputStream的直接子类
AudioInputStream , ByteArrayInputStream , FileInputStream , FilterInputStream , InputStream , ObjectInputStream , PipedInputStream , SequenceInputStream , StringBufferInputStream
这里我们通常使用FileInputStream。
OutputStream
public abstract class OutputStream extends Object implements Closeable, Flushable
这个抽象类是表示字节输出流的所有类的超类。输出流接收输出字节并将其发送到某个接收器。
需要定义OutputStream
子类的应用程序必须至少提供一个写入一个字节输出的方法。
一些OutputStream的直接子类
ByteArrayOutputStream , FileOutputStream , FilterOutputStream , ObjectOutputStream , OutputStream , PipedOutputStream
这里我们通常使用FileOutputStream。
????字节流(FileInputStream&FileOutputStream)
public class FileInputStream extends InputStream
public class FileOutputStream extends OutputStream
构造方法
FileInputStream:
FileOutputStream:
构造方法使用例子
FileInputStream fis = new FileInputStream("复习\\test.txt");
FileOutputStream fos = new FileOutputStream("复习\\test2.txt");
常用方法
FileInputStream:
OutputStream:
综合运用例子
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("复习\\test.txt");
FileOutputStream fos = new FileOutputStream("复习\\test2.txt");
byte[] bytes = new byte[1024]; //一次读取一个字节数组
int len;
while ((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len); //一次写入一个字节数组
}
System.out.println("ok");
fis.close();
fos.close();
}
????字节缓冲流(BufferedInputStream&BufferedOutputStream)
**BufferedInputStream:**A BufferedInputStream为另一个输入流添加了功能,即缓冲输入并支持mark和reset方法的功能。 创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。 mark操作会记住输入流中的一个点,并且reset操作会导致从最近的mark操作读取的所有字节在从包含的输入流中取出新字节之前重新读取。
**BufferedOutputStream:**该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
构造方法
BufferedInputStream:
BufferedOutputStream:
构造方法使用例子
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("复习\\test.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("复习\\test2.txt"));
常用方法
BufferedInputStream:
BufferedOutputStream:
综合运用例子
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("复习\\test.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("复习\\test2.txt"));
byte[] bytes = new byte[1024];
int len;
while ((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.close();
bis.close();
}
????关于字节流和字节缓冲流的效率大比拼
我们使用字节流的一次读取一个字节和一次读取一个字节数组,以及字节缓冲流的一次读取一个字节和一次读取一个字节数组去复制视频,看看哪一个的效率最高!
代码实现
import java.io.*;
public class BufStrDemo02 {
public static void main(String[] args) throws IOException {
long startTime = System.currentTimeMillis();
// method1();//time is :7495
// method2();//time is :12
// method3();//time is :58
method4();//time is :4
long endTime = System.currentTimeMillis();
System.out.println("time is :"+(endTime-startTime) );
}
// 字节缓冲流一次读写一个字节数组
public static void method4() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\OBS\\1.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myBufferStream\\03.mp4"));
byte[] bys = new byte[1024];
int by;
while((by = bis.read(bys))!=-1) {
bos.write(bys,0,by);
}
bos.close();
bis.close();
}
// 字节缓冲流一次读写一个字节
public static void method3() throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\OBS\\1.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myBufferStream\\03.mp4"));
int by;
while((by = bis.read())!=-1) {
bos.write(by);
}
bos.close();
bis.close();
}
// 基本字节流一次读一个字节数组
public static void method2() throws IOException {
FileInputStream fis = new FileInputStream("D:\\OBS\\1.mp4");
FileOutputStream fos = new FileOutputStream("myBufferStream\\02.mp4");
byte[] bys = new byte[1024];
int len;
while((len = fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
// 基本字节流一次读一个字节
public static void method1() throws IOException {
FileInputStream fis = new FileInputStream("D:\\OBS\\1.mp4");
FileOutputStream fos = new FileOutputStream("myBufferStream\\01.mp4");
int by;
while ((by = fis.read())!=-1){
fos.write(by);
}
fos.close();
fis.close();
}
}
以上字节缓冲流一次读写一个字节数组的效率是最高的!!!!
????字符流(InputStreamReader&OutputStreamWriter)
InputStreamReader:InputStreamReader是从字节流到字符流的桥梁:它读取字节,并使用指定的charset
将其解码为字符。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。 为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。
为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
OutputStreamWriter:OutputStreamWriter是从字符流到字节流的桥梁:使用指定的charset
将写入的字符编码为字节。它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
每次调用write()方法都会使编码转换器在给定的字符上被调用。 所得到的字节在写入底层输出流之前累积在缓冲区中。 请注意,传递给write()方法的字符不会缓冲。
为了最大的效率,请考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用。 例如:
Writer out = new BufferedWriter(new OutputStreamWriter(System.out));
构造方法
InputStreamReader:
OutputStreamWriter:
构造方法使用例子
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("复习\\test.txt"));
InputStreamReader isw = new InputStreamReader(new FileInputStream("复习\\test.txt"));
常用方法
InputStreamReader:
OutputStreamWriter:
综合运用例子:
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("复习\\test.txt"));
InputStreamReader isw = new InputStreamReader(new FileInputStream("复习\\test.txt"));
osw.write("jajjajaajajajjsdfnsdfkl ");
osw.close();
char[] chars = new char[1024];
int len;
while ((len = isw.read(chars)) != -1) {
System.out.println(new String(chars,0,len));
}
isw.close();
}
????字符缓冲流(BufferedReader&BufferedWriter)
构造方法例子
BufferedReader br = new BufferedReader(new FileReader("复习\\test.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("复习\\test.txt"));
综合使用方法
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("myBufferStream\\test.txt"));
for(int i=0;i<10;i++){
bw.write("hello"+i);
bw.newLine();
bw.flush();
}
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("myBufferStream\\test.txt"));
// readline不包含换行符
String line;
while ((line = br.readLine())!=null){
System.out.println(line);
}