一、File类的使用
1、File类的一个对象代表一个文件或一个文件目录。
2、File类声明在java.io包下。
3、创建File类的实例
3.1、构造器一:File(String pathname)。
3.2、构造器二:File(String parent, String child)。
3.3、构造器三:File(File parent, String child)。
@Test
public void test(){
//构造器一
//通过文件相对路径创建File类实例
File file = new File("hello.txt");//相对于当前类文件所在module的根目录
//通过文件绝对路径创建File类实例
File file1 = new File("F:\\program\\LearnJava\\IOTest\\hello.txt");
//构造器二
File file2 = new File("F:\\program\\LearnJava","IOTest");
//构造器三
File file3 = new File(file2,"hello.txt");
}
4、创建File实例的注意点:
4.1、路径
4.1.1、绝对路径:包含盘符在内的文件或文件目录的路径。
4.2.2、相对路径:相对于某个路径下指明的路径
4.2、路径分隔符
4.2.1、Windows:\\
4.2.2、Unix:/
5、File类的功能
5.1、File类的获取功能
5.1.1、public String getAbsolutePath():获取绝对路径
5.1.2、public String getPath():获取路径
5.1.3、public String getName():获取名称
5.1.4、public String getParent():获取上层文件目录,若没有,返回null
5.1.5、public long length():获取文件长度
5.1.6、public long lastModified():获取最后一次修改时间,返回时间戳
5.1.7、public String[] list():获取文件目录中的内容,返回String数组(相对路径)
5.1.8、public File[] listFiles():获取文件目录中的内容,返回File数组(绝对路径)
5.2、File类的重命名功能
5.2.1、public boolean renameTo(File dest):把文件重命名为指定的文件路径
5.3、File类的判断功能
5.3.1、public boolean isDirectory():判断是否是文件目录
5.3.2、public boolean isFile():判断是否是文件
5.3.3、public boolean exists():·判断是否存在
5.3.4、public boolean canRead():判断是否可读
5.3.5、public boolean canWrite():判断是否可写
5.3.6、public boolean isHidden():判断是否隐藏
5.4、File类的创建功能
5.4.1、public boolean createNewFile():创建文件
5.4.2、public boolean mkdir():创建文件夹
5.4.5、public boolean mkdirs():创建文件夹,如果上级文件夹不存在,一并创建
5.5、File类的删除功能
5.5.1、public boolean delete() :删除文件或文件夹
@Test
public void test1() throws IOException {
File file = new File("hello.txt");
File file1 = new File("F:\\program\\LearnJava\\IOTest\\hello.txt");
//获取绝对路径
System.out.println(file.getAbsolutePath());//F:\program\LearnJava\IOTest\hello.txt
//获取路径
System.out.println(file.getPath());//hello.txt
//获取名称
System.out.println(file.getName());//hello.txt
//获取上层文件目录,若没有,返回null
System.out.println(file.getParent());//null
//获取文件长度
System.out.println(file.length());//10
//获取最后一次修改时间,返回时间戳
System.out.println(new Date(file.lastModified()));//Thu May 27 23:37:48 CST 2021
System.out.println("**********************************");
System.out.println(file1.getAbsolutePath());//F:\program\LearnJava\IOTest\hello.txt
System.out.println(file1.getPath());//F:\program\LearnJava\IOTest\hello.txt
System.out.println(file1.getName());//hello.txt
System.out.println(file1.getParent());//F:\program\LearnJava\IOTest
System.out.println(file1.length());//10
System.out.println(file1.lastModified());//1622129868338
File file2 = new File("F:\\program\\LearnJava");
String[] list = file2.list();
//遍历文件目录中的内容(相对路径)
System.out.println(Arrays.toString(list));//[.idea, compareTest, DateTimeTest, IOTest, jihe, LearnJava.iml, Lock, out, StringTest, Thread]
File[] files = file2.listFiles();
遍历文件目录中的内容(绝对路径)
System.out.println(Arrays.toString(files));//[F:\program\LearnJava\.idea, F:\program\LearnJava\compareTest, F:\program\LearnJava\DateTimeTest, F:\program\LearnJava\IOTest, F:\program\LearnJava\jihe, F:\program\LearnJava\LearnJava.iml, F:\program\LearnJava\Lock, F:\program\LearnJava\out, F:\program\LearnJava\StringTest, F:\program\LearnJava\Thread]
File file3 = new File("he.txt");
//把文件重命名为指定的文件路径
// System.out.println(file.renameTo(file3));
//判断是否是文件目录
System.out.println(file.isDirectory());//false
//判断是否是文件
System.out.println(file.isFile());//true
//判断是否存在
System.out.println(file.exists());//true
//判断是否可读
System.out.println(file.canRead());//true
//判断是否可写
System.out.println(file.canWrite());//true
//判断是否隐藏
System.out.println(file.isHidden());//false
File file4 = new File("hahaha.txt");
if (!file4.exists()) {
//创建文件
System.out.println(file4.createNewFile());//true
}
File file5 = new File("win");
if (!file5.exists()) {
//创建文件夹
System.out.println(file5.mkdir());//true
}
File file56 = new File("wins/test");
if (!file56.exists()) {
//创建文件夹,如果上级文件夹不存在,一并创建
System.out.println(file56.mkdirs());//true
}
//删除文件或文件夹
System.out.println(file56.delete());//true
}
6、File类中涉及到关于文件或文件夹创建、删除、重命名、修改时间、文件大小等方法,并未涉及到写入或读取文件内容的操作,如果需要读取或写入文件内容,必须使用IO流完成。
7、后续File类的对象会作为参数传递到流的构造器中,指明读取或写入的“终点”。
二、流的分类
1、按操作的数据单位划分:字节流、字符流。
2、按数据的流向划分:输入流、输出流。
3、按流的角色划分:节点流、处理流。
三、流的体系结构
抽象基类(及用到的方法) | 节点流(文件流) | 缓冲流(处理流的一种) | |
字节流 | InputStream | FileInputStream(read(byte[] buffer)) | BufferedInputStream(read(byte[] buffer)) |
字节流 | OutPutStream | FileOutPutStream(write(byte[] buffer , 0 , len)) | BufferedOutPutStream(write(byte[] buffer , 0 , len),flush()刷新缓冲区) |
字符流 | Reader | FileReader(read(char[] cbuf)) | BufferedReader(read(char[] cbuf),readLine()) |
字符流 | Writer | FileWriter(write(char[] cbuf, 0 , len)) | BufferedWriter(write(char[] cbuf, 0 , len),flush()刷新缓冲区) |
1、FileReader
1.1、read( )的理解:返回读入的一个字符,如果达到文件末尾,返回负一。
1.2、异常处理:为保证溜资源一定可以执行关闭操作,需要使用try-catch-finally处理。
1.3、读入的文件一定要存在,否则会抛出FileNotFoundException。
@Test
public void testFileReader() {
//实例化File对象
File file = new File("hello.txt");
FileReader fr = null;
try {
//数据流实例化
fr = new FileReader(file);
//数据读入
//返回读入的字符,如果到达文件末尾,返回-1
//方式一:
/* int read = fr.read();
while (read != -1) {
System.out.println(fr.read());
read = fr.read();
}*/
//方式二:
int data;
while ((data = fr.read()) != -1) {
System.out.println((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//手动关闭连接资源
try {
if (fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.4、使用read( char [ ] cbuf )读入数据
@Test
public void readCharTest() {
FileReader fr = null;
try {
File file = new File("hello.txt");
fr = new FileReader(file);
char[] cbuf = new char[5];
int len;
while ((len = fr.read(cbuf)) != -1) {
//方式一、
/* for (int i = 0; i < len; i++) {
System.out.print(cbuf[i]);//hello File
}*/
//方式二
System.out.println(new String(cbuf,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2、FileWriter
2.1、输出操作:对应的File文件可以不存在。并不会抛异常。
2.2、File对应的硬盘路径中的文件如果存在:
如果调用的构造器是FileWriter(File file)或FileWriter(File file, boolean append)append为false,则会对原有文件进行覆盖。
如果调用的构造器是FileWriter(File file, boolean append)append为true,则会对原有文件内容进行追加。
@Test
public void fileWriterTest() {
FileWriter fw = null;
try {
File file = new File("hello.txt");
//fw = new FileWriter(file);
fw = new FileWriter(file,true);
fw.write("I have a dream!");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、使用FileReader和FileWriter进行文件复制
@Test
public void readAndWriteTest() {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
//创建File类对象,指定读取和写入的文件位置。
File reF = new File("hello.txt");
File wrF = new File("hi.txt");
//创建输入输出对象
fileReader = new FileReader(reF);
fileWriter = new FileWriter(wrF);
//数据的读入和写出
char[] cbuf = new char[5];
int len;
while ((len = fileReader.read(cbuf)) != -1) {
fileWriter.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭输入输出流。
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4、FileInputStream和FileOutPutStream
4.1、Stream处理文本文件可能会出现乱码,如果只是复制则不会乱码。
4.2、字节流多用于读取和传输非文本文件,比如:jpg,doc,pdf等。
4.3、字节流读写非文本文件:
@Test
public void testCopy(){
copyFile("F:\\program\\LearnJava\\IOTest\\360wallpaper.jpg","F:\\program\\LearnJava\\IOTest\\360wallpaper23.jpg");
}
public void copyFile(String oldFilePath,String newFilePath){
FileInputStream inputStream = null;
FileOutputStream fileOutputStream = null;
try {
//通过匿名对象创建文件对象,创建字节流对象
inputStream = new FileInputStream(new File(oldFilePath));
fileOutputStream = new FileOutputStream(new File(newFilePath));
//读写
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (inputStream!=null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream!=null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5、处理流之一:缓冲流的使用
5.1、缓冲流 :BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
5.2、作用:提高流的读取,写入速度。
提高速度的原因:内部提供了一个缓冲区。
5.3、字节缓冲流复制文件
@Test
public void testCopy() {
long startTime = System.currentTimeMillis();
copyFileWithBuffered("E:\\工具\\CentOS-7-x86_64-DVD-1810.iso", "E:\\copy\\CentOS-7-x86_64-DVD-1810.iso");
long endTime = System.currentTimeMillis();
System.out.println("耗时" + (endTime - startTime));
}
public void copyFileWithBuffered(String oldFilePath, String newFilePath) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
//通过匿名对象创建文件对象,创建字节流对象
FileInputStream inputStream = new FileInputStream(new File(oldFilePath));
FileOutputStream fileOutputStream = new FileOutputStream(new File(newFilePath));
//
bufferedInputStream = new BufferedInputStream(inputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//读写
byte[] bytes = new byte[1024];
int len;
while ((len = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if (bufferedInputStream != null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedOutputStream != null) {
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5.4、字符缓冲流复制文本文件
@Test
public void test() {
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new FileReader(new File("hello.txt")));
writer = new BufferedWriter(new FileWriter(new File("hello1.txt")));
//方式一:
/* char[] chars = new char[1024];
int len;
while ((len = reader.read(chars)) != -1) {
writer.write(chars, 0, len);
}*/
//方式二:
String data;
while ((data = reader.readLine()) != null) {
//方法一:
// writer.write(data + "\n");//data中不包含换行符
//方法二:
writer.write(data);
writer.newLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6、转换流的使用
6.1、转换流:属于字符流
InputStreamReader:将一个字节的输入流,转换成字符的输入流。
OutputStreamWriter:将一个字节的输出流,转换为字符的输出流。
6.2、作用:提供字节流与字符流之间的转换。
6.3、编码:字节、字节数组 --------> 字符数组、字符串
解码:字符数组、字符串 --------> 字节、字节数组
@Test
public void test() {
InputStreamReader reader = null;
OutputStreamWriter writer = null;
try {
reader = new InputStreamReader(new FileInputStream(new File("hello.txt")), "UTF-8");
writer = new OutputStreamWriter(new FileOutputStream(new File("hello1.txt")), "UTF-8");
char[] chars = new char[20];
int len;
while ((len = reader.read(chars)) != -1) {
System.out.println(new String(chars, 0, len));
writer.write(chars, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6.4、字符集
6.4.1、ASCII:美国标准信息交换码,用一个字节的7位表示。
6.4.2、ISO8859-1:拉丁码表,欧洲码表,用一个字符的8位表示
6.4.3、GB2312:中国的中文编码表,最多两个字节编码所有字符。
6.3.4、GBK:中国的中文编码表升级,融合了更多的中文文字符号,最多两个字节编码。
6.3.5、Unicode:国际标准编码,融合了人类使用的所有字符,为每个字符分配唯一的字符码,所有的文字都用两个字节来表示。
6.3.6、UTF-8:变长的编码方式,可用1~4个字节表示一个字符。
7、对象流的使用
7.1、ObjectOutputStream和ObjectInputStream
7.2、作用:用于存储和读取基本数据类型数据或对象的处理流,他的强大之处就是可以把Java对象写入到数据源中,也可将对象从数据源中还原回来。
@Test
public void test() {
//序列化过程 :将内存中的Java对象保存到磁盘中,或通过网络传输出去。
//使用ObjectOutputStream
ObjectOutputStream outputStream = null;
try {
outputStream = new ObjectOutputStream(new FileOutputStream(new File("object.dat")));
outputStream.writeObject(new Date());
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void test1(){
//反序列化过程 :将磁盘中的Java对象读取到内存中,或通过网络接收。
//使用ObjectInputStream
ObjectInputStream inputStream = null;
try {
inputStream = new ObjectInputStream(new FileInputStream(new File("object.dat")));
Object object = inputStream.readObject();
System.out.println((Date)object);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (inputStream!= null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7.3、自定义类实现序列化和反序列化
7.3.1、要求:自定义类必须实现Serializable接口
7.3.2、当前类必须提供一个全局变量serialVersionUID
7.3.3、除了当前类实现Serializable接口外,还需保证类中所有元素的类型都是可序列化的。
7.3.4、不能序列化static和transient修饰的成员变量。
public class Person implements Serializable {
private static final long serialVersionUID = -6878978784564667710L;
private String name;
private Integer age;
//···········
}
8、RandomAccessFile的使用
8.1、RandomAccessFile直接继承与java.long.Object类,实现了DataInput和DataOutput接口。
8.2、RandomAccessFile既可以作为输入流,也可以作为输出流。
8.3、如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
如果写出到文件,则会对原有文件内容进行覆盖(默认情况下从头覆盖)。
@Test
public void test() {
RandomAccessFile randomAccessFile = null;
RandomAccessFile randomAccessFile1 = null;
try {
randomAccessFile = new RandomAccessFile(new File("360wallpaper.jpg"), "r");
randomAccessFile1 = new RandomAccessFile(new File("360wallpaper1.jpg"), "rw");
byte[] bytes = new byte[1024];
int len;
while ((len = randomAccessFile.read(bytes)) != -1) {
randomAccessFile1.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (randomAccessFile != null) {
try {
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (randomAccessFile1 != null) {
try {
randomAccessFile1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
操作文本
@Test
public void test1() {
RandomAccessFile randomAccessFile1 = null;
try {
randomAccessFile1 = new RandomAccessFile(new File("hello.txt"), "rw");
//通过seek方法设置写入位置
randomAccessFile1.seek(new File("hello.txt").length());
randomAccessFile1.write("hahahahahahahaha".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (randomAccessFile1 != null) {
try {
randomAccessFile1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}