JavaSE-IO流
Java的IO通过java.io包下的类和接口来支持,在java.io包下主要包括输入、输出两种IO流,每种输入、输出流又可以分为字节流和字符流两大类。其中字节流以字节为单位来处理输入、输出操作,而字符流则以字符来处理输入、输出操作
Java7在java.nio及其子包下提供了一系列全新的API,这些API是对原有新IO的升级,因此也被称为NIO2,通过这些NIO2,程序可以更高效地进行输入、输出操作
File类
File类在包java.io.File下、代表操作系统的文件对象(文件、文件夹)
File类提供了诸如:定位文件,获取文件本身的信息、删除文件、创建文件(文件夹)等功能,File不能访问文件内容本身,如果需要访问文件内容,则需要使用输入/输出流
| File构造器 | 说明 |
|---|---|
| File(String pathname) | 根据文件路径创建文件对象 |
| File(String parent, String child) | 从父路径名字符串和子路径名字符串创建文件对象 |
| File(File parent, String child) | 根据父路径对应文件对象和子路径名字符串创建文件对象 |
| File(URI uri) |
File对象可以定位文件和文件夹;File封装的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的
// 绝对路径:从盘符开始
File f1 = new File("D:\\workspace\\IdeaProjects\\JavaSE\\HelloWorld");
// 相对路径:不带盘符,默认直接到当前工程下的目录寻找文件
File f2 = new File("a.txt");
File类常用方法
| 常用方法 | 返回值类型 | 说明 |
|---|---|---|
| getAbsolutePath() | String | 获取绝对路径 |
| getAbsoluteFile() | File | 获取绝对路径的File对象 |
| getPath() | String | 获取文件定义时使用的路径 |
| getName() | String | 获取文件的名称(带后缀)或路径名(如果是路径名,则只返回最后一级子路径名) |
| getParent() | String | 获取最后一级子目录的父目录名 |
| getParentFile() | File | 获取最后一级子目录的父目录名的File对象 |
| getCanonicalPath() | String | 获取规范路径;此方法首先将路径名转换为绝对路径 |
| getCanonicalFile() | File | 获取规范路径;此方法首先将路径名转换为绝对路径 |
| length() | long | 获取文件的大小(字节个数) |
| lastModified() | long | 获取文件的最后修改时间(毫秒值) |
| createNewFile() | boolean | 创建一个新的空文件 |
| delete() | boolean | 删除此文件或空文件夹,默认不能删除非空文件夹(不走回收站) |
| mkdir() | boolean | 只能创建一级文件夹 |
| mkdirs() | boolean | 可创建多级文件夹 |
| renameTo(File dest) | boolean | 重命名文件名或文件夹;如果成功返回true |
| exists() | boolean | 判断是否存在 |
| isFile() | boolean | 判断是否是文件 |
| isDirectory() | boolean | 判断是否是文件夹 |
| isAbsolute() | boolean | 判断是否是绝对路径 |
| isHidden() | boolean | 判断是否是一个隐藏文件 |
| canRead() | boolean | 判断文件/文件夹是否可以读取 |
| canWrite() | boolean | 判断文件/文件夹是否可以写入 |
| canExecute() | boolean | |
| createTempFile(String prefix, String suffix) | staitc File | 在默认的临时文件目录中创建一个临时的空文件 |
| createTempFile(String prefix, String suffix, File directory) | static File | 在指定的目录中创建一个临时的空文件 |
| deleteOnExit() | void | 注册一个删除钩子,指定当JVM退出时,删除File对象所对应的文件和目录 |
| list() | String[] | 获取当前目录下的所有一级文件和文件夹名称的String数组 |
| listFiles() | File[] | 获取当前目录下的所有一级文件和文件夹的File数组 |
| listRoots() | static File[] | 列出系统所有的根路径 |
| list(FilenameFilter filter) | String[] | 只会对符合条件的文件/文件夹进行迭代(底层就是FileFilter) |
| listFiles(FileFilter filter) | File[] | 只会对符合条件的文件/文件夹进行迭代 |
| listFiles(FilenameFilter filter) | File[] | 只会对符合条件的文件/文件夹进行迭代 |
| getFreeSpace() | long | |
| getTotalSpace() | long | |
| getUsableSpace() | long | |
| toPath() | Path | 转换为Path对象 |
| toURI() | URI | 转换为URI对象 |
| setLastModified(long time) | boolean | 设置最后一次修改时间 |
| setReadable(boolean readable) | boolean | 是指是否可读 |
| setReadable(boolean readable, boolean ownerOnly) | boolean | 是指是否可读 |
| setReadOnly() | boolean | 是指是否可读 |
| setWritable(boolean writable) | boolean | 是指是否可写 |
| setWritable(boolean writable, boolean ownerOnly) | boolean | 是指是否可写 |
| setExecutable(boolean executable) | boolean | |
| setExecutable(boolean executable, boolean ownerOnly) | boolean | |
| compareTo(File pathname) | int | 比较 |
| equals(Object obj) | boolean | 相等 |
| hashCode() | int | 哈希码 |
| toString() | String | 返回字符串 |
案例代码:查询指定目录下的指定文件
// 查询指定目录下的指定文件
public class Main {
public static void main(String[] args) throws IOException {
searchFile(new File("D:/"), "a.txt");
}
public static void searchFile(File dir, String fileName) {
// 判断dir是否是目录
if (dir != null && dir.isDirectory()) {
// 提取当前目录下的一级文件对象
File[] files = dir.listFiles();
// 判断是否存在一级文件对象,如果存在才能遍历
if (files != null && files.length > 0) {
for (File file : files) {
// 判断当前遍历的一级文件对象是文件还是目录
if (file.isFile()) {
// 如果是要找到的文件,把其路径输出即可
if (file.getName().contains(fileName)) {
System.out.println("找到了" + file.getAbsolutePath());
}
} else {
// 如果是文件夹,需要继续递归查找
searchFile(file, fileName);
}
}
}
} else {
System.out.println("对不起,当前搜索的位置不是文件夹!");
}
}
}
IO流框架
- I表示intput,输入流,读数据到内存
- O表示output,输出流,写数据到磁盘
字节流和字符流
字节流和字符流它们的操作完全一样,区别只是操作的数据单元不同而已——字节流操作的数据单元是字节,字符流操作的单元是字符
| 分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
|---|---|---|---|---|
| 抽象基类 | InputStream | OutputStream | Reader | Writer |
| 访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
| 访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
| 访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
| 访问字符串 | —— | —— | StringReader | StringWriter |
| 缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
| 转换流 | —— | —— | InputStreamReader | OutputStreamWriter |
| 对象流 | ObjectInputStream | ObjectOutputStream | —— | —— |
| 抽象基类 | FilterInputStream | FilterOutputStream | FilterReader | FilterWriter |
| 打印流 | —— | PrintStream | —— | PrintWriter |
| 推回输入流 | PushbackInputStream | —— | PushbackReader | —— |
| 特殊流 | DataInputStream | DataOutputStream | —— | —— |
代码案例:文件拷贝(高级流BufferedInputStream)
// 文件拷贝
String srcPath = "D:\\avatar.jpg";
String destPath = "D:\\new.jpg";
try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcPath));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destPath));) {
byte[] buffer = new byte[1024];
int len = 0;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
System.out.println("复制文件已完成~");
} catch (Exception e) {
e.printStackTrace();
}
代码案例:解决读取文件乱码的问题(使用转换流来解决)
// 获取正确编码的输入流(InputStreamReader:将字节输入流转换为字符输入流)
String srcPath = "D:/a.txt";
try (Reader reader = new InputStreamReader(new FileInputStream(srcPath), "GBK");
BufferedReader bufferedReader = new BufferedReader(reader);) {
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// 输出正确编码的输出流(OutputStreamWriter:字节输出流转换为字符输出流)
String destPath = "D:/b.txt";
try (Writer writer = new OutputStreamWriter(new FileOutputStream(destPath), "GBK");
BufferedWriter buffer = new BufferedWriter(writer);) {
buffer.write("hello 不二橘子酱!");
} catch (IOException e) {
e.printStackTrace();
}
代码案例:序列化与反序列化(使用对象流来处理)
@Data
public class Student implements Serializable {
private String name;
private transient String password;
private int age;
}
// 序列化:把内存中的对象存入到磁盘文件中
Student s = new Student("不二橘子酱", "123456", 18);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/a.txt"))) {
// 直接调用序列化方法
oos.writeObject(s);
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化:把磁盘中的对象数据转换成内存中的Java对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/a.txt"))) {
Student s = (Student) ois.readObject();
System.out.println(s); // Student{name='不二橘子酱', password='null', age=18}
} catch (Exception e) {
e.printStackTrace();
}
代码案例:打印流的区别(PrintStream/PrintWriter)
// 打印流:在打印数据功能上是一模一样的,区别在于PrintStream只能写字节数据;PrintWriter只能写字符数据
// PrintStream继承自OutputStream;PrintWriter继承自Writer
try (PrintStream ps1 = new PrintStream(new FileOutputStream("D:/a.txt"), true);
PrintStream ps2 = new PrintStream("D:/b.txt");
PrintWriter ps3 = new PrintWriter("D:/c.txt");
) {
ps2.println("我是打印流输出的,是什么就打印什么");
ps3.write("不二橘子酱");
} catch (Exception e) {
e.printStackTrace();
}