IO流解决程序中的什么问题?
- 把程序中存储在内存中的数据,写入到文件中(持久存储)
- 把磁盘文件中存储的数据,读取到内存中(Java程序)
IO流:
- I流: 把磁盘文件中存储的数据,读取到内存中(读数据)
- O流:把内存中的数据,写入到磁盘文件(写数据)
InputStream:输入流
- 字节输入流
- 字符输入流
OutputStream:输出流
- 字节输出流
- 字符输出流
字节流:万能流(所有类型的文件都可以读写)
字符流:通常用于针对纯文本文件进行读写操作
- 纯文本文件: 使用计算机中的记事本软件打开并看得懂的文件
IO流的作用:对磁盘上的文件进行读、写操作
- 读:输入流
- 写:输出流(把内存中的数据写入到磁盘文件中)
学习所有的IO流有一个固定套路:
第1步:创建
- 实例化不同的IO流类
第2步:操作(写、读)
- 读:read()
- 写:write()
第3步:关闭
- close()
字节输出流
字节输出流:以字节为单位,把内存中数据写入到磁盘文件中
步骤:
1.创建字节输出流对象。注意:如果文件不存在,就创建;如果文件存在就清空
2.写数据。注意:写出的整数,实际写出的是整数在码表上对应的字符
3.释放资源。注意:每次使用完流必须要释放资源
三种方式:
java
void write(int a) 一次写一个字节数据
void write(byte[] a) 一次写一个字节数组数据
void write(byte[] a, int off, int len) 一次写一个字节数组的部分数据
java
import java.io.*;
public class OutputStreamDemo1 {
//字节输出流
public static void main(String[] args) throws IOException {
//创建字节输出流对象
OutputStream os = new FileOutputStream("files/hello.txt");
//操作:写数据
os.write('B');//char类型在底层自动转换为int,通过码表
//关闭
os.close();
}
}
java
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputStreamDemo2 {
public static void main(String[] args) throws IOException {
//创建字节输出流
FileOutputStream os = new FileOutputStream("files/helloworld.txt");
//操作:写数据
// os.write("嗨,你好呀".getBytes());//把字符串转换为字节数据并存储到数组中
byte[] buf = "haihai".getBytes();
os.write(buf,1, 5);//将字节数组中部分数据,写入到文件中
//释放资源
os.close();
}
}
向文件中追加写入数据:(创建字节输出流对象时,不会清空文件中的原有内容)
java
FileOutputStream fos = new FileOutputStream("关联文件" , true );
//第二个参数: true , 表示追加写入数据
向文件中写入:换行符号
java
fos.write("\r\n".getBytes());
java
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputStreamDemo3 {
public static void main(String[] args) throws IOException {
//创建字节输出流对象,并关联文件,表示追加写入
FileOutputStream fos = new FileOutputStream("files/hello.txt",true);
//输出内容
fos.write("hello,nihao".getBytes());
//换行
fos.write("\r\n".getBytes());
//关闭资源
fos.close();
}
}
字节输入流
InputStream(抽象类)
- FileInputStream类(使用到的)
步骤:
1.创建字节输出流对象。注意:如果文件不存在,就直接报错
2.读数据。注意:读出来的是文件中数据的码表值
3.释放资源。注意:每次使用完流必须要释放资源
java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamDemo1 {
public static void main(String[] args) throws IOException {
//创:创建字节输入流对象,并关联文件
//InputStream is = new FileInputStream("files/test.txt");//当关联的文件不存在时:运行时异常
InputStream is = new FileInputStream("files/hello.txt");
//读:读取数据
// int ch = is.read();//读取到A的编码值:97
char ch = (char)is.read();//读取到A的编码值:97,强制转换为char类型
System.out.println(ch);//A
char ch1 = (char)is.read();
System.out.println(ch1);//B
char ch2 = (char)is.read();
System.out.println(ch2);//C
int ch3 = is.read();//读到文件末尾了,(没有数据了)
System.out.println(ch3);
//关:释放资源
is.close();
}
}
文件拷贝案例
文件复制方案:
- 前置:
- 有源文件(读源文件中的数据)
- 有目标文件(向目标文件中写入数据)
- 创建字节输入流,关联源文件
- 创建字节输出流,关联目标文件
- 使用字节输入流,读取源文件中的字节数据
- 把读取到的字节数据,写入到目标文件中
- 循环重复:3、4
- 当源文件读取结束( 结束标记:-1 )
- 释放资源
java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile1{
public static void main(String[] args) throws IOException {
//创建字节输入流,关联源文件(读)
FileInputStream fis = new FileInputStream("C:\\Users\\韦爽\\Documents\\code\\123.jpg");
//创建字节输出流,关联目标文件(写)
FileOutputStream fos = new FileOutputStream("files/images.jpg");
//循环:读数据,写数据
int data = 0;
while((data = fis.read()) != -1){
//把读取的数据写入到目标文件中
fos.write(data);
}
//释放资源
fis.close();
fos.close();
}
}
IO资源处理
try...catch升级版
java
try{
//监视可能会发生异常的代码
}catch(Exception e){
//处理异常
}finally{
//不论是否有异常,都会执行
//应用场景: 释放资源
}
java
有点繁琐
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile1 {
public static void main(String[] args){
FileInputStream fis = null;
FileOutputStream fos = null;
//创建字节输入流,关联源文件(读)
try {
fis = new FileInputStream("C:\\Users\\韦爽\\Documents\\code\\123.jpg");
//创建字节输出流,关联目标文件(写)
fos = new FileOutputStream("files/images.jpg");
//循环:读数据,写数据
int data = 0;
while ((data = fis.read()) != -1) {
//把读取的数据写入到目标文件中
fos.write(data);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//释放资源
try{
if(fos!=null){
fos.close();
}
if(fis!=null){
fis.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
升级版:
JDK1.7版本中IO资源处理代码:
- 好处:自动释放IO资源 ( 不需要在书写close方法 )
- 资源对象想要实现自动释放,必须保证资源对象有实现AutoCloseable接口
java
try( IO流对象; IO流对象; ... ){
//监视可能会发生异常的代码
}catch(Exception e){
//处理异常
}
java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile2 {
public static void main(String[] args){
//创建字节输入流,关联源文件(读) //创建字节输出流,关联目标文件(写)
try(FileInputStream fis = new FileInputStream("C:\\Users\\韦爽\\Documents\\code\\123.jpg");
FileOutputStream fos = new FileOutputStream("files/images.jpg");
) {
//循环:读数据,写数据
int data = 0;
while ((data = fis.read()) != -1) {
//把读取的数据写入到目标文件中
fos.write(data);
}
}catch (IOException e){
//异常处理
e.printStackTrace();
}
// 不用再释放资源
// fis.close();
// fos.close();
}
}
文件复制:
- 方案1:循环一次读写1个字节数据 (程序性能低)
- 方案2:循环一次读写多个字节数据(性能高)
java
//一次读取1个字节数据,返回实际读取到的字节数据;读取到文件末尾时返回:-1
int read()
//一次最多读取buf.length个字节数据,把读取到的字节数据存储到buf数组中,并返回实际读取字节数据的个数
//读取到文件末尾时返回:-1
int read(byte[] buf)
提升性能
一次读取多个数据
java
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
public class InputStreamDemo2 {
//read(byte[] buf)方法使用
public static void main(String[] args) throws IOException {
//创建字节输出流
FileInputStream fis = new FileInputStream("files/helloworld.txt");
//定义字节数组
byte[] buf = new byte[5];
//第一次读取数据
int len = fis.read(buf);
System.out.println("第一次读取数据个数:"+len);//第一次读取数据个数:5
System.out.println("数据为:"+ Arrays.toString(buf));//数据为:[104, 101, 108, 108, 111]
System.out.println(new String(buf,0,len));//hello
//第二次读取数据
len = fis.read(buf);
System.out.println("第二次读取数据:"+ len );//第二次读取数据:5
System.out.println("数据为:"+ Arrays.toString(buf));//数据为:[119, 111, 114, 108, 100]
System.out.println(new String(buf,0,len));//world
//第三次读取数据
len = fis.read(buf);
System.out.println("第三次读取数据:"+ len );//第三次读取数据:1
System.out.println("数据为:"+ Arrays.toString(buf));//数据为:[126, 111, 114, 108, 100]
System.out.println(new String(buf,0,len));//~
//关闭资源
fis.close();
}
}
java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyFile2 {
/*文件复制:
* 需要源文件: 使用字节输入流读文件数据
* 需要目标文件: 使用字节输出流向文件中写入数据
* */
public static void main(String[] args) {
String srcPath = "f:/files/111.jpg";
String destPath = "files/111.jpg"; //必须是目标文件,而不是目标目录
long beginTime = System.currentTimeMillis();
copy(srcPath, destPath);
long endTime = System.currentTimeMillis();
System.out.println("文件复制花费:" + (endTime - beginTime) + "毫秒");//6毫秒
}
/**
* 文件复制 :读多个个字节数据,写入多个个字节数据
*
* @param src 源文件路径
* @param dest 目标文件路径
*/
public static void copy(String src, String dest) {
//循环:读取源文件中的数据,向目标文件中写入数据
//字节输入流,并联源文件
//字节输出流,并联目标文件
try (FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest);
) {
//字节数组
byte[] buf = new byte[1024*8]; //一次读取1K
//读取字节数据的个数
int len = -1;
while ((len = fis.read(buf)) != -1) {
//向目标文件中写入实际读取到的字节数据
fos.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在IO体系下,java提供了高效流(提高读写文件的效率)
- 读文件:BufferedInputStream
- 写文件:BufferedOutputStream
BufferedInputStream流的创建: 读数据
- 自己没有读数据的能力,需要依赖字节输入流实现读数据
java
//构造方法: public BufferedInputStream( InputStream is )
BufferedInputStream bis = new BufferedInputStream( new FileInputStream("关联文件") );
BufferedOutputStream流的创建: 写数据
- 自己没有写数据的能力,需要依赖字节输出流实现读数据
java
//构造方法: public BufferedOutputStream( OutputStream os )
//覆盖写入
BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("关联文件") );
//追加写入 (构造方法的第二个参数为true)
FileOutputStream fos = new FileOutputStream("关联文件" , true); //追加写入
BufferedOutputStream bos = new BufferedOutputStream( fos );//当前流有具有追加写入能力
使用字节缓冲流提高效率
java
import java.io.*;
public class CopyFile {
public static void main(String[] args) {
String srcPath = "C:\\Users\\韦爽\\Documents\\code\\123.jpg";
String destPath = "files/images.jpg"; //必须是目标文件,而不是目标目录
long beginTime = System.currentTimeMillis();
copy(srcPath, destPath);
long endTime = System.currentTimeMillis();
System.out.println("文件复制花费:" + (endTime - beginTime) + "毫秒");//6毫秒
}
/**
* 文件复制 :使用高效流(缓冲流)提高读写能力
*
* @param src 源文件路径
* @param dest 目标文件路径
*/
public static void copy(String src, String dest) {
//循环:读取源文件中的数据,向目标文件中写入数据
//字节输入流,并联源文件
//字节输出流,并联目标文件
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));
) {
//字节数组
byte[] buf = new byte[1024*8]; //一次读取1K
//读取字节数据的个数
int len = -1;
while ((len = bis.read(buf)) != -1) {
//向目标文件中写入实际读取到的字节数据
bos.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}