I/O,即输入(Input)/ 输出(Output),IO流指的是数据像连绵的流体一样进行传输。
Java中I/O的操作是指使用java.io包下的内容进行输入、输出操作。
按数据的流向分为:输入流和输出流
按数据的类型分为:
字节流:以字节为单位来操作数据。
InputStream: 字节输入流的顶层抽象类.
FileInputStream:普通的字节输入流.
BufferedInputStream: 高效的字节输入流(也叫: 字节缓冲输入流)
OutputStream:字节输出流的顶层抽象类.
FileOutputStream:普通的字节输出流.
BufferedOutputStream:高效的字节输出流(也叫: 字节缓冲输出流).
字符流: 以字符为单位来操作数据
Reader: 字符输入流的顶层抽象类.
FileReader:普通的字符输入流.
BufferedReader:高效的字符输入流(也叫: 字符缓冲输入流)
Writer: 字符输出流的顶层抽象类.
FileWriter:普通的字符输出流.
BufferedWriter:高效的字符输出流(也叫: 字符缓冲输出流)
//1.根据字符串形式获取File对象
public File(String pathname);
//2.根据字符串形式的父目录以及子目录创建File对象
public File(String parent, String child);
//3.根据父目录对象以及字符串形式的子目录对象获取File对象
public File(File parent, String child);
也就是我们有三种方法创建File对象
String pathname = "E:\\test\\1.txt"
String parent = "E:\\test\\"
String child = "1.txt"
//方式一:根据字符串形式获取File对象
File file1 = new File(pathname);
//方式二:根据字符串形式的父目录以及子目录创建File对象
File file2 = new File(parent,child);
//方式三:根据父目录对象以及字符串形式的子目录对象获取File对象
File file3 = new File(new File(parent),child);
//在 E:\test\ 文件夹下创建 1.txt 文件
File file1 = new File("E:\\test\\2.txt");
Boolean flag = file5.createNewFile();
System.out.println(flag);
//在 E:\test\ 下创建 test1 文件夹,创建单极目录
File file2 = new File("E:\\test\\test1");
file2.mkdir();
//在 E:\test\ 下创建 a\b\c 文件夹,创建多极目录
File file3 = new File("E:\\test\\a\\b\\c");
file7.mkdirs(); //创建多级目录
System.out.println("------------------测试判断功能------------------");
File file4 = new File("E:\\test\\a\\b\\c");
file8.mkdirs();
System.out.println("测试file8是否是文件夹"+file8.isDirectory());
System.out.println("测试file8是否是文件"+file8.isFile());
System.out.println("测试file8是否存在"+file8.exists());
System.out.println("------------------测试获取功能------------------");
File file5 = new File("a/1.txt");
//获取绝对路径
String path1 = file9.getAbsolutePath();
System.out.println("绝对路径: "+path1);
//获取相对路径
String path2 = file9.getPath();
System.out.println("相对路径:"+path2);
//获取文件名
String filename = file9.getName();
System.out.println("文件名:"+filename);
System.out.println("------------------------------------");
//获取lib文件夹下所有文件(夹)的:名称数组String[]
File file6 = new File("a");
String[] names = file6.list();
for (String name:names){
System.out.println(name);
}
//获取lib文件夹下所有文件(夹)的:File对象数组 File[]
File[] files = file6.listFiles();
for(File file:files){
System.out.println(file);
}
读取字符:read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1,循环读取,代码使用演示:
public class TestReader {
public static void main(String[] args) throws Exception {
//通过字符流读取数据
Reader reader = new FileReader("a/1.txt");
int ch;
while ((ch = reader.read()) != -1){
System.out.println((char)ch);
}
//关闭资源
reader.close();
}
}
public class TestReader2 {
public static void main(String[] args) throws IOException {
//通过字符数组读取数据
Reader reader = new FileReader("a/1.txt");
char[] chs = new char[3];
int len = 0;
// 读取字符到数组中,返回读取的字符数,若到达流的末尾,返回-1
while ((len = reader.read(chs))!=-1){
String s = new String(chs,0,len);
System.out.println(s);
}
reader.close();
}
}
public class TestWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileWriter fw = new FileWriter("1.txt");
// 写出数据
fw.write(97); // 写出第1个字符
fw.write('b'); // 写出第2个字符
fw.write('C'); // 写出第3个字符
//关闭资源。
// fw.close();
}
}
public class Testwriter {
public static void main(String[] args) throws IOException {
Writer writer = new FileWriter("a/1.txt");
//每写入一次会覆盖之前的内容
char[] chars = {'女','朋','朋','很','帅'};
writer.write(chars,0,3);
writer.write("好好学习");
writer.close();
}
}
每次读取一个字符,效率太低,因此我们一般都采用数组进行读写操作。
public class CopyFile {
public static void main(String[] args) throws IOException {
//将 1.txt 文件中的内容拷贝到 2.txt 中
//创建输入流对象
FileReader fileReader = new FileReader("1.txt");
//创建输出流对象
FileWriter fileWriter = new FileWriter("2.txt");
int len;
char[] chars = new char[1024];
while ((len = fileReader.read(chars))!=-1){ //读数据
//写数据
fileWriter.write(chars,0,len);
}
fileReader.close();
fileWriter.close();
}
}
最后强调:
字符流,只能操作文本文件,不能操作图片,视频等非文本文件。当我们单纯读或者写文本文件时使用字符流其他情况使用字节流
字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB,底层是按照字符数组进行读取的。在实际中我们一般使用字符缓冲流。
public class 拷贝文件标准代码 {
public static void main(String[] args) throws IOException {
//字符缓冲流自带有缓冲区,大小为8192个字符,也就是16KB,底层是按照字符数组进行读取的
//1.创建字符缓冲输入流读文件对象
BufferedReader br = new BufferedReader(new FileReader("a/1.txt"));
//1.创建字符缓冲输出流读文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("a/2.txt"));
int len;
while ((len = br.read())!=-1){
bw.write(len);
}
br.close();
bw.close();
}
FileInputStream的构造方法:
//通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(File file)
//通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名name命名。
FileInputStream(String name)
FileOutputStream的构造方法:
//根据File对象为参数创建对象。
public FileOutputStream(File file)
//根据名称字符串为参数创建对象。
public FileOutputStream(String name)
一般使用第二种构造方法。
字节流的用法和字符流大体一致,因此在这里我们直接进行应用,并且字符流无法对图片进行读写操作,下面我们用字节流对图片进行读写操作。
public class CopyFile{
public static void main(String[] args) throws IOException {
// 使用文件名称创建字节流读文件对象
FileInputStream fls = new FileInputStream("1.png");
// 使用文件名称创建字节流写文件对象
FileOutputStream fos = new FileOutputStream("2.png");
int len;
while ((len = fls.read())!=-1){
fos.write(len);
}
fls.close();
fos.close();
}
}
在开发中一般强烈推荐使用数组读取文件,代码如下:
public class CopyFile {
public static void main(String[] args) throws IOException {
// 使用文件名称创建字节流读文件对象
FileInputStream fls = new FileInputStream("1.png");
// 使用文件名称创建字节流写文件对象
FileOutputStream fos = new FileOutputStream("2.png");
int len;
//定义字节数组,每次读取1024个字节
byte[] bytes = new byte[1024];
while ((len = fls.read(bytes))!=-1){
fos.write(bytes,0,len);
}
fls.close();
fos.close();
}
}
缓冲流的基本原理:
也就是说在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而大大提高读写的效率。
//创建一个新的缓冲输入流,注意参数类型为InputStream。
public BufferedInputStream(InputStream in)
//创建一个新的缓冲输出流,注意参数类型为OutputStream。
public BufferedOutputStream(OutputStream out)
public class CopyFile{
public static void main(String[] args) throws IOException {
//记录开始时间
long start = System.currentTimeMillis();
//创建字节缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.png"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.png"));
int len;
while ((len = bis.read())!=-1){ //读数据
//写数据
bos.write(len);
}
bis.close();
bos.close();
//记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");
}
}
那么能不能更快呢,答案是可以的,下面我们使用字节缓冲流和字节数组进行读写操作,代码如下:
public class CopyFile{
public static void main(String[] args) throws IOException {
//记录开始时间
long start = System.currentTimeMillis();
//创建字节缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.png"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("2.png"));
int len;
byte[] bytes = new byte[2048];
while ((len = bis.read(bytes))!=-1){ //读数据
//写数据
bos.write(bytes,0,len);
}
bis.close();
bos.close();
//记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");
}
}
//创建一个新的缓冲输入流,注意参数类型为Reader。
public BufferedReader(Reader in)
//创建一个新的缓冲输出流,注意参数类型为Writer。
public BufferedWriter(Writer out)
字符缓冲流的使用方法和字节缓冲流的方法基本一致,但字符缓冲流具有一些特有的方法。
public String readLine()
:读一行数据。 读取到最后返回null。public void newLine()
: 换行,由系统属性定义符号。我们使用字符缓冲流和字节数组进行读写操作
public class 拷贝文件标准代码 {
public static void main(String[] args) throws IOException {
//记录开始时间
long start = System.currentTimeMillis();
//1.创建字符缓冲输入流读文件对象
BufferedReader br = new BufferedReader(new FileReader("1.txt"));
//1.创建字符缓冲输出流读文件对象
BufferedWriter bw = new BufferedWriter(new FileWriter("2.txt"));
int len;
char[] chars = new char[1024];
while ((len = br.read(chars))!=-1){ //读数据
//写数据
bw.write(chars,0,len);
}
br.close();
bw.close();
//记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");
}
}