一、IO流概述
IO都是全大写 说明肯定是两个单词的首字母
I inputstream 输入流 O outputstream 输出流
IO 称之为 java的输入输出流
其实学习IO 就是学习 如何通过java代码 对文件内容 进行 读(输入流) 写(输出流)
所以有一话: 读进来 写出去
Java流的分类
按流向分:
输入流: 程序可以从中读取数据的流。
输出流: 程序能向其中写入数据的流。
按数据传输单位分:
字节流: 以字节为单位传输数据的流
字符流: 以字符为单位传输数据的流
按功能分:
节点流: 用于直接操作目标设备的流 ---- 四大基流
过滤流: 是对一个已存在流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。 ---- 包装流
四大基流:
字节输入流
字节输出流
字符输入流
字符输出流
二、字节输出流
第一种方式
@Test
public void test5() throws Exception{
/*1 创建流*/
FileOutputStream fileOutputStream = new FileOutputStream("D:/aaa/666.txt");
//2 输出操作
fileOutputStream.write(100);
fileOutputStream.write(101);
fileOutputStream.write(102);
fileOutputStream.write(103);
fileOutputStream.write(104);
/*3 关闭流*/
fileOutputStream.close();
}
调用write函数 参数是int类型 代表将int类型对应的char字符写出
第二种方式 byte数组形式
@Test
public void test5() throws Exception{
/*1 创建流*/
FileOutputStream fileOutputStream = new FileOutputStream("D:/aaa/666.txt");
//2 输出操作
byte[] data = "asdlkfjalksdjflksadjf;ljaksdf world".getBytes();
fileOutputStream.write(data);
/*3 关闭流*/
fileOutputStream.close();
}
第三种方式 局部byte数组
@Test
public void test5() throws Exception{
/*1 创建流*/
FileOutputStream fileOutputStream = new FileOutputStream("D:/aaa/666.txt");
//2 输出操作
byte[] data = "abcdefghijklmnopqrstuvwxyz".getBytes();
fileOutputStream.write(data,3,6);
/*3 关闭流*/
fileOutputStream.close();
}
追加操作
@Test
public void test5() throws Exception{
/*1 创建流*/
FileOutputStream fileOutputStream = new FileOutputStream("D:/aaa/666.txt",true);
//2 输出操作
byte[] data = "abcdefghijklmnopqrstuvwxyz".getBytes();
fileOutputStream.write(data,4,4);
/*3 关闭流*/
fileOutputStream.close();
}
三、字节输入流
方式一 直接调用 read() 函数 返回为读取的一个字节信息
@Test
public void test6() throws Exception {
// 1 创建流
InputStream in = new FileInputStream("D:/aaa/666.txt");
// 2 操作
int read = in.read();
int read1 = in.read();
System.out.println(read + "----" +read1);
// 3 关闭流
in.close();
}
方式二 直接调用 read(byte[]) 函数
@Test
public void test6() throws Exception {
// 1 创建流
InputStream in = new FileInputStream("D:/aaa/666.txt");
// 2 操作
byte[] data = new byte[16];
int read = in.read(data);
System.out.println(read);
System.out.println(Arrays.toString(data));
// 3 关闭流
in.close();
}
26
[65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
此时 会将本次读取的数据 存储到 byte数组中 并且返回当前读取的个数
问题: 数组定义多少容量合适?
方式三
@Test
public void test6() throws Exception {
// 1 创建流
InputStream in = new FileInputStream("D:/aaa/666.txt");
// 2 操作
byte[] data = new byte[50];
int read = in.read(data, 5, 8);
System.out.println(read);
System.out.println(Arrays.toString(data));
// 3 关闭流
in.close();
}
8
[0, 0, 0, 0, 0, 65, 66, 67, 68, 69, 70, 71, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
注意 第二个参数代表初始索引 第三个参数代表 长度 整体代表 数组中 哪些位置可以用来存储数据
将数组中的内容转换成原始内容
@Test
public void test6() throws Exception {
// 1 创建流
InputStream in = new FileInputStream("D:/aaa/666.txt");
// 2 操作
byte[] data = new byte[70];
int read = in.read(data );
// 将byte数组转换成字符串
String s = new String(data , 0 , read);
System.out.println(s);
// 3 关闭流
in.close();
}
循环读取大文件数据
@Test
public void test6() throws Exception {
// 1 创建流
InputStream in = new FileInputStream("D:/aaa/666.txt");
// 2 操作 26
byte[] data = new byte[4];
/*用来记录每次读取的长度*/
int len = -1;
StringBuilder sb = new StringBuilder();
// 1 in.read(data) 读取数据到数组中 2 本次读取的长度 赋值给 len 3 判断len是否大于0
while( (len = in.read(data) ) > 0 ){
String s = new String(data, 0, len);
sb.append(s);
}
System.out.println(sb);
// 3 关闭流
in.close();
}
四、文件复制
@Test
public void test7() throws Exception{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
in.close();
out.close();
}
五、异常处理
1 将异常转移的代码干掉 换成异常捕获
/**
* FileNotFoundException IOException
*/
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
此时代码虽然不报错 但是有问题,关闭资源的代码 在try中,如果中途出现异常 会出现 资源打开但是没有关闭的情况
我们的资源无论有没有问题 都需要关闭。
2 将关闭资源的代码写到 finally 中
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 in和out报错 错误信息为: Cannot resolve symbol 'in' 使用了未定义的变量
in 和 out的定义在 try中 ,局部变量的作用域 此时从定义开始 到 所在结束大括号
3 所以我们需要 in和out的定义在try外面 赋值在里面 保证了 作用域能达到 并且 异常在try中处理
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 close() 代码报错 : Unhandled exception: java.io.IOException
也就是说 close中也有 非运行时异常 也需要处理
4 在finally 中 通过 try-catch 处理 close的异常
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
此时注意 虽然看着不出问题了 但是有隐藏问题 如果 in和out在没有赋值之前就崩了 此时会导致 catch进行捕获 最终到达fianlly 执行关闭代码 但是 in和out还是个 null 就会出现空指针异常
5 所以我们需要在关闭之前添加 非空判断
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
int i = 1/0;
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
if(out != null){
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
此时看上去没有问题 但是依然有隐藏问题: 如果 in在关闭的时候 出现异常 此时会导致 out关闭无法正常执行
6 在in 的 try之后的finally中再去关闭 out
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
所以 JDK1.7开始 推出了新的 try-catch 解决关闭资源麻烦的问题
六、字符的输入流和输出流
1 将异常转移的代码干掉 换成异常捕获
/**
* FileNotFoundException IOException
*/
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
此时代码虽然不报错 但是有问题,关闭资源的代码 在try中,如果中途出现异常 会出现 资源打开但是没有关闭的情况
我们的资源无论有没有问题 都需要关闭。
2 将关闭资源的代码写到 finally 中
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 in和out报错 错误信息为: Cannot resolve symbol 'in' 使用了未定义的变量
in 和 out的定义在 try中 ,局部变量的作用域 此时从定义开始 到 所在结束大括号
3 所以我们需要 in和out的定义在try外面 赋值在里面 保证了 作用域能达到 并且 异常在try中处理
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 close() 代码报错 : Unhandled exception: java.io.IOException
也就是说 close中也有 非运行时异常 也需要处理
4 在finally 中 通过 try-catch 处理 close的异常
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
此时注意 虽然看着不出问题了 但是有隐藏问题 如果 in和out在没有赋值之前就崩了 此时会导致 catch进行捕获 最终到达fianlly 执行关闭代码 但是 in和out还是个 null 就会出现空指针异常
5 所以我们需要在关闭之前添加 非空判断
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
int i = 1/0;
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
if(out != null){
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
此时看上去没有问题 但是依然有隐藏问题: 如果 in在关闭的时候 出现异常 此时会导致 out关闭无法正常执行
6 在in 的 try之后的finally中再去关闭 out
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
所以 JDK1.7开始 推出了新的 try-catch 解决关闭资源麻烦的问题
七、包装流--缓存流
1 将异常转移的代码干掉 换成异常捕获
/**
* FileNotFoundException IOException
*/
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
此时代码虽然不报错 但是有问题,关闭资源的代码 在try中,如果中途出现异常 会出现 资源打开但是没有关闭的情况
我们的资源无论有没有问题 都需要关闭。
2 将关闭资源的代码写到 finally 中
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 in和out报错 错误信息为: Cannot resolve symbol 'in' 使用了未定义的变量
in 和 out的定义在 try中 ,局部变量的作用域 此时从定义开始 到 所在结束大括号
3 所以我们需要 in和out的定义在try外面 赋值在里面 保证了 作用域能达到 并且 异常在try中处理
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 close() 代码报错 : Unhandled exception: java.io.IOException
也就是说 close中也有 非运行时异常 也需要处理
4 在finally 中 通过 try-catch 处理 close的异常
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
此时注意 虽然看着不出问题了 但是有隐藏问题 如果 in和out在没有赋值之前就崩了 此时会导致 catch进行捕获 最终到达fianlly 执行关闭代码 但是 in和out还是个 null 就会出现空指针异常
5 所以我们需要在关闭之前添加 非空判断
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
int i = 1/0;
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
if(out != null){
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
此时看上去没有问题 但是依然有隐藏问题: 如果 in在关闭的时候 出现异常 此时会导致 out关闭无法正常执行
6 在in 的 try之后的finally中再去关闭 out
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
所以 JDK1.7开始 推出了新的 try-catch 解决关闭资源麻烦的问题
八、包装流--对象流
1 将异常转移的代码干掉 换成异常捕获
/**
* FileNotFoundException IOException
*/
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
此时代码虽然不报错 但是有问题,关闭资源的代码 在try中,如果中途出现异常 会出现 资源打开但是没有关闭的情况
我们的资源无论有没有问题 都需要关闭。
2 将关闭资源的代码写到 finally 中
@Test
public void test7() {
try{
FileInputStream in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
FileOutputStream out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 in和out报错 错误信息为: Cannot resolve symbol 'in' 使用了未定义的变量
in 和 out的定义在 try中 ,局部变量的作用域 此时从定义开始 到 所在结束大括号
3 所以我们需要 in和out的定义在try外面 赋值在里面 保证了 作用域能达到 并且 异常在try中处理
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
in.close();
out.close();
}
}
此时 close() 代码报错 : Unhandled exception: java.io.IOException
也就是说 close中也有 非运行时异常 也需要处理
4 在finally 中 通过 try-catch 处理 close的异常
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
in.close();
out.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
此时注意 虽然看着不出问题了 但是有隐藏问题 如果 in和out在没有赋值之前就崩了 此时会导致 catch进行捕获 最终到达fianlly 执行关闭代码 但是 in和out还是个 null 就会出现空指针异常
5 所以我们需要在关闭之前添加 非空判断
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
int i = 1/0;
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
if(out != null){
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
此时看上去没有问题 但是依然有隐藏问题: 如果 in在关闭的时候 出现异常 此时会导致 out关闭无法正常执行
6 在in 的 try之后的finally中再去关闭 out
@Test
public void test7() {
FileInputStream in = null;
FileOutputStream out = null;
try{
in = new FileInputStream("D:/datasource/jdk_8.0.1310.11_64.exe");
out = new FileOutputStream("D:/jdk8.exe");
byte[] data = new byte[1024];
int len = -1;
while( (len = in.read(data)) > 0 ){
out.write(data,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(in != null) {
in.close();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(out != null) {
out.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
所以 JDK1.7开始 推出了新的 try-catch 解决关闭资源麻烦的问题