1. IO流概述和分类
- IO流概述
- IO:输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流本质是数据传输
- IO流就是用来处理设备间数据传输问题的
- 常见的应用:文件复制;文件上传;文件下载等
- IO流的分类
-
按照数据的流向
- 输入流:读数据
- 输出流:写数据
-
按照数据类型来分
- 字节流
- 字节输入流;字节输出流
- 字符流
- 字符输入流;字符输出流
- 字节流
一般情况下,IO流的分类是按照数据类型来分的
- 字节流和字符流在什么情况下使用
- 吐过数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就是用字符流;否则使用字节流。如果不知道用那种类型的流,就是用字节流。
2.字节流写数据
- 字节流抽象基类
-
InputeStream
:这个抽象类是表示字节输入流的所有类的超类。 -
OutputStream
:这个抽象类是表示字节输出流的所有类的超类。 -
子类名特点:子类名称都是以其父类名作为子类名的后缀
- 字节流写数据
-
FileOutputStream:
文件输出流用于将数据写入File -
FileOutputStream(String name):
创建文件输出流以指定的名称写入文件
- 使用字节输出写数据的步骤
- 创建字节流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
- 调用字节输出流对象的写数据方法
- 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
package study01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
- `FileOutputStream:`文件输出流用于将数据写入File
- `FileOutputStream(String name):`创建文件输出流以指定的名称写入文件
*/
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("Stuay01\\fos.txt");
/*- 做了三件事:
- ①:调用系统功能创建了文件
- ②:创建了字节输出流对象
- ③:让字节输出流对象指向创建好的文件*/
//void write(int b):将指定的字节写入此文件输出流
fileOutputStream.write(89);
fileOutputStream.write(55);
fileOutputStream.write(57);
// 所有和IO相关的操作最后都要释放资源
// void close():关闭此文件输出流并释放与此流相关联的任何系统资源
fileOutputStream.close();
}
}
3. 字节流写数据的3中方式
-
构造方法
FileOutputStream(String name):
创建文件输出流以指定的名称写入文件------一般用它FileOutStream(File file)
:创建文件输出流以写入指定的File对象表示的文件
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流,一次写一个字节数据 |
void write(byte[] b) | 将b.length 长度的字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 |
void write(byte[] b,int off,int len) | 将长度为len 的字节从指定的字节数组开始,从偏移量off 开始写入此文件输出流,一次写一个字节数组的部分数据。 |
- 案例
package study01;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*1. 构造方法(两种方式效果相同)
- `FileOutputStream(String name):`创建文件输出流以指定的名称写入文件------一般用它
- `FileOutStream(File file)`:创建文件输出流以写入指定的File对象表示的文件
| 方法名 | 说明
| `void write(int b)` | 将指定的字节写入此文件输出流,一次写一个字节数据
| `void write(byte[] b)` | 将`b.length`长度的字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
| `void write(byte[] b,int off,int len)` | 将长度为`len`的字节从指定的字节数组开始,从偏移量`off`开始写入此文件输出流,一次写一个字节数组的部分数据。
*/
public class FileOutputStreamDemo01 {
public static void main(String[] args) throws IOException {
//创建字节流输出对象
FileOutputStream fox = new FileOutputStream("Stuay01\\fos1.txt");
/*// | `void write(int b)` | 将指定的字节写入此文件输出流,一次写一个字节数据
fox.write(97);
fox.write(98);
fox.write(99);
fox.write(100);*/
/*// | `void write(byte[] b)` | 将`b.length`长度的字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
// byte[] bytes = {97,98,99,100};
//byte[] getBytes():返回字符串对应的字节数组
byte[] bytes = "abcde".getBytes();
fox.write(bytes);*/
// | `void write(byte[] b,int off,int len)` | 将长度为`len`的字节从指定的字节数组开始,从偏移量`off`开始写入此文件输出流,一次写一个字节数组的部分数据。
byte[] bytes = "abcde".getBytes();
// fox.write(bytes,0,bytes.length);
fox.write(bytes,1,3);
// 释放资源
fox.close();
}
}
4. 字节流写数据的两个小问题
-
字节流写数据如何实现换行
不同操作系统对换行符的识别是不同的
windows:\r\n
linux:\n
mac:\r
-
字节流写数据如何实现追加写入
public FileOutputStream(File file,
boolean append)
throws FileNotFoundException
创建文件输出流以写入由指定的File
对象表示的文件。 如果第二个参数为true
,则字节将写入文件的末尾而不是开头
package study01;
/*1. 字节流写数据如何实现换行
不同操作系统对换行符的识别是不同的
- `windows:\r\n`
- `linux:\n`
- `mac:\r`
2. 字节流写数据如何实现追加写入
public FileOutputStream(File file, boolean append) throws FileNotFoundException
创建文件输出流以写入由指定的`File`对象表示的文件。 如果第二个参数为`true` ,则字节将写入文件的末尾而不是开头*/
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("Stuay01\\fos2.txt",true);
//写数据
for (int i = 0;i<10;i++){
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
//释放资源
fos.close();
}
}
5. 字节流写数据加异常处理
finally
:在异常处理时提供finally
块来执行所有清除操作。比如说IO流中的释放资源。
特点:被finally
控制的语句一定会执行,除非JVM
退出
try{
可能出现异常的代码;
}catch(异常名 变量名){
异常处理的代码;
}finally{
执行所有清除操作;
}
- 代码示例
package study01;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo03 {
public static void main(String[] args) {
// try {
// FileOutputStream fos = new FileOutputStream("Stuay01\\fos2.txt");
// fos.write("hello".getBytes());
// fos.close();
// } catch (IOException e){
// e.printStackTrace();
// }
//加入finally来实现释放资源
FileOutputStream fos = null;
try {
fos = new FileOutputStream("Stuay01\\fos2.txt");
fos.write("hello".getBytes());
} catch (IOException e){
e.printStackTrace();
}finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
6.字节流读数据(一次读一个字节数据)
-
需求:把文件
fos.txt
中的内容读取出来在控制台输出 -
FileInputStream
:从文件系统中的文件获取输入字节FileInputStream(String name)
:通过打开与实际文件的链接来创建一个FileInputStream
,该文件由文件系统中的路径名name
命名
-
使用字节输入流读数据的步骤:
- 创建字节输入流对象
- 调用字节输入流对象的读数据方法
- 释放资源
-
读数据的方法
方法 | 说明 |
---|---|
int read() | 从该输入流读取一个字节的数据。 当文件中没有数据了读取的返回值为-1 |
int read(byte[] b) | 从该输入流读取最多 b.length 个字节的数据到一个字节数组。 |
int read(byte[] b, int off, int len) | 从该输入流读取最多 len 个字节的数据到字节数组。 |
package Study02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
1. 需求:把文件`fos.txt`中的内容读取出来在控制台输出
2. `FileInputStream`:从文件系统中的文件获取输入字节
- `FileInputStream(String name)`:通过打开与实际文件的链接来创建一个`FileInputStream`,该文件由文件系统中的路径名`name`命名
3. 使用字节输入流读数据的步骤:
- 创建字节输入流对象
- 调用字节输入流对象的读数据方法
- 释放资源
*/
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
//FileInputStream(String name)
FileInputStream fis = new FileInputStream("Stuay01\\fos2.txt");//fos2.txt中的内容为:hello
//调用字节输入流对象的读数据方法
//`int read()`从该输入流读取一个字节的数据。 当文件中没有数据了读取的返回值为-1
/*// 第一次读取数据
int read = fis.read();
System.out.println(read);//104
System.out.println((char) read);//h
//第二次读取数据
read = fis.read();
System.out.println(read);//101
System.out.println((char) read);//e*/
//循环改造读取字节
/*int read = fis.read();
while (read!=-1){
System.out.print((char) read);
read = fis.read();
}*/
//优化上面的代码---字节流读数据的标准代码
int read;
while ((read=fis.read())!=-1){
System.out.print((char) read);
}
//释放资源
fis.close();
}
}
7. 案例:字节流复制文本文件
需求:把D:\\Java\\java.txt
复制到模块目录下的fos2.txt
分析:
①:复制文本文件,其实就是把文本文件的内容从一个文件中读出来(数据源),然后写入另一个文件中(目的地)。
②:数据源:
D:\\Java\\java.txt
——–读数据-------------InputStream
-------FileInputStream
③:目的地
Stuay01\\fos2.txt
--------写数据-------------OutputStream
——-FileOutputStream
思路:
①:根据数据源创建字节输入流对象
②:根据目的地创建字节输出流对象
③:读写数据,赋值文本文件(一次读取一个字节,一次写入一个字节)
④:释放资源
package Study02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*需求:把`D:\\Java\\java.txt`复制到模块目录下的`fos2.txt`
分析:
①:复制文本文件,其实就是把文本文件的内容从一个文件中读出来(数据源),然后写入另一个文件中(目的地)。
②:数据源:
- `D:\\Java\\java.txt`——–读数据-------------`InputStream`-------`FileInputStream`
③:目的地
- `Stuay01\\fos2.txt`--------写数据-------------`OutputStream`——-`FileOutputStream`
思路:
①:根据数据源创建字节输入流对象
②:根据目的地创建字节输出流对象
③:读写数据,赋值文本文件(一次读取一个字节,一次写入一个字节)
④:释放资源
*/
public class FileInputeStreamDemo01 {
public static void main(String[] args) throws IOException {
//①:根据数据源创建字节输入流对象
FileInputStream fis = new FileInputStream("D:\\Java\\java.txt");
//②:根据目的地创建字节输出流对象
FileOutputStream fos = new FileOutputStream("Stuay01\\fos2.txt");
//③:读写数据,赋值文本文件(一次读取一个字节,一次写入一个字节)
int read;
while ((read = fis.read())!=-1){
fos.write(read);
}
//④:释放资源
fis.close();
fos.close();
}
}
8. 字节流读数据(一次读一个字节数组数据)
需求:把文件fos2.txt
中的内容读出来在控制台输出
使用字节输入流读数据的步骤:
①:创建字节输入流对象
②:调用字节输入流对象的读数据方法
③:释放资源
package Study02;
import java.io.FileInputStream;
import java.io.IOException;
/*需求:把文件`fos2.txt`中的内容读出来在控制台输出
使用字节输入流读数据的步骤:
①:创建字节输入流对象
②:调用字节输入流对象的读数据方法
③:释放资源*/
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
//①:创建字节输入流对象
FileInputStream fis = new FileInputStream("Stuay01\\fos2.txt");
//②:调用字节输入流对象的读数据方法
byte[] bytes = new byte[1024];//长度一般为1024或1024的整数倍
int len;
//当长度为-1时代表已经读到了最后
while ((len = fis.read(bytes))!=-1){
//String(byte[] bytes, int offset, int length)
//通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
System.out.print(new String(bytes,0,len));
}
//③:释放资源
fis.close();
}
}
9. 案例:复制图片
需求:把D:\\Java\\ml.png
复制到模块目录下的ml.png
- 思路:
- 根据数据源创建字节输入流对象
- 根据目的地创建字节输出流对象
- 读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
- 释放资源
package Study02;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*需求:把`D:\\Java\\ml.png`复制到模块目录下的`ml.png`
1. 思路:
- 根据数据源创建字节输入流对象
- 根据目的地创建字节输出流对象
- 读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
- 释放资源*/
public class FileInputStreamDemo02 {
public static void main(String[] args) throws IOException {
//根据数据源创建字节输入流对象
FileInputStream fis = new FileInputStream("D:\\\\Java\\\\ml.png");
//根据目的地创建字节输出流对象
FileOutputStream fos = new FileOutputStream("Stuay01\\ml.png");
//读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
byte[] bytes = new byte[1024];
int len;
while ((len = fis.read(bytes))!=-1){
fos.write(bytes,0,len);
}
//释放资源
fis.close();
fos.close();
}
}
10.字节缓冲流
-
字节缓冲流:
BufferedOutputStream
:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。BufferedInputStream
:创建BufferedInputStream
将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节。
-
构造方法
- 字节缓冲输出流:
BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:
BufferedInputStream(InputStream in)
- 字节缓冲输出流:
-
为什么构造方法需要的是字节流,而不是具体的文件或路径呢?
- 字节缓冲流仅仅是提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作。
package Study03;
import java.io.*;
/*1. 字节缓冲流:
- BufferedOutputStream
- BufferedInputStream
2. 构造方法
- 字节缓冲输出流:`BufferedOutputStream(OutputStream out)`
- 字节缓冲输入流:`BufferedInputStream(InputStream in)`
*/
public class BuffereStreamDemo {
public static void main(String[] args) throws IOException {
//- 字节缓冲输出流:`BufferedOutputStream(OutputStream out)`
/*FileOutputStream fos = new FileOutputStream("Stuay01\\bos.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);*/
//--合为一步解决--
/*BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Stuay01\\bos.txt"));
//写数据
bos.write("hello\r\n".getBytes());
bos.write("world\r\n".getBytes());
//释放资源
bos.close();
*/
//- 字节缓冲输入流:`BufferedInputStream(InputStream in)`
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("Stuay01\\bos.txt"));
//读数据
//一次读一个字节数据
/*int by;
while ((by=bis.read())!=-1){
System.out.print((char) by);
}
bis.close();
*/
//一次读一个字节数组数组
byte []bytes = new byte[1024];
int len;
while ((len=bis.read(bytes))!=-1){
System.out.print(new String(bytes,0,len));
}
//释放资源
bis.close();
}
}
11. 案例:复制视频
需求:把D:\\Java\\153_IO流小结.mp4
复制到模块目录下的Stuay01\\153_IO流小结.mp4
思路:
① 根据数据源创建字节输入流对象
② 根据目的地创建字节输出流对象
③ 读写数据,复制视频
④ 释放资源
package Study03;
import java.io.*;
/*需求:把`D:\\Java\\153_IO流小结.mp4`复制到模块目录下的`Stuay01\\153_IO流小结.mp4`
思路:
① 根据数据源创建字节输入流对象
② 根据目的地创建字节输出流对象
③ 读写数据,复制视频
④ 释放资源
1. 四种方式实现复制视频,并记录每种方式复制视频的时间
- 基本字节流一次读写一个字节 花费35530毫秒
- 基本字节流一次读写一个字节数组 花费62毫秒
- 字节缓冲流一次读写一个字节 花费了183毫秒
- 字节缓冲流一次读写一个字节数组 花费了22毫秒
*/
public class BuffereStreamDemo01 {
public static void main(String[] args) throws IOException {
//记录开始时间
long startTime = System.currentTimeMillis();
//读写数据,复制视频
// method1();//基本字节流一次读写一个字节总共花费35530毫秒
// method2();//基本字节流一次读写一个字节数组总共花费了62毫秒
// method3();//字节缓冲流一次读写一个字节总共花费了183毫秒
method4();//字节缓冲流一次读写一个字节数组总共花费了22毫秒
//记录结束时间
long enfTime = System.currentTimeMillis();
System.out.println("总共花费了" + (enfTime - startTime) + "毫秒");
}
//基本字节流一次读写一个字节
public static void method1() throws IOException{
FileInputStream fis1 = new FileInputStream("D:\\Java\\153_IO流小结.mp4");
FileOutputStream fos1 = new FileOutputStream("Stuay01\\\\153_IO流小结.mp4");
int by;
while ((by=fis1.read())!=-1){
fos1.write(by);
}
fis1.close();
fos1.close();
}
//基本字节流一次读写一个字节数组
public static void method2() throws IOException{
FileInputStream fis2 = new FileInputStream("D:\\Java\\153_IO流小结.mp4");
FileOutputStream fos2 = new FileOutputStream("Stuay01\\\\153_IO流小结.mp4");
byte []bytes = new byte[1024];
int len;
while ((len=fis2.read(bytes))!=-1){
fos2.write(bytes,0,len);
}
fis2.close();
fos2.close();
}
//字节缓冲流一次读写一个字节
public static void method3() throws IOException{
BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream("D:\\Java\\153_IO流小结.mp4"));
BufferedOutputStream bos2 = new BufferedOutputStream(new FileOutputStream("Stuay01\\\\153_IO流小结.mp4"));
int by;
while ((by = bis1.read())!=-1){
bos2.write(by);
}
bos2.close();
bis1.close();
}
////字节缓冲流一次读写一个字节数组
public static void method4() throws IOException{
BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream("D:\\Java\\153_IO流小结.mp4"));
BufferedOutputStream bos2 = new BufferedOutputStream(new FileOutputStream("Stuay01\\\\153_IO流小结.mp4"));
byte[]bytes=new byte[1024];
int len;
while ((len = bis2.read(bytes))!=-1){
bos2.write(bytes,0,len);
}
bos2.close();
bis2.close();
}
}