1、基础概念
1.1、文件(File)
文件的读写可以说是开发中必不可少的部分,因为系统会存在大量处理设备上的数据,这里的设备指硬盘,内存,键盘录入,网络传输等。当然这里需要考虑的问题不仅仅是实现,还包括同步,读写熟读,文件类型等等都需要考虑在具体的项目中。
Java 的标准库 java.io
提供了File类的实例对象来操作文件
1.2、流(Stream)
I/O是Input/Output的缩写, I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。
Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行。
java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
2、文件(File)
2.1、File类创建
名称 | 说明 |
public File(String pathname) | 根据文件路径创建对象 |
public File(String parent,String child) | 从父路径名字符串和子路径名字字符串创建文件对象 |
public File(File parent,String child) | 根据父路径对应文件对象和子路径名字字符串创建对象 |
2.2、常用方法
public String getAbsolutePath() 获取绝对路径
public String getPath() 获取路径
public String getName() 获取名称
public String getParent() 获取上层文件目录路径。若无,返回null
public long length() 获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified() 获取最后一次的修改时间,毫秒值
public String[] list() 获取指定目录下的所有文件或者文件目录的字符串数组
public File[] listFiles() 获取指定目录下的所有文件或者文件目录的File对象数组
public boolean isDirectory() 判断是否是文件目录
public boolean isFile() 判断是否是文件
public boolean exists() 判断是否存在
public boolean canRead() 判断是否可读
public boolean canWrite() 判断是否可写
public boolean isHidden() 判断是否隐藏
2.3、实例
public class FileTest {
public static void main(String[] args) throws IOException {
//1、设置目录名称
String filePath = "H:\\test";
//2、设置文件名称
String fileName = "test.txt";
//添加文件目录
File file = new File(filePath);
//1、判断是否存在目录
boolean exists = file.exists();
System.out.println("路径"+filePath+"在磁盘中是否存在:"+exists);
//2、不存在,创建目录
if (!exists) {
boolean b = file.mkdirs();// 在磁盘中指定路径下创建目录
System.out.println("创建目录是否成功:"+b);
}else {
System.out.println("创建目录已经存在");
}
//3、再判断是否存在目录
boolean exists1 = file.exists();
System.out.println("路径"+filePath+"在磁盘中是否存在:"+exists1);
//判断传入的抽象路径名是否是一个在磁盘中已存在的文件
System.out.println("判断传入的抽象路径名是否是一个在磁盘中已存在的文件:"+file.isFile());// false
//判断传入的抽象路径名是否是一个在磁盘中已存在的目录
System.out.println("判断传入的抽象路径名是否是一个在磁盘中已存在的目录:"+file.isDirectory());// true
System.out.println("获取绝对路径"+file.getAbsolutePath());
System.out.println("获取路径"+file.getPath());
System.out.println("获取名称"+file.getName());
System.out.println("获取上层文件目录路径。若无,返回null"+file.getParent());
System.out.println("获取文件长度(即:字节数)。不能获取目录的长度"+file.length());
System.out.println("获取最后一次的修改时间,毫秒值"+new Date(file.lastModified()));
System.out.println("获取指定目录下的所有文件或者文件目录的字符串数组:"+file.list());
System.out.println("获取指定目录下的所有文件或者文件目录的File对象数组:"+file.listFiles());
//从磁盘中删除指定文件路径下的文件或者文件目录
// file.delete();
// System.out.println("再次判断传入的抽象路径名(目录/普通文件)在磁盘中是否存在:"+file.exists());// false
System.out.println("=================================================================================");
//添加文件
File f = new File(filePath,fileName);
//1、判断是否存在目录
boolean e = f.exists();
System.out.println("路径"+filePath+"在磁盘中是否存在:"+e);
//2、不存在,创建文件
if (!e) {
boolean b = f.createNewFile();
System.out.println("创建文件是否成功:"+b);
}else {
System.out.println("创建文件已经存在");
}
//3、再判断是否存在目录
boolean e1 = f.exists();
System.out.println("路径"+filePath+"在磁盘中是否存在:"+e1);
// 判断传入的抽象路径名是否是一个在磁盘中已存在的文件
System.out.println("判断传入的抽象路径名是否是一个在磁盘中已存在的文件:"+f.isFile());// false
// 判断传入的抽象路径名是否是一个在磁盘中已存在的目录
System.out.println("判断传入的抽象路径名是否是一个在磁盘中已存在的目录:"+f.isDirectory());// true
System.out.println("判断是否可读"+f.canRead());
System.out.println("判断是否可写"+f.canWrite());
System.out.println("判断是否隐藏"+f.isHidden());
System.out.println("获取绝对路径"+f.getAbsolutePath());
System.out.println("获取路径"+f.getPath());
System.out.println("获取名称"+f.getName());
System.out.println("获取上层文件目录路径。若无,返回null"+f.getParent());
System.out.println("获取文件长度(即:字节数)。不能获取目录的长度"+f.length());
System.out.println("获取最后一次的修改时间,毫秒值"+new Date(f.lastModified()));
System.out.println("获取指定目录下的所有文件或者文件目录的字符串数组:"+f.list());
System.out.println("获取指定目录下的所有文件或者文件目录的File对象数组:"+f.listFiles());
// 从磁盘中删除指定文件路径下的文件或者文件目录
// f.delete();
// System.out.println("再次判断传入的抽象路径名(目录/普通文件)在磁盘中是否存在:"+file.exists());// false
}
}
3、流的分类
- 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
- 按数据流的流向不同分为:输入流,输出流
补充:
- 按流的角色的不同分为:节点流,处理流
节点流:直接从数据源或目的地读写数据
处理流:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
3.1、IO 流体系图
3.2、派生类
Java的IO流共涉及40多个类,实际上非常规则,都是从以上4个抽象基类派生的,并且子类名称都是以其父类名作为子类名后缀。
4、字节流
字节流分为字节输入流InputStream和字节输出流OutputStream,其中输入与输出是相对于内存而言的;输入即从文件中读出数据输入至内存;输出即从内存向文件中输出数据。
从jdk8文档中,InputStream 方法如下:
OutputStream方法如下:
从 Java 9 开始,InputStream 新增加了多个实用的方法:
readAllBytes():读取输入流中的所有字节,返回字节数组。
readNBytes(byte[] b, int off, int len):阻塞直到读取 len 个字节。
transferTo(OutputStream out):将所有字节从一个输入流传递到一个输出流。
4.1、实例
public class FileStreamTest {
public static void main(String[] args) throws IOException {
//写入
FileOutputStream fileOutputStream = new FileOutputStream("H:\\test\\test.txt");
String s = "test123";
// 将字符串转换为byte数组
byte[] outBytes = s.getBytes();
fileOutputStream.write(outBytes);
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("=================================================================");
//读取
FileInputStream fileInputStream = new FileInputStream("H:\\test\\test.txt");
//1、返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
int available = fileInputStream.available();
System.out.println("available:" + available);
//2、跳过并丢弃来自此输入流的 2字节数据。
// long skip = fileInputStream.skip(2);
// System.out.println("skip:" + skip);
//3、读取文件内容,为了减少IO,我们创建一个Byte数组作为接收缓冲区
byte[] inBytes = new byte[available];
int read;
//4、从输入流读取一些字节数,并将它们存储到缓冲区 b 。
while ((read = fileInputStream.read(inBytes)) != -1) {
// 把byte数组转换成字符串
System.out.print(new String(inBytes, 0, read));
}
if (fileInputStream != null) {
fileInputStream.close();
}
}
}
5、字符流
已经有字节流了,可以读取任意文件,为什么还要有字符流呢?
- 对于字符文件,先作为字节传输,再转成字符,耗时耗力。
- 对于字符文件,转成字节之后,再转回来,如果是中文,很容易乱码。
5.1、Reader
5.2、Writer
5.3、实例
public class FileStreamTest {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("H:\\test\\test.txt");
String s = "少年";
fw.write(s); // 将字符串写入文件
// 关闭资源
fw.close();
FileReader fr = new FileReader("H:\\test\\test.txt");
String str = new String();
int b;
// 循环读取
while ((b = fr.read())!=-1) {
str = str + (char)b;
}
System.out.println("str:"+str);
// 关闭资源
fr.close();
}
}
- flush :刷新缓冲区,流对象可以继续使用。
- close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。