1.1什么是IO
在Java中I/O操作主要是指用java.io
包下的内容,进行输入和输出操作。输入也叫读取操作,输出也叫作写出数据。以内存为基准,分为输入input
和输出output
1.2IO的分类
根据数据的流向分为:输入流和输出流
-
输入流:把数据从其他设备上读取到内存中的流。
-
输出流:把数据从内存中写到其他设备上的流。
根据数据的类型分为:字节流和字符流
-
字节流:以字节为单位,读写数据的流。
-
字符流:以字符为单位,读写数据的流。
输入流 输出流 字节流 InputStream 字节输入流 OutputStream<br/>字节输出流 字符流 Reader 字符输入流 Writer 字符输出流 以上类都是抽象类,我们平时使用的是各抽象类的子类。
2.1字节流
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存。比如右击一个文档文件,再点击属性,就是显示出这个文件的字节大小。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。
字节输出流【OutputStream】抽象类
java.io.OutputStream
抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
-
public void close()
:关闭此输出流并释放与此流相关联的任何系统资源。 -
public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出。 -
public void write(byte[] b)
:将 b.length字节从指定的字节数组写入此输出流。 -
public void write(byte[] b, int off, int len)
:从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 -
public abstract void write(int b)
:将指定的字节输出流。
FileOutputStream类
OutputStream
有很多子类,我们从最简单的一个子类开始。
java.io.FileOutputStream
类是文件输出流,用于将数据写出到文件。
构造方法
-
public FileOutputStream(File file)
:创建文件输出流以写入由指定的 File对象表示的文件。 -
public FileOutputStream(String name)
: 创建文件输出流以指定的名称写入文件。
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。
<span style="color:#333333"> //创建FileOutputStream对象,构造方法中绑定要写入数据的目的地
FileOutputStream fos = new FileOutputStream(new File("09_IOAndProperties\\b.txt"));
//调用FileOutputStream对象中的方法write,把数据写入到文件中
//在文件中显示100,写个字节
fos.write(49);
fos.write(48);
fos.write(48);
/*
public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
一次写多个字节:
如果写的第一个字节是正数(0-127),那么显示的时候会查询ASCII表
如果写的第一个字节是负数,那第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)
*/
byte[] bytes = {65,66,67,68,69};//ABCDE
//byte[] bytes = {-65,-66,-67,68,69};//烤紻E
fos.write(bytes);
/*
public void write(byte[] b, int off, int len) :把字节数组的一部分写入到文件中
int off:数组的开始索引
int len:写几个字节
*/
fos.write(bytes,1,2);//BC
/*
写入字符的方法:可以使用String类中的方法把字符串,转换为字节数组
byte[] getBytes() 把字符串转换为字节数组
*/
byte[] bytes2 = "你好".getBytes();
System.out.println(Arrays.toString(bytes2));//[-28, -67, -96, -27, -91, -67]
fos.write(bytes2);
//释放资源
fos.close();
</span>
字节输入流【InputStream】抽象类
java.io.InputStream
抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
-
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。 -
public abstract int read()
: 从输入流读取数据的下一个字节。 -
public int read(byte[] b)
: 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
FileInputStream类
java.io.FileInputStream
类是文件输入流,从文件中读取字节。
构造方法
-
FileInputStream(File file)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 -
FileInputStream(String name)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException
。
<span style="color:#333333">public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("D:\\b.txt");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if(fis!=null){
fis.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}</span>
3.1字符流
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
字符输入流【Reader】抽象类
java.io.Reader
抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
-
public void close()
:关闭此流并释放与此流相关联的任何系统资源。 -
public int read()
: 从输入流读取一个字符。 -
public int read(char[] cbuf)
: 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
FileReader类
-
FileReader(File file)
: 创建一个新的 FileReader ,给定要读取的File对象。 -
FileReader(String fileName)
: 创建一个新的 FileReader ,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。
FileInputStream is = null;
try {
is = new FileInputStream("D:\\b.txt");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1) {
System.out.println((char) len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符输出流【Writer】
java.io.Writer
抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
-
void write(int c)
写入单个字符。 -
void write(char[] cbuf)
写入字符数组。 -
abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分,off数组的开始索引,len写的字符个数。 -
void write(String str)
写入字符串。 -
void write(String str, int off, int len)
写入字符串的某一部分,off字符串的开始索引,len写的字符个数。 -
void flush()
刷新该流的缓冲。 -
void close()
关闭此流,但要先刷新它。FileWriter类
java.io.FileWriter
类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。构造方法
-
FileWriter(File file)
: 创建一个新的 FileWriter,给定要读取的File对象。 -
FileWriter(String fileName)
: 创建一个新的 FileWriter,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
-
FileWriter fw = null;
try {
fw = new FileWriter("D:\\b.txt");
fw.write(97);
//a
fw.write(65);
//A
fw.write('a');
fw.write('b');
fw.flush();
//字符数组
char[]chars="梁明明".toCharArray();
fw.write(chars);
//字符串
String string = "只为超越";
fw.write(string);
fw.write("\r\n");
//换行
fw.write(string,2,2);
//索引从2开始,长度两个,超越
} catch (IOException e) {
e.printStackTrace();
}
finally {
try{
if(fw!=null){
fw.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush
方法了。
-
flush
:刷新缓冲区,流对象可以继续使用。 -
close
:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了
即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。