Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
本文从流操作、文件操作方面总结。
流(Stream)
流的本质是数据传输,根据处理数据类型的不同,流可以分为两大类:字节流和字符流。字节流以字节(8bit)为单位,包含两个抽象类:InputStream
和OutputStream
。字符流以字符(16bit)为单位,包含两个抽象类:Reader
和Writer
。
下图是一个描述输入流和输出流的类层次图(图片来自菜鸟教程)。
FileInputStream / FileOutputStream
构造方法(输入流为例)
使用字符串类型的文件名来创建一个输入流对象来读取文件:
InputStream f = new FileInputStream("C:/java/hello");
使用一个文件对象来创建一个输入流对象来读取文件:
File f = new File("C:/java/hello"); InputStream out = new FileInputStream(f);
注意,如果输入流在打开文件进行输出前目标文件不存在,会抛出异常;但是输出流在打开文件进行输出前目标文件不存在,该流会创建该文件。
带缓冲的字节流读写数据举例
import java.io.*; public class Main { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("movie.mp4"); BufferedInputStream bis = new BufferedInputStream(fis); FileOutputStream fos = new FileOutputStream("movie_copy.mp4"); BufferedOutputStream bos = new BufferedOutputStream(fos); byte[] input = new byte[100000]; int count = 0; long begin = System.currentTimeMillis(); while (bis.read(input) != -1) { bos.write(input); count++; } long time = System.currentTimeMillis() - begin; bos.close(); fos.close(); bis.close(); fis.close(); System.out.println("读取了 " + count + " 次"); System.out.println("花费时间 " + time + " 毫秒"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
运行结果:拷贝了mp4文件,并输出
读取了 154 次 花费时间 10 毫秒
数组大小可以改变,大文件对应的数组大一些,小文件对应的小一些。注意,这个数组不是用来缓冲的,即不是用来减少IO次数的,缓冲区在BufferedReader构造函数中可设置。
InputStreamReader / OutputStreamWriter
字符流到字节流的桥梁。能将字节流输出为字符流,并且能为字节流指定字符集,可输出一个个的字符。
不带缓冲的字节流读写示例:
import java.io.*;
public class Main {
public static void main(String[] args) {
File file = new File("text.txt");
try {
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
FileOutputStream fos = new FileOutputStream("text_copy.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
char[] input = new char[100];
int l = -1;
while ((l = isr.read(input)) != -1) {
osw.write(input, 0, l);
}
osw.close();
fos.close();
isr.close();
fis.close();
System.out.println("done!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader / FileWriter
FileReader类从InputStreamReader类继承而来,该类按字符读取流中数据。
不带缓冲的字符流读写数据示例:
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("Hello1.txt");
// 创建文件
file.createNewFile();
// creates a FileWriter Object
FileWriter writer = new FileWriter(file);
// 向文件写入内容
writer.write("This\n is\n an\n example\n");
writer.flush();
writer.close();
// 创建 FileReader 对象
FileReader fr = new FileReader(file);
char [] a = new char[50];
// 读取数组中的内容
int l = fr.read(a) ;
for(int i = 0; i < l; i++)
System.out.print(a[i]); // 一个一个打印字符
fr.close();
}
}
随机读写流
过滤流
数据流
还有ByteArrayInputStream类、DataInputStream类等介绍,详见JDK文档手册
文件操作
Java文件类以抽象的方式代表文件名和目录路径名。该类主要用于文件和目录的创建、文件的查找和文件的删除等。File对象代表磁盘中实际存在的文件和目录。
构造方法:
File(String pathname) ;
成员方法:
public String getName()
返回由此抽象路径名表示的文件或目录的名称。public String getParent()
返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null。public File getParentFile()
返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null。public String getPath()
将此抽象路径名转换为一个路径名字符串。public boolean isAbsolute()
测试此抽象路径名是否为绝对路径名。public String getAbsolutePath()
返回抽象路径名的绝对路径名字符串。public boolean exists()
测试此抽象路径名表示的文件或目录是否存在。public boolean isDirectory()
测试此抽象路径名表示的文件是否是一个目录。public boolean isFile()
测试此抽象路径名表示的文件是否是一个标准文件。public boolean createNewFile() throws IOException
当且仅当不存在具有此抽象路径名指定的名称的文件时,原子地创建由此抽象路径名指定的一个新的空文件。public boolean delete()
删除此抽象路径名表示的文件或目录。public String[] list()
返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。public File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。public boolean mkdir()
创建此抽象路径名指定的目录。public boolean mkdirs()
创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。public boolean renameTo(File dest)
重新命名此抽象路径名表示的文件。
读取控制台输入方法
Java 的控制台输入由 System.in 完成。为了获得一个绑定到控制台的字符流,可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。
举例:
读取字符:import java.io.*; public class BRRead { public static void main(String args[]) throws IOException { char c; // 使用 System.in 创建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("输入字符, 按下 'q' 键退出。"); // 读取字符 do { c = (char) br.read(); System.out.println(c); } while(c != 'q'); } }
读取字符串:
import java.io.*; public class BRReadLines { public static void main(String args[]) throws IOException { // 使用 System.in 创建 BufferedReader BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("Enter lines of text."); System.out.println("Enter 'end' to quit."); do { str = br.readLine(); System.out.println(str); } while(!str.equals("end")); } }
Scanner类
详见博客Java Scanner类从控制台读取输入