4 字节流
- 字节流抽象基类
- InputStream:这个抽象类是表示字节输入流的所有类的超类
- OutputStream:这个抽象类是表示字节输出流的所有类的超类
- 子类名特点:子类名称都是以其父类名作为子类名的后缀
4.1 IO流概述和分类
- IO流概述:
- IO: 输入/输出(Input/Output)
- 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输
- IO流就是用来处理设备间数据传输问题的
- 常见的应用:文件复制;文件上传;文件下载
IO流分类
-
按照数据的流向
- 输入流:读数据
- 输出流:写数据
-
按照数据类型来分(重点)
- 字节流:字节输入流;字节输出流
- 字符流:字符输入流:字符输出流
-
一般情况, IO流的分类是按照数据类型来分的
-
那么这两种流都在什么情况下使用呢?
- 如果数据通过Window自带的记事本软件打开, 我们还可以读懂里面的内容,就使用字符流,否则使用字节流。
- 如果你不知道该使用哪种类型的流,就使用字节流
4.2 字节输出流(写数据)
-
父类:
OutputStream
(抽象类) -
子类:
FileOutputStream
;文件输出流用于将数据写入文件 -
使用字节输出流写数据的步骤:
- 1、创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件):
FileOutputStream(String name)
,(name表示文件路径) - 2、调用字节输出流对象的写数据方法:
void write(int b)
- 3、释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源):
void close()
- 1、创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件):
-
范例
package test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//1,创建字节输出流对象
FileOutputStream fos = new FileOutputStream("E:\\test\\fos.txt");
/*做了三件事情:
1:调用系统功能创建了文件
2:创建了字节输出流对象
3:让字节输出流对象指向创建好的文件*/
//2,写数据
fos.write(97); //a
//3,最后都到释放资源
fos.close();
}
}
4.2.1 字节输出流构造方法和常用方法
- 构造方法
方法名 | 说明 |
---|---|
FileOutputStream(String name)(推荐) | 创建文件输出流以指定名称写入文件 |
FileOutputStream(File file) | 创建文件输出流写入以指定的 File对象表示的文件 |
public FileOutputStream(String file,boolean append) | 创建一个追加数据的字节输出流管道通向目标文件路径(如果第二个参数为true就追加写入) |
public FileOutputStream(File file,boolean append) | 创建一个追加数据的字节输出流管道通向目标文件对象 |
- 写入数据三种方法
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流一次写一个字节数据 |
void write(byte[ ] b) | 将b.length字节从指定的字节数组写入此文件输出流一次写一个字节数组数据 |
void wirte(byte[ ] b,int off,int len) | 将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流一次写一个字节数组的部分数据 |
- 范例
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//一、FileOutputStream(String name) 创建文件输出流以指定名称写入文件
FileOutputStream fos = new FileOutputStream("E:\\test\\fos.txt");
/*源码解析:创建了File对象进行封装
new File(name)
FileOutputStream fos = new FileOutputStream(new File("E:\\test\\fos.txt"));*/
//二、FileOutputStream(File file) 创建文件输出流写入以指定的 File对象表示的文件
/*File file = new File("E:\\test\\fos.txt");
FileOutputStream fos2 = new FileOutputStream(file);*/
// FileOutputStream fos2 = new FileOutputStream(new File("E:\\test\\fos.txt")); //和上两句相等
//1、void write(int b) 将指定的字节写入此文件输出流一次写一个字节数据
/*fos.write(97);
fos.write(98);
fos.write(99);
fos.write(100);
fos.write(101);*/
//abcde
//2、void write(byte[ ] b) 将b.length字节从指定的字节数组写入此文件输出流一次写一个字节数组数据
/*byte[] bys = {97,98,99};
fos.write(bys); //abc*/
//byte[] getBytes():返回字符串对应的字节数组
byte[] bys = "abc".getBytes();
// fos.write(bys); //abc
//3,void wirte(byte[ ] b,int off,int len)
//将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流一次写一个字节数组的部分数据
fos.write(bys,1,2); //bc;从索引1开始写两个
fos.close()
}
}
4.2.2 字节输出流换行和追加写入
-
字节流写完数据后, 加换行符实现换行
- windows系统:
\r\n
- linux系统:
\n
- mac系统:
\r
- windows系统:
-
字节流写数据实现追加写入
- public FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
package test;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//public FileOutputStream(String file,boolean append) 创建一个追加数据的字节输出流管道通向目标文件路径
FileOutputStream fos = new FileOutputStream("E:\\test\\fos.txt",true);
for(int i=0;i<4;i++) {
fos.write("hello".getBytes()); //hellohellohellohello
fos.write("\r\n".getBytes());
/*第一次执行
hello
hello
hello
hello*/
/*第二次执行
hello
hello
hello
hello
hello
hello
hello
hello*/
}
fos.close();
}
}
4.2.3 字节输出加异常处理
finally
:在异常处理时提供finally块来执行所有清除操作。比如说O流中的释放资源- 特点:被finally控制的语句一定会执行,除非JVM退出
- 格式
try {
可能出现异常的代码;
}catch(异常类名 变量名) {
异常处理的代码;
}finally {
执行所有清除操作;
}
- 案例
package test;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) {
FileOutputStream fos =null; //初始化
try {
// 1,测试地址错误 fos = new FileOutputStream("Z:\\test\\fos.txt");
fos = new FileOutputStream("E:\\test\\fos.txt");
fos.write("hello".getBytes());
}catch (IOException e) {
e.printStackTrace();
}finally {
//1,NullPointerException;当文件地址错误时,fos还是为null,就不需要释放内存,所以需要加个判断fos是否为null的判断
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.3 字节输入流(读数据)
-
父类:
InputStream(抽象类)
-
子类:
FileInputStream(实现类:从文件系统中的文件获取输入字节)
-
构造方法
方法名 | 说明 |
---|---|
public FileInputStream(File path) | 创建一个字节输入流管道与源文件对象接通 |
public FileInputStream(String pathName) | 创建一个字节输入流管道与文件路径对接 |
- 方法
方法名 | 说明 |
---|---|
public int read() | 每次读取一个字节返回!读取完毕会返回 -1 |
public int read(byte[] buffer) | 从字节输入流中读取字节到字节数组中去,返回读取的字节数量,没有字节可读返回 -1 |
- 使用字节输入流读数据的步骤:
- 1、创建字节输入流对象
- 2、调用字节输入流对象的读数据方法
- 3、释放资源
- 范例:
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
// 1、创建字节输入流对象
FileInputStream fis = new FileInputStream("E:\\test\\fos.txt");
//2、调用字节输入流对象的读数据方法
//int read():从该输入流读取一个字节数据
//第一次读取数据
/*int by = fis.read();
System.out.println(by); //97,表示a
System.out.println((char)by); //a
//第二次读取数据
by = fis.read();
System.out.println(by); //98
System.out.println((char)by); //b
//再多读取两次
by = fis.read();
System.out.println(by); //-1,表示没有数据了
by = fis.read();
System.out.println(by); //-1*/
//循环改进
/*int by = fis.read();
while(by != -1) {
System.out.print((char)by); //ab
by = fis.read();
}*/
//优化循环
int by;
//1、先做了读数据fis.read();2、赋值by=fis.read();3、与by 与 -1比较
while((by=fis.read()) != -1) {
System.out.print((char)by); //ab
}
//3、释放资源
fis.close();
}
}
- 案例:按字节数组读取
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyTxtDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\test\\fos.txt");
byte[] bys = new byte[1024]; //1024及其整数倍
int len;
while((len=fis.read(bys)) != -1) {
System.out.println(new String(bys,0,len));
/*ab
cd*/
}
fis.close();
}
}
- 案例:Copy文本文件
package test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyTxtDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\test\\fos.txt");
FileOutputStream fos = new FileOutputStream("E:\\test\\Demo\\fos.txt");
int by;
while((by=fis.read()) != -1) {
fos.write(by);
}
fos.close();
fis.close();
}
}
- 案例:Copy图片
package test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyPngDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\test\\1.png");
FileOutputStream fos = new FileOutputStream("E:\\test\\Demo\\1.png");
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys)) != -1) {
fos.write(bys,0,len);
}
fos.close();;
fis.close();
}
}
4.4 字节缓冲流
-
缓冲流可以提高字节流和字符流的读写数据的性能
-
字节缓冲流:
BufferedInputStream
:创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节BufferOutputStream
:该类实现缓冲输出流。通过设置这样的输出流, 应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
-
构造方法:
- 字节缓冲输入流:
BufferedInputStream(InputStream in)
- 字节缓冲输出流:
BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:
-
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲流仅仅提供缓冲区, 而真正的读写数据还得依靠基本的字节流对象进行操作
-
范例:
package test;
import java.io.*;
public class BufferStreamDemo {
public static void main(String[] args) throws IOException {
//字节缓冲输出流:BufferedOutputStream(OutputStream out)
/*FileOutputStream fos = new FileOutputStream("E:\\test\\fos.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);*/
/*BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\test\\fos.txt"));
//写数据
bos.write("hello\r\n".getBytes());
bos.write("java\r\n".getBytes());
// hello
// java
bos.close();*/
//字节缓冲输入流:BufferedInputStream(InputStreamin)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\test\\fos.txt"));
int by;
while((by=bis.read()) != -1) {
System.out.print((char)by);
// hello
// java
}
bis.close();
}
}