学习真的是忘了学,学了忘的过程,学的好多东西都忘了,又要重新复习,好在之前都有做较为详细的笔记,可以及时的拿来复习,如果没有做笔记,转而再去听视频,会很浪费时间,听视频效果也没有看笔记效果好,而且更节省时间,所以关于这个IO流的总结,我会写的尽量的详细,以便后来进行复习。
文章目录
1. 什么是流?
- 流的概念:
java的IO流是实现输入输出的基础,可以方便的实现数据的输入和输出操作。
在java中把不同的输入输出源(键盘,文件,网络连接等)抽象的表述为流
。
通过流的方式允许java程序使用相同的方式来访问不同的输入和输出源。 - 流的分类:
输入流:能够从中读取数据的设备
输出流:能够向其写入数据的设备 - 如何区分输入流和输出流???
这是一个很容易搞混的问题,划分输入流和输出流是从内存的角度来划分的。
比如这张图,从内存的角度,内存向硬盘(输出流)写入数据
再比如这张图,站在内存的角度来看,左边是从输入流中读取数据到内存,右边是向输出流中写入数据。 - 输入流和输出流
输入流:InputStream和Reader
输出流:OutputStream和Writer
以上四个类都是抽象类,不可实例化,需要子类继承他们。
2. 字节文件输出流(FileOutputStream)
-
什么是字节文件输出流??
所谓的字节文件输出流,就是指将字节数据从内存中写入文件中 -
字节文件输出流的构造方法:
(1)创建一个向指定 File 对象表示的文件中写入数据的文件输出流:
public FileOutputStream(File file)
(2)创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处:
public FileOutputStream(File file, boolean append)
(3)创建一个向具有指定名称的文件中写入数据的输出文件流:
public FileOutputStream(String name)
(4)创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处:
public FileOutputStream(String name,boolean append)
注意:并且写入文件不需要文件已经存在。如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,则抛出 FileNotFoundException。 -
字节文件输出流的常用方法:
(1)将 b.length 个字节从指定 byte 数组写入此文件输出流中:
public void write(byte[] b)
(2)将指定字节写入此文件输出流。
public void write(int b)
(3)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流
public void write(byte[] b,int off,int len)
(4)关闭此文件输出流并释放与此流有关的所有系统资源。此文件输出流不能再用于写入字节
public void close()
注意:以上的四个方法均为覆盖 OutputStream 的中的方法
例1:向文件fos.txt中写入数据hello,io
public class FileOutputStreamDemo
{
public static void main(String[] args) throws IOException, IOException {
//创建字节输出流对象
//public FileOutputStream(String name)
FileOutputStream fos = new FileOutputStream("fos.txt");
//将数据写入到文件输出流中
//write(byte[] b)
//先把字符串转为字节数组,因为字节输出流只能写入字节数组或者单个字节
fos.write("hello,io".getBytes());
//释放资源
//关闭此文件输出流并释放与此流有关的所有系统资源
fos.close();
}
}
分析:
- 在创建字节文件输出流时,文件可以不存在,如果文件不存在,就会在项目的根目录下自动创建一个文件
- 需要注意的是,对于字节文件输出流,他的
write()
方法参数里面的传入参数的都是字节数据,需要将字符数据转成字节数据才能写入到输出流中。 - 使用完流以后,一定要关闭流,释放资源
例2:在例1的基础上,仍然向fos.txt文件中写入数据
public class FileOutputStreamDemo1
{
public static void main(String[] args) throws IOException
{
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
//write(int b)一次写入一个字节数据
fos.write(97);
//write(byte[] b)一次写入一个字节数组
byte[] bys = {97,98,99,100,101};
fos.write(bys);
//write(byte[] b,int off,int len)一次写入一个字节数组,并且指定字节数组的长度
fos.write(bys, 1, 3);
//释放资源
fos.close();
}
}
分析:可以看到再次向文件中写入数据时,就会将文件中之前的数据覆盖掉
例3:在例1的基础上向fos.txt文件中追加写入数据
这个时候,使用构造方法public FileOutputStream(String name,boolean append)
public class FileOutputStreamDemo2
{
public static void main(String[] args) throws IOException
{
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
//write(byte[] b)一次写入一个字节数组
byte[] bys = {97,98,99,100,101};
fos.write(bys,1,3);
//释放资源
fos.close();
}
}
3. 字符文件输出流(FileWriter)
-
什么是字符文件输出流??
简单讲,字符文件输出流就是将字符数据写入到输出流中
它是用来写入字符文件的便捷类,使用默认字符编码集进行编码,默认的缓冲区大小,要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。(这个原因会在下个知识点中讲解) -
字符文件输出流的构造方法:
(1)根据给定的 File 对象构造一个 FileWriter 对象:
public FileWriter(File file)
(2)根据给定的 File 对象构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
public FileWriter(File file,boolean append)
(3)根据给定的文件名构造一个 FileWriter 对象。
public FileWriter(String fileName)
(4)根据给定的文件名构造一个 FileWriter 对象。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
public FileWriter(String fileName,boolean append)
注意:如果指定文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开它,会抛出IOException。并且使用构造方法创建的是流对象,可以向这个流中写入数据。没有流对象是没有流的。 -
字符文件输出流的常用方法:
(1)写入单个字符:
public void write(int c)
(2)写入字符数组的某一部分:
public void write(char[] cbuf,int off,int len)
(3)写入字符串的某一部分:
public void write(String str, int off,int len)
(4)刷新该流的缓冲:
public abstract void flush()
(5)关闭此流,但要先刷新它:
public abstract void close()
注意:对于字符输出流,因为电脑中文件中的数据都是以字节的形式保存的,而字符占用两个字节,所以进不到文件中而是在缓冲区中,需要刷新一下,也就是说,每写入一次数据都要刷新一下才能把数据从缓冲区刷新到文件中,但是如果觉得麻烦,可以在最后使用close()方法,因为close()方法调用时默认先刷新。
例1:向文件demo.txt中写入数据
public class FileWriterDemo
{
public static void main(String[] args) throws IOException {
/*
* 如果文件不存在,则会自动创建
* 如果文件存在,则会被覆盖
*/
//创建一个可以往文件中写入字符数据的字符输出流对象
FileWriter fw = new FileWriter("demo.txt");
//将字符数据写入到临时存储缓冲区中
fw.write("henghengaijianghui");
//进行刷新,将数据直接写入到文件中
fw.flush();
//关闭流,关闭资源
fw.close();
}
}
分析:
- 首先需要创建一个流对象,用来向这个流中写入数据
- 对于字符数据不会直接写入文件中,而是先保存在缓冲区中,再刷新到文件中。
- 对于字符文件输出流,可以直接向里面写入字符数据,比较方便。
例2:使用带追加写入的构造方法创建流对象
public class FileWriterDemo1
{
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) throws IOException
{
//使用构造方法实现对文件的追加续写
FileWriter fw = new FileWriter("demo.txt",true);
fw.write("henghengai"+LINE_SEPARATOR+"jianghui");
fw.close();
}
}
4. 转换流(OutputStreamWriter)
-
什么是转换流??
OutputStreamWriter是字符流通向字节流的桥梁:可以使用指定的编码集将要写入的字符编码为字节
,他所指定的编码集可以由名称指定或者显示的指定,否则将使用平台默认的编码集。 -
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。
为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。 -
通过FileWriter进一步理解转换流的作用:
FileWriter继承了OutputStreamWriter:
转换流OutputStreamWriter将字符数据转换为字节数据,然后将其写入到文件中,而这个转换流就可以指定字符编码方式,
FileWriter相当于使用了默认的字符编码方式即UTF-8,将字符数据转换为字节数据写入文件中。 如果,不想使用UTF-8,就需要使用转换流,将要写入的字符数据转换为字节数据,写入到文件中。 -
OutputStreamWriter的构造方法:
(1)创建使用指定字符集的OutputStreamWriter:
public OutputStreamWriter(OutputStream out,String charsetName)
(2)创建使用默认字符编码的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out)
-
OutputStreamWriter的常用方法:
(1)写入字符数组的某一部分:
public void write(char[] cbuf,int off,int len)
(2)写入字符串的某一部分:
public void write(String str,int off, int len)
(3)写入单个字符:
public void write(int c)
例1:向文件中写入中文字符:指定字符编码方式为GBK
public class OutputStreamWriterDemo
{
public static void main(String[] args) throws IOException
{
//指定使用GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"GBK");
osw.write("中国");
osw.close();
}
}
分析:
- 要写入的数据为字符数据,“中国”
- 如果我们想使用默认的编码方式将“中国”这两个字写入文件中,可以使用FileWriter
- 如果我们不想使用默认的编码方式,可以使用转换流指定编码方式,将“中国”这两个字写入到文件中
例2 :向文件中写入中文字符:指定字符编码方式为UTF-8
public class OutputStreamWriterDemo1
{
public static void main(String[] args) throws IOException
{
//指定使用GBK
OutputStreamWriter osw =
new OutputStreamWriter(new FileOutputStream("osw.txt"),"UTF-8");
osw.write("中国");
osw.close();
}
}
5. 字节输出缓冲流(BufferedOutputStream)
- 什么是缓冲流?
实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统,可以提高效率。 - 构造方法:
创建一个新的缓冲输出流,以将数据写入指定的底层输出流:
public BufferedOutputStream(OutputStream out)
- 方法:
(1)将指定的字节写入此缓冲的输出流:
public void write(int b)
(2)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流:
public void write(byte[] b, int off, int len)
(3)刷新此缓冲的输出流。这迫使所有缓冲的输出字节被写出到底层输出流中:
public void flush()
注意:一般来说,将给定数组的字节存入此流的缓冲区中,根据需要将该缓冲区刷新,并转到底层输出流。
例1:利用缓冲流将字节数据写入到文件中
public class BufferedOutputStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("bos.txt"));
//写数据
bos.write("hello".getBytes());
//释放资源
bos.close();
}
}
6. 字符输出缓冲流(BufferedWriter)
- 作用:
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。 - 构造方法:
创建一个使用默认大小输出缓冲区的缓冲字符输出流:
public BufferedWriter(Writer out)
- 方法:
(1)写入单个字符。
public void write(int c)
(2)写入字符数组的某一部分。
public void write(char[] cbuf, int off, int len)
(3)写入字符串的某一部分。
public void write(String s, int off,int len)
(4)刷新该流的缓冲。
public void flush()
(5)写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 (’\n’) 符。
public void newLine()
例1:使用字符输出缓冲流向文件中写入数据
public class BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个文件输出流
FileWriter fw = new FileWriter("buffered.txt");
//为了提高写入的效率,使用字符流缓冲区
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区的写入方法,将数据先写入到缓冲区中
bufw.write("abdskkdk");
//使用缓冲区的刷新方法将数据刷新到目的地中
bufw.flush();
//关闭缓冲区
bufw.close();
}
}
例2:使用平台默认的换行方法对输入的数据进行换行
public class BufferedWriterDemo2
{
public static void main(String[] args) throws IOException
{
FileWriter fw = new FileWriter("buffered.txt");
BufferedWriter bufw = new BufferedWriter(fw);
for(int x=1;x<=4;x++)
{
bufw.write("abcdef"+x);
//字符输出流加入缓冲区之后,有平台自身的换行方法
bufw.newLine();
bufw.flush();
}
//关闭缓冲区
bufw.close();
}
}
来源:CSDN
作者:茶花女-
链接:https://blog.csdn.net/qq_42764468/article/details/103650975