一、流的概念
流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。 一个流,必有源端和目的端。
流机制是Java及C++中的一个重要机制,通过流我们可以自由地控制文件、内存、IO(Input输入/Output输出)设备等数据的流向。而IO流就是用于处理设备上的数据,如:硬盘、内存、键盘录入等。
一个形象的比喻是——水流,文件===程序,文件和程序之间连接一个管道,水流就在管道中形成了,自然也就出现了方向:可以流进,也可以流出
二、流的分类
- 根据处理数据的单位不同可分为字节流和字符流
- 根据流向的不同可分为输入流和输出流
- 根据流的功能可以分为节点流(低级流)和处理流(高级流,也叫过滤流)
字节流:以字节为单位操作流
- InputStream
- OutputStream
字符流:以字符为单位操作流
- Reader
- Writer
输入流:从程序角度来看,输入到程序中的流
- InputStream
- Reader
输出流:从程序角度来看,从程序中输出的流
- OutputStream
- Writer
节点流:直接与数据源相连,操作流
处理流:直接使用节点流,读写不方便,为了更快的读写文件,有了处理流。处理流不直接连接数据源,而是连接在已存在的流(节点流或处理流)上,通过对数据的处理为程序提供更强大的处理能力
三、文件类
java.io包中的File类提供了管理文件与目录的功能,是文件和目录路径名的抽象表示形式。该类也是我们在使用IO流的时候经常会用到的一个类。下面列举类中常用到的方法:
|方法 |说明 ||:--------------|:----------------------------------------------------------||delete() |删除文件或目录,如果此路径名表示一个目录,则该目录必须为空才能删除 ||exists() |判断文件或目录是否存在 ||isFile() |判断是否为文件 ||isDirectory() |判断是否为目录 ||lastModified() |获取最后一次修改时间 ||length() |获得文件的长度 ||list() |返回一个字符串数组,这些字符串指定目录中的文件和子目录 ||listFiles() |返回一个抽象路径名数组,这些路径名表示此目录中的File对象 ||mkdir() |创建此抽象路径名指定的目录 ||mkdirs() |创建此抽象路径名指定的目录,包括所有必需但不存在的父目录 |
更多方法的详细信息,请参考JDK API文档查看
四、如何使用
1. 文件类
import java.io.File;
import java.io.IOException;
import java.util.Date;
/**
* File类测试
* @author 小明
*
*/
public class FileTest {
public static void main(String[] args) {
// 创建File对象
File file = new File("E:\\jg\\exercise_bak.txt");
// 能否读
System.out.println("能否读:" + file.canRead());
// 删除
System.out.println("删除成功:" + file.delete());
// 重新创建文件对象
file = new File("E:\\jg\\exercise_bak.txt");
// 判断文件是否存在
System.out.println("是否存在:" + file.exists());
// 目录或文件名称
System.out.println("名称:" + file.getName());
// 是否目录、文件
System.out.println("是否目录:" + file.isDirectory());
System.out.println("是否文件:" + file.isFile());
// 最后一次修改时间
System.out.println("最后一次修改时间:" + new Date(file.lastModified()));
// 文件大小
System.out.println("文件大小:" + file.length());
// 重新创建File对象
file = new File("E:\\jg");
System.out.println("文件目录列表:");
// 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录
String[] list = file.list();
for (String string : list) {
System.out.println(string);
}
System.out.println("*******************************");
// 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件对象
File[] files = file.listFiles();
for (File item : files) {
if (item.isDirectory()) { // 当前File对象为目录,则遍历该目录下所有子目录与文件
System.out.println(item.getName() + " 目录下子目录与文件:");
String[] it = item.list();
for (String i : it) {
System.out.println(i);
}
System.out.println("*******************************");
continue;
}
System.out.println(item.getName() + " 文件");
}
// 重新创建File对象
file = new File("E:\\jg\\test\\demo\\test.txt");
if (!file.exists()) { // 文件不存在
// 获取文件路径
File dir = file.getParentFile();
if (!dir.exists()) { // 目录不存在,则创建路径中所有不存在的目录
dir.mkdirs();
}
try {
// 创建空文件
System.out.println("文件是否创建成功:" + file.createNewFile());
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2. 字节流
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;
/**
* 字节输入输出流测试
*
* @author 小明
*
*/
public class IOTest {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer(); // 字符串缓冲
/* 输入流 */
InputStream in = null;
try {
// 1. 打开输入流
in = new FileInputStream("E:\\jg\\exercise.txt");
// 2. 读取
byte[] b = new byte[1024 * 4];
int len = in.read(b); // 返回读取到的字节数,返回-1表示读取到流结尾
while(len != -1){
buffer.append(new String(b, 0, len)); // 将读取到的字节解析为String追加到缓冲
len = in.read(b);
}
System.out.println(buffer.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3. 释放资源,关闭输入流
if (in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/* 输出流 */
OutputStream out = null;
try {
File file = new File("D:\\test\\demo\\test.txt");
if (!file.getParentFile().exists()){ // 文件路径不存在,则创建路径中所有不存在的目录
file.getParentFile().mkdirs();
}
// 1. 打开输出流
out = new FileOutputStream(file);
// 2. 写
out.write(buffer.toString().getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3. 释放输出流资源
if (out != null){
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3. 字符流
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
/**
* 字符输入输出流测试
*
* @author 小明
*
*/
public class IOTest2 {
public static void main(String[] args) {
StringBuffer buffer = new StringBuffer();
/* 输入流 */
Reader reader = null;
try {
// 1. 打开流
reader = new FileReader("E:\\jg\\exercise.txt");
// 2. 读取
char[] ch = new char[128]; // 缓冲区
int len;
do {
len = reader.read(ch);
if (len == -1)
break;
buffer.append(new String(ch, 0, len));
} while (len != -1);
System.out.println(buffer.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3. 释放资源
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/* 输出流 */
Writer writer = null;
try {
// 1. 打开流
writer = new FileWriter("d:\\test.txt");
// 2. 写入
writer.write(buffer.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
// 3. 释放资源
if (writer != null) {
try {
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
归纳总结
-
流的使用步骤:
- 打开一个输入/输出流对象
- 读取或写入数据
- 释放资源,关闭输入/输出流对象
-
InputStream和OutputStream主要用来处理可以被直接读作byte的数字
- Reader和Writer主要用来处理文本