目录
2.3.3、FileOutputStream方法write()
2.4.2、FileInputStream的读方法read()
1、I/O流
1.1、什么是I/O流?
当你编辑一个文本文件,忘记了
ctrl+s
,可能文件就白白编辑了。当你电脑上插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里。我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入input
和输出output
,即流向内存是输入流,流出内存的输出流。Java中I/O操作主要是指使用java.io
包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。
1.2、I/O流的分类
根据数据的流向分为:输入流(inputStream)和输出流(outputStream)。
1、输入流 :把数据从
其他设备
上读取到内存
中的流。2、输出流 :把数据从
内存
中写出到其他设备
上的流。格局数据的类型分为:字节流(inputStream&outputStream)和字符流(Reader&Writer)。
1、字节流 :以字节为单位,读写数据的流。字节可以读写所有数据,用记事本打开如果你看不懂,就用字节。
2、字符流 :以字符为单位,读写数据的流。字符一般只操作文本,用记事本打开如果你能看懂,就用字符。
1.3、I/O流向说明
输入:硬盘---->内存
输出:内存---->硬盘
2、字节流
2.1、字节流概述
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,我们要时刻明确,无论使用什么样的流对象,底层传输的始终为二进制数据。即一切皆为字节。字节流下有两个常用的子类,分别是OutputStream(输出流,写操作)、InputStream(输入流,读操作)。
2.2、OutputStream
2.2.1、常用方法
方法名 | 说明 |
---|---|
public abstract void write(int b) | 将指定的字节输出流。 |
public void write(byte[] b) | 将 b.length字节从指定的字节数组写入此输出流。 |
public void write(byte[] b, int off, int len) | 从指定的字节数组写入 len字节,从偏移量 off开始输 |
public void close() | 关闭此输出流并释放与此流相关联的任何系统资源。 |
public void flush() | 刷新此输出流并强制任何缓冲的输出字节被写出。 |
注意事项: close方法,当完成流的操作时,必须调用此方法,释放系统资源。
2.3、FileOutputStream
2.3.1、FileOutputStream构造方法
方法名 | 说明 |
---|---|
public FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文件。 |
public FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件。 |
注意事项:当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。
2.3.2、代码演示
public class FileOutputStreamDemo throws IOException {
public static void main(String[] args) {
// 使用File对象创建流对象
File file = new File("a.txt");
FileOutputStream fos = new FileOutputStream(file);
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("b.txt");
}
}
2.3.3、FileOutputStream方法write()
普通写入,即一个一个写入数据
public class Demo1 {
public static void main(String[] args) throws IOException {
//创建输出流对象
OutputStream o1=new FileOutputStream("a.txt");
//写数据
o1.write(97);//写第一个字节
o1.write(98);//写第二个字节
o1.write(99);//写第三个字节
//释放资源
o1.close();
}
}
写入一个字符串
public class Demo3 {
public static void main(String[] args) throws IOException {
//构造方法传递参数true,可以在文件后面进行追加,不会覆盖掉前面的文件内容
OutputStream o=new FileOutputStream("a.txt",true);
//写入字符串,把字符串先转为字节数组
byte[] bytes="我爱中国".getBytes();
//写入字节数组
o.write(bytes);
//释放资源
o.close();
}
}
指定字符串索引位置写入
public class Demo4 {
public static void main(String[] args) throws IOException {
OutputStream o=new FileOutputStream("a.txt",true);
byte[] bytes="abcde".getBytes();
//第一个参数为字节数组,第二参数为起始索引,第三个参数为截取长度
o.write(bytes,2,2);
o.close();
}
}
2.4、FileInputStream
2.4.1、FileInputStream构造方法
方法名 | 说明 |
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。 |
public class Demo {
public static void main(String[] args) throws IOException {
//使用File对象创建流对象
File file=new File("a.txt");
InputStream in1=new FileInputStream(file);
//使用文件名称创建流对象
InputStream in2=new FileInputStream("a.txt");
}
}
2.4.2、FileInputStream的读方法read()
read
方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1。
三种读数据的方法
public class Demo2 {
public static void main(String[] args) throws IOException {
InputStream i=new FileInputStream("a.txt");
//一个一个的读
int read = i.read();
System.out.println(read);
System.out.println("------------------");
//改进使用while循环方法
int b;
while((b=i.read())!=-1){
System.out.println((char) b);
}
System.out.println("------------------");
//使用字节数组读文件
byte[] bytes=new byte[1024];
//定义变量,来接收长度
int len;
while((len=i.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
//释放资源
i.close();
}
}
2.5、使用字节流完成图片复制
2.5.1、代码演示
public class Demo {
public static void main(String[] args) throws IOException {
//创建流对象
//指定数据源
InputStream in=new FileInputStream("D:\\img.jpg");
//指定目的地
OutputStream o=new FileOutputStream("F:\\img.jpg");
//定义字节数组
byte[] bytes=new byte[1024];
//定义长度
int len;
//循环读取
while((len=in.read(bytes))!=-1){
//写出数据
o.write(bytes,0,len);
o.flush();
}
//关闭资源
in.close();
o.close();
}
}
3、字符流
3.1、Reader
方法名 | 说明 |
---|---|
public void close() | 关闭此流并释放与此流相关联的任何系统资源。 |
public int read() | 从输入流读取一个字符。 |
public int read(char[] cbuf) | 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 |
3.1.1、FileReader类
注意事项:
1、字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。idea中UTF-8。
2、字节缓冲区:一个字节数组,用来临时存储字节数据。
3.1.2、FileReader类构造方法
方法名 | 说明 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给定要读取的File对象。 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称。 |
public class FileReaderDemo throws IOException{
public static void main(String[] args) {
// 使用File对象创建流对象
File file = new File("a.txt");
FileReader fr = new FileReader(file);
// 使用文件名称创建流对象
FileReader fr = new FileReader("b.txt");
}
}
3.1.3、FileReader读取字符方法read()
read
方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1
循环读取
public class Demo1 {
public static void main(String[] args) throws IOException {
Reader reader=new FileReader("a.txt");
//定义变量,接收到读取后返回的ASCII码值
int b;
while((b=reader.read())!=-1){
System.out.println((char)b);
}
reader.close();
}
}
使用字符数组进行读取
public class Demo2 {
public static void main(String[] args) throws IOException {
Reader reader=new FileReader("a.txt");
//定义字符数组
char[] chars=new char[1024];
//定义变量 用来接收长度
int len;
while((len=reader.read(chars))!=-1){
System.out.println(new String(chars,0,len));
}
reader.close();
}
}
3.2、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() | 关闭此流,但要先刷新它。 |
3.2.1、FileWriter类
方法名 | 说明 |
---|---|
FileWriter(File file) | 创建一个新的 FileWriter,给定要读取的File对象。 |
FileWriter(String fileName) | 创建一个新的 FileWriter,给定要读取的文件的名称。 |
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
// 使用File对象创建流对象
File file = new File("a.txt");
FileWriter fw = new FileWriter(file);
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("b.txt");
}
}
3.2.2、FileWriter写数据方法writer()
public class Demo1 {
public static void main(String[] args) throws IOException {
Writer writer=new FileWriter("b.txt");
writer.write("hello");
writer.write(26);
writer.write("world");
writer.close(); //如果不关闭 数据只是保存到缓存区 并未保存到文件
}
}
3.3、flush与close之间的区别
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要
flush
方法了。
flush:
刷新缓冲区,流对象可以继续使用。
close:
先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
面试题:close()和flush()的区别?
1、close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。
2、flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。