1.什么是IO
IO全称为input(输入)和output(输出),对于什么是输入和输出,用一张图来理解一下
以cpu为基准,数据朝着cpu过来,就是输入,而数据远离cpu,就是输出。例如在电脑上通过网络下载文件(网卡→硬盘),就是输入;把内存数据保存在硬盘上(内存→硬盘),就是输出。
2.文件的简单介绍
2.1 认识文件
对于文件,我们应该都不陌生。像文本文件,图片文件等等都是文件,文件夹也是一种文件,称为“目录文件”,同样保存在硬盘上。在硬盘上,存在很多的文件和文件夹,文件夹和文件存在一定的“嵌套关系”,整体的结构是一个树型结构,下图是一个简单的树型结构的演示。
2.2 路径
从根节点出发,一层一层往下,最终到达目标文件,中间这些目录集合在一起,就构成了路径。路径分为绝对路径和相对路径两种表示方法。
绝对路径(起点是此电脑):以盘符(C盘,D盘等等)开头的路径
相对路径(起点是任意路径):指定一个基准目录,从这个目录去定位文件,以 .(当前所在位置)或者 ..(当前目录的上一级目录位置)开头
2.3 文件的分类
文件主要分为两类:
1.文本文件:文件中保存的是字符串数据,每个部分都是合法的字符(例如.java,.c等后缀的文件)
2.二进制文件:文件中保存的是二进制数据(例如.mp3,.pdf等后缀的文件)
对于如何区分文本文件和二进制文件,这里提供一种简单的方法,可以通过记事本打开文件,如果不是乱码,就是文本文件,如果是乱码,就是二进制文件。
3.文件操作
java标准库提供了File类来表示一个文件,通过File类提供的方法,我们就可以进行文件系统操作。在进行文件操作之前,我们先来简单介绍一下Flie类。
3.1 File概述
3.1.1 属性
修饰符及类型 | 属性 | 说明 |
static String | pathSeparator | 依赖系统的路径分割符,String类型的表示 |
static char | pathSeparator | 依赖系统的路径分割符,char类型的表示 |
3.1.2 构造方法
签名 | 说明 |
File(File parent,String child) | 根据父目录+孩子文件路径,创建一个新的Flie实例 |
Flie(String Pathname) | 根据文件路径创建一个新的Flie实例,路径可以是绝对路径或者相对路径 |
Flie(String parent,String child) | 根据父目录+孩子文件路径,创建一个新的Flie实例,父目录用路径表示 |
3.1.3 方法及简单的使用
修饰符及返回值类型 | 方法签名 | 说明 |
String | getParent() | 返回File对象的父目录文件路径 |
String | getName() | 返回File对象的纯文件名称 |
String | getPath() | 返回File对象的文件路径 |
String | getAbsolutePath() | 返回File对象的绝对路径 |
String | getCanonicalPath() | 返回File对象的修饰过的绝对路径 |
boolean | exists() | 判断File对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断File对象代表的文件是否是一个目录 |
boolean | isFile() | 判断File对象代表的文件是否是一个普通文件 |
boolean | createNewFile() | 根据Flie对象,自动创建一个空文件。成功创建后返回true |
boolean | delete() | 根据File对象,删除该文件。成功删除后返回true |
void | deleteOnExit() | 根据File对象,标注文件将被删除,删除动作会到JVM运行结束时才会进行 |
String[ ] | list() | 返回File对象代表的目录下的所有文件名 |
File[ ] | listFiles() | 返回File对象代表的目录下的所有文件,以File对象表示 |
boolean | mkdir() | 创建File对象代表的目录 |
boolean | mkdirs() | 创建File对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(File dest) | 进行文件改名,也可以视为我们平时的剪切,粘贴操作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class File_test {
public static void main(String[] args) throws IOException {
File f =new File("d:/test.txt");//文件不一定要真实存在
System.out.println("父目录文件路径:"+f.getParent());
System.out.println("文件名称:"+f.getName());
System.out.println("文件路径:"+f.getPath());
System.out.println("绝对路径:"+f.getAbsoluteFile());
System.out.println("相对路径:"+f.getCanonicalFile());
System.out.println("文件是否存在:"+f.exists());
System.out.println("文件是否是普通文件:"+f.isFile());
System.out.println("文件是否是目录:"+f.isDirectory());
f.createNewFile();//创建文件
System.out.println("创建文件后文件是否存在:"+f.exists());
Scanner scanner=new Scanner(System.in);
f.deleteOnExit();
scanner.next();//把程序阻塞住
System.out.println("删除成功");
}
}
运行结果如下:
3.2 文件内容的读写
在Java中,用来读写文件内容的"流"是一组类,其中提供的类有很多,但是整体上可以分成两组,字节流与字符流。字符流以字符为单位读写数据,字节流以字节为单位读写数据。
3.2.1 字节流--InputStream
修饰符及返回类型 | 方法签名 | 说明 |
int | read() | 读取一个字节的数据,返回-1代表已经完全读完了 |
int | read(byte[ ] b) | 最多读取b数组长度字节的数据到b中,返回实际读到的数量,-1代表已经读完了 |
int | read(byte[ ] b,int off,int len) | 最多读取len-off字节的数据到b中,放在从off开始,返回实际读取到的数量,-1代表已经读完了 |
void | close() | 关闭字节流 |
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStream_test {
public static void main(String[] args) {
try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
//代码执行出try代码块时,自动调用inputStream的close
//只有实现了Closeable接口的类才能放到try代码块中
while (true) {
byte[] bytes = new byte[1024];
int n = inputStream.read(bytes);
if(n==-1){
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("0x%x ", bytes[i]);
}
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
3.2.2 字节流--OutputStream
修饰符及返回值类型 | 方法签名 | 说明 |
void | write(int b) | 写入要给字节的数据 |
void | write(byte[ ] b) | 将b这个字符数组中的数据全部写入 |
int | write(byte[ ] b,int off,int len) | 将b这个字符数组中从off开始的数据写入,一共len个 |
void | close() | 关闭字节流 |
void | flush() | 大多的OutputStream为了减少设备操作的次数,在写数据的时候会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区里。需要在最后或者合适的位置,调用flush这个刷新操作,将数据刷新到设备中 |
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class OutputStream_test {
public static void main(String[] args) {
try(OutputStream outputStream=new FileOutputStream("d:/test.txt",true)){
//添加true会将新写入的数据追加在之前内容的末尾,如果不添加true,写入时会把文件原有内容清空掉
outputStream.write(97);//写入字母a
outputStream.write(98);//写入字母b
}
catch (IOException e){
e.printStackTrace();
}
}
}
3.2.3 字符流--Reader
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Reader_test {
public static void main(String[] args) {
try(Reader reader=new FileReader("d:/test.txt")){
while(true){
int b=reader.read();//读取一个字符,返回unicode编码
if(b==-1){
break;
}
char ch=(char)b;
System.out.println(ch);
}
}
catch (IOException e){
e.printStackTrace();
}
}
}
3.2.4 字符流--Writer
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Writer_test {
public static void main(String[] args) {
try(Writer writer=new FileWriter("d:/test.txt",true)){
writer.write("hello world!");//一次写入多个字符
}
catch (IOException e){
e.printStackTrace();
}
}
}