IO流技术总览

引入:生活中我们下载/上传就是IO操作的过程。这就是IO流,其实就是一连串动态数据的集合。
前提知识:
必须先说明IO理解必须分为网络IO和磁盘IO
网络IO的理解:
关于BIO、NIO、AIO的理解参考:https://www.cnblogs.com/barrywxx/p/8430790.html
以下的单纯是IO磁盘的理解
数据源(data source)的理解:提供原始数据的原始媒介,常见的:数据库、文件、其他程序、内存、网络连接、IO设备。
在整个java.IO包中最后重要的5个类:File,文件类;InputStream,字节输入流;OutputStream,字节输出流;Reader,字符输入流;Writer,字节输出流;
3个接口:Closeable,关闭流接口;Flushable,刷新流接口;Serializeable,序列化接口。
上面就提出两个概念:
字节流:按照字节读取数据,如InputStream,OutputStream;适合音频、视频、execl等文件必须用这个
字符流:按照字符读取数据,如:Reader,Writer;这是因为文件的编码不同,从而有了对字符进行高效操作的的字符流对象。但是说到底原理还是字节流。能用字符流的都可以用字节流。这个字符流仅仅适合字符文件
java.IO包下的内容:(上面的只是一部分,有时间得去研究更多)
在这里插入图片描述

File路径构建的方式:(三种常见方式)

package com.stu.io;

import java.io.File;

public class Mytest1 {

public static void main(String[] args) {
    String path = "E:/ownStudy/IOStudy/IO.PNG";

    // 1,构建file对象
    File src = new File(path);
    System.out.println(src);

    // 2,构建file对象
    src = new File("E:/ownStudy/IOStudy","IO.PNG");
    System.out.println(src);

    // 3,构建file对象
    src = new File(new File("E:/ownStudy/IOStudy"),"IO.PNG");
    System.out.println(src);
}
}

运行结果:
在这里插入图片描述
File的源码有700多行,这里实现不好拿出来说,建议看着的时候去打开File.class查看源码;
这里介绍起其中的方法:
getName : 获取file的名称;
getPath:获取file路径(这里的路径取决于你构建的路径)
getAbsolutePath:返回绝对路径。
getParent:返回父路径
exists:判断是否存在
isFile:判断是否是一个文件。
isDirectory:是检查一个对象是否是文件夹;
createNewFile:不存在下,创建文件
delete:删除已经存在的文件等等;
length:返回文件的情况下文件字节数

package com.stu.io;

import java.io.File;

public class Mytest1 {

public static void main(String[] args) {
    String path = "E:/ownStudy/IOStudy/IO.PNG";
    File src = new File(path);
    System.out.println("名称: " + src.getName());
    System.out.println("绝对路径:" + src.getAbsolutePath());
    System.out.println("路径: " + src.getPath());
    System.out.println("父对象: " + src.getParentFile());
    System.out.println("存在是否?: " + src.exists());
    System.out.println("文件是否?:" + src.isFile());
    System.out.println("目录是否?:" + src.isDirectory());
    // 通常操作逻辑
    if(!src.exists()) {
        System.out.println("文件不存在");
    } else {
        if (src.isFile()) {
            System.out.println("执行文件操作");
        } else {
            System.out.println("执行文件夹操作");
        }
    }
}
}

运行结果:
在这里插入图片描述

创建目录
这里改了风格,改用IDEA编辑软件;

package com.bytecode.stu;

import java.io.File;

public class Main {

public static void main(String[] args) {
    // 创建目录mkdir,mkdirs创建目录一个是存在路径下目录,一个是不存在父目录也可以创建父目录及创建目录。
    // list 下级名称,listFiles 下级File,listRoots 根路径
    File dir = new File("E:/ownStudy/dir/test"); // 路径下没有dir
    boolean fflag = dir.mkdir();
    boolean flag = dir.mkdirs();
    System.out.println(fflag);
    System.out.println(flag);
}
}

运行结果:
在这里插入图片描述

import java.io.File;
import java.util.Arrays;

public class Main {

public static void main(String[] args) {
    // 创建目录mkdir,mkdirs创建目录一个是存在路径下目录,一个是不存在父目录也可以创建父目录及创建目录。
    // list 下级名称,listFiles 下级File,listRoots 根路径
    File dir = new File("E:/ownStudy");
    String[] strs = dir.list();
    Arrays.asList(strs).forEach(t->{System.out.println(t);});
    System.out.println("------------------");
    File[] files = dir.listFiles();
    Arrays.asList(files).forEach(t->{System.out.println(t);});
}
}

运行结果:(如果是深层次目录利用递归找到即可)
在这里插入图片描述
流的操作过程(重要)–字节流
创建源 - 》 选择流 - 》 操作 (读写)- 》 释放。
在这里插入图片描述
读操作的体现

package com.ss.nn;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class JStest {
public static void main(String[] args) throws IOException {
    // 创建源 - > 选择流 - > 操作 (读写)- > 释放。
    // 创建源
    File src = new File("aa.txt");

    // 选择流
    InputStream ism = null;
    try {
        ism = new FileInputStream(src);

        // 读操作
        int temp = 0;
        while ((temp = ism.read()) != -1) { // read(),返回单个字符
            System.out.print((char)temp + " "); // 强转为字符
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != ism) {
                // 关闭流
                ism.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

运行结果:(可见这一个一个的读取,效率是不高的)
在这里插入图片描述
由上面可以,我们利用byte[] 缓冲来解决。

package com.ss.nn;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class JStest {
public static void main(String[] args) throws IOException {
    // 创建源 - > 选择流 - > 操作 (读写)- > 释放。
    // 创建源
    File src = new File("aa.txt");

    // 选择流
    InputStream ism = null;
    try {
        ism = new FileInputStream(src);

        // 读操作(分段读取)
        int len = -1; // 接收到的长度
        byte[] bytes = new byte[4]; // 缓存中放四个
        while ((len = ism.read(bytes)) != -1) {
            String strs = new String(bytes,0,len);
            System.out.println(strs);
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != ism) {
                // 关闭流
                ism.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

运行结果:
在这里插入图片描述

写操作的体现:
在这里插入图片描述

package com.ss.nn;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class JStest {
public static void main(String[] args) throws IOException {
    // 创建源 - > 选择流 - > 操作 (读写)- > 释放。
    // 创建源
    File src = new File("bb.txt");

    // 选择流
    OutputStream osm = null;
    try {
        osm = new FileOutputStream(src,true); // 设置为真,保证可以对文件内容的追加,不会覆盖原有的数据。

        String aha = "nihao,shahahah";

        // 假写一个读的过程
        byte[] bytes = aha.getBytes();

        // 写操作
        osm.write(bytes, 0, aha.length());
        osm.flush(); // 冲刷保证数据完全写入
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != osm) {
                // 关闭流
                osm.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

运行结果:
在这里插入图片描述
上面整合(就是我们常见的文件copy,)–利用递归做文件夹的拷贝。

package com.ss.nn.mm;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class OperateFile {

/**
 * 文件拷贝
 * @param srcPath 被拷贝文件
 * @param destPath 拷贝至该目标
 * @throws zhouyi
 */
public void fileCopy(String srcPath,String destPath) throws IOException {
InputStream ism = null;
OutputStream os = null;

try {
    ism = new FileInputStream(new File(srcPath));
    os = new FileOutputStream(new File(destPath));

    int len = -1;
    byte[] bytes = new byte[1024];
    while ((len = ism.read(bytes)) != -1) {
        os.write(bytes, 0, bytes.length);
    }
    os.flush();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    try {
        if (null != os) {
            os.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (null != ism) {
            ism.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}
}

上面这个方法,由于是字节流的,可以copy任何东西,图片,电影等。

流的操作过程(重要)–字符流
好处是不用转换,也能很好避免编码乱码的的问题。

package com.ss.nn.mm;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class OperateFile {

/**
 * 文件拷贝:上面的字节流,当内容中英文时会乱码,这就需要字符流来操作。
 * 局限:只能应用于字符文件,不能是图片等。
 * @param srcPath 被拷贝文件
 * @param destPath 拷贝至该目标
 * @throws zhouyi
 */
public void fileCopy(String srcPath,String destPath) throws IOException {
Reader reader = null;
Writer writer = null;

try {
    reader = new FileReader(new File(srcPath));
    writer = new FileWriter(new File(destPath));

    int len = -1;
    char[] bytes = new char[1024];
    while ((len = reader.read(bytes)) != -1) {
        writer.write(bytes, 0, bytes.length);
    }
    writer.flush();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    try {
        if (null != reader) {
            reader.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (null != writer) {
            writer.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}
}

ByteArrayOutputStream/ ByteArrayInputStream 字节数组(底层框架经常用)
1,不需要关闭,因此不要太大(最好还是关闭的好);可以操作任何文件(因为是二进制)

package com.ss.nn.mm;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class OperateFile {

/**
 * 文件转成字节流
 * @param srcPath 被拷贝文件
 * @param destPath 没有意义
 * @throws zhouyi
 */
public byte[] fileToByteArray(String srcPath,String destPath) throws IOException {
InputStream bais = null; // 也是可以的
ByteArrayOutputStream baos = null;

try {
    bais = new FileInputStream(new File(srcPath));
  //不需要dest 需要使用toByteArray()去获得字节数组或者toString得到字符串
    baos = new ByteArrayOutputStream();

    int len = 0;
    byte[] bytes = new byte[1024];
    while ((len = bais.read(bytes)) != -1) {
        baos.write(bytes, 0, len);
    }
    baos.flush();
    byte[] data = baos.toByteArray();
    return data;
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    try {
        if (null != bais) {
            bais.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (null != baos) {
            baos.close();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
return null;
}

/**
 * 字节流转成文件
 * @param data 字节数组
 * @param srcPath 写入路径
 */
public void byteArrayToFile(byte[] data,String srcPath) {
    InputStream is = null;
    OutputStream os = null;
    try {
        is = new ByteArrayInputStream(data);
        os = new FileOutputStream(srcPath);

        byte[] bytes = new byte[1024];
        int len = -1;
        while ((len = is.read(bytes)) != -1) {
            os.write(bytes, 0, len);
        }
        os.close();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != os) {
                os.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (null != is) {
                is.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
}

package com.ss.nn;

import java.io.IOException;
import java.util.Arrays;

import com.ss.nn.mm.OperateFile;

public class JStest {
public static void main(String[] args) throws IOException {
OperateFile tt = new OperateFile();
byte[] data = tt.fileToByteArray("bb.txt", "zhouyi.txt");
System.out.println(Arrays.toString(data));
tt.byteArrayToFile(data, "zhouyi.txt");
}
}

以上都是成功运行了的。接下来是学习common_IO的中介过程,理解他是怎么来的。

package com.ss.nn.mm;

import java.io.ByteArrayInputStream;
import java.io.Closeable;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * 封装
 * @author zhouyi
 *
 */
public class FileUtils {

  /**
	 * 对接输入输出流
	 * @param is
  * @param os
	 * @throws IOException
 */
public void fileCopy(InputStream is,OutputStream os) throws IOException {

    try {
        int len = -1;
        byte[] bytes = new byte[1024];
        while ((len = is.read(bytes)) != -1) {
            os.write(bytes, 0, bytes.length);
        }
        os.flush();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    }
/**
 * 关闭流
 * @param ios
 */
public void close(Closeable... ios) { // 可变参数
    for(Closeable io : ios) {
        try {
            if (null != io) {
                io.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}


package com.ss.nn;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.ss.nn.mm.FileUtils;

public class JStest {
public static void main(String[] args) throws IOException {
	FileUtils fileUtils = new FileUtils();
  	InputStream is = new FileInputStream("bb.txt");
 	 OutputStream os = new FileOutputStream("zhouyi.txt");
	  fileUtils.fileCopy(is, os);
	  fileUtils.close(is,os);
}
}

上面这种封装思想就是common_IO包的来由。

BufferedInputStream/BufferedOutputStream

package com.ss.nn;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * BufferedInputStream/BufferedOutputStream
 * 这是缓冲流,有一定缓冲内存,当满了的时候才会一次性写出,提高了速度和性能
 * 需要使用InputStream/OutputStream来过渡。即是需要套嵌节点流
 * @author zhouyi
	 *
*/
public class MyTest1 {

/**
 * 文件拷贝
 * @param srcPath 被拷贝文件
 * @param destPath 拷贝至该目标
 * @throws zhouyi
 */
public void fileCopy(String srcPath,String destPath) throws IOException {
	BufferedInputStream is = null;
	BufferedOutputStream os = null;
	try {
  is = new BufferedInputStream(new FileInputStream(new File(srcPath)));

 os = new BufferedOutputStream(new FileOutputStream(new File(destPath)));

int len = -1;
byte[] bytes = new byte[1024];
while ((len = is.read(bytes)) != -1) {
    os.write(bytes, 0, bytes.length);
}
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
    if (null != os) {
        os.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}
try {
    if (null != is) {
        is.close();
    }
} catch (Exception e) {
    e.printStackTrace();
}
}
}
}

BufferedReader/BufferedWriter
相同操作。

BufferedReader reader = null;
BufferedWriter writer = null;
try {
 reader = new BufferedReader(new FileReader(new File(srcPath)));

 writer = new BufferedWriter(new FileWriter(new File(destPath)));

 String line = null;
 while ((line = reader.readLine()) != null) { // 逐行读入
    writer.write(line, 0, line.length());
}
writer.flush();

转换流OutputStreamWriter/InputStreamReader
字符流和字节流的转换桥梁。

public class JStest {
public static void main(String[] args) throws IOException {

try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));) { // 这是java7的写法
    //获取键盘输入
    String str = "";
    while (!str.equals("exit")) {
        str = reader.readLine();// 读入一行
        writer.write(str); // 写出一行
        writer.newLine(); // 写出为新行
        writer.flush();// 这是为了防止较小时,没有满足缓存大小,而不写出。
    }
} catch (IOException e) {
    e.printStackTrace();
}
}
}

下载网络流:

public class JStest {
public static void main(String[] args) throws IOException {
// BufferedReader is = new BufferedReader(new InputStreamReader(new URL("http://www.baidu.com").openStream(),"UTF-8"));最好的写法
try(InputStreamReader is = new InputStreamReader(new URL("http://www.baidu.com").openStream(),"UTF-8");) { // 这是java7的写法
    int temp = 0; // 上面不写成InputStreamReader,并不设置UTF-8就有乱码问题
    while ((temp = is.read()) != -1) {
        System.out.print((char)temp);
    }
} catch (IOException e) {
    e.printStackTrace();
}
}
}

数据流 DataOutputStream/DataInputStream
注意点:写出后读取,必须保证写出和读取的顺序一致。代码和上面的差不多,不给出。

对象流-ObjectOutputStream/ObjectInputStream(序列化的对的想才能支持对象流)
使用和 数据流的注意事项一样,除了序列化要求。

打印流 --PrintStream或者PrintWriter

上面的所有就是为了建立思维。真正应用还是下面。commonIO工具包。
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值