File类与IO流
文章目录
- File类与IO流
- 1. File类
- 1.1 File类理解
- 1.2 构造器
- 1.3 常用方法
- 1.4 练习
- 2. IO流概述
- 2.1 IO流理解
- 2.2 流的分类
- 2.3 基础IO流的框架
- 3. FileReader/FileWriter
- 3.1 执行步骤
- 3.2 注意
- 4. FileInputStream / FileOutputStream
- 5. 缓冲流
- 6. 转换流的使用
- 7. 对象流的使用
- 8. 其它流
1. File类
1.1 File类理解
- File类位于java.io包下
- File类对象,对应操作系统下一个文件或一个文件夹(目录)
- 文件内容的读写——使用IO流
1.2 构造器
package file.fileTest;
import org.junit.Test;
import java.io.File;
public class FileTest {
@Test
public void test1(){
//1. public File(String pathname)
File file1 = new File("E:\\Java\\JavaU\\JavaSE\\src\\file\\file_exer\\hello.txt");
File file2 = new File("abc");
System.out.println(file2.getAbsolutePath());
}
@Test
public void test2(){
//2. public File(String parent, String child)
//参数一:一定是一个文件目录
//参数二:可以是文件目录,可以是文件
File file1 = new File("E:\\Java\\JavaU\\JavaSE\\src\\file\\file_exer","abc_txt");
File file2 = new File("abc","abc0");
//3. public File(File parent, String child)
//参数一:一定是一个文件目录
//参数二:可以是文件目录,可以是文件
File file3 = new File(file2,"abc1");
}
}
1.3 常用方法
-
列出目录的下一级
//列出目录的下一级 @Test public void test1(){ File file = new File("E:\\Java_learning\\JavaSE"); //String[] list()返回的是相对路径 String[] list = file.list(); for(String s : list){ System.out.print(s+" "); } System.out.println(); //File[] listFiles()返回的是绝对路径 File[] files = file.listFiles(); for(File f : files){ System.out.println(f); } }
-
File类重命名
public boolean renameTo(File dest) -- file1.renameTo(file2):file1必须存在,file2必须不存在,且file2所在文件目录需存在
-
判断功能方法
-- public boolean exists():此File表示的文件或目录是否实际存在 -- public boolean isDirectory():此File表示的是否是目录 -- public boolean isFile():此File表示的是否是文件 -- public boolean canRead() -- public boolean canWriter() -- public boolean isHidden()
-
创建、删除功能
-- public boolean createNewFile():创建文件。若文件存在,则不创建,返回false -- public boolean mkdir():创建文件目录。如果此文件目录存在,就不创建。如果此文件的上层目录不存在,也不创建 -- public boolean mkdirs():创建文件目录。如果上层文件目录不存在,一并创建 -- public boolean delete():删除文件或文件夹
- 删除注意:(1)Java中删除不走回收站 (2)要删除一个文件目录,该文件目录里不能包含文件或文件目录
1.4 练习
-
判断指定目录下是否有后缀名为.jpg的文件,如果有,输出该文件名称
import org.junit.Test; import java.io.File; public class Pra2 { @Test public void test(){ File file = new File("C:\\Users\\cmf\\Pictures"); String[] list = file.list(); for(String s : list){ if(s.endsWith(".jpg")){ //endsWith(String s)判断后缀 System.out.println(s); } } } }
-
遍历指定目录下的所有文件的名称,包括子文件目录中的文件
//遍历指定目录下的所有文件的名称,包括子文件目录中的文件 public void printFileName(File file){ if(file.isFile()){ //如果是一个文件 System.out.println(file.getName());//打印文件本身的名字 }else if(file.isDirectory()){ //如果是目录 File[] files = file.listFiles(); for(File f : files){ //遍历每个文件或目录 printFileName(f); //进行递归,判断接下来的文件或目录 } } }
-
删除指定目录及其下所有文件
// 删除指定目录及其下所有文件 public void deleteDirectory(File file){ //如果file是文件减,直接delete //如果file是目录,先把它的下一级删除,再删除自己 if(file.isDirectory()){ File[] files = file.listFiles(); //循环删除file的下一级 for(File f : files){ deleteDirectory(f); } } //删除自己 file.delete(); }
2. IO流概述
2.1 IO流理解
- 输入input:读取外部数据到程序(内存)中
- 输出output:将程序(内存)输出到磁盘、光盘等存储设备中
2.2 流的分类
- 流向不同
- 输入流:InputStream、Reader
- 输出流:OutputStream、Writer
- 数据单位不同
- 字节流:InputStream、OutputStream
- 字符流:Reader、Writer
- 角色不同
- 节点流:直接连接到数据源或目的地
- 处理流
2.3 基础IO流的框架
抽象基类 | 4个节点流(文件流) |
---|---|
InputStream | FileInputStream |
OutputStream | FileOutputStream |
Reader | FileReader |
Writer | FileWriter |
3. FileReader/FileWriter
3.1 执行步骤
- 1)创建读取或写出的File类对象
- 2)创建输入流或输出流
- 3)具体的读入或写出过程
- 读入:read(char[] cbuffer)
- 写出:writer(String str) / writer(char[] cbuffer, 0, len)
- 4)关闭流资源,避免内存泄漏
import org.junit.Test;
import java.io.*;
public class FrfwTest {
/* 读取hello.txt文件中内容,并输出
* */
@Test
public void test1() {
FileReader fr = null;
try {
//1.创建File类的对象,对应着hello.txt文件
File file = new File("hello.txt");
//2.创建输入的字符流,用于读取数据
fr = new FileReader(file);
//3.读取数据,并显示在控制台上
char[] cbuffer = new char[5];
int len;
while((len = fr.read(cbuffer))!= -1){
//遍历数组
for(int i = 0; i < len; i++){
System.out.print(cbuffer[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.流资源关闭(必须关闭,否则会内存泄漏)
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/* 将内存中的数据写到指定文件中
* */
@Test
public void test2() {
FileWriter fw = null;
try {
//1.创建File类对象,指明要写出的文件名称
File file = new File("info.txt");
//2.创建输出流
//覆盖文件使用
fw = new FileWriter(file);
//fw = new FileWriter(file,false);
//在现有文件基础上,末尾追加
//fw = new FileWriter(file,true);
//3.写出具体过程
fw.write("I am happy!\n");
System.out.println("输出成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//4.关闭输出流
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3.2 注意
-
涉及到流资源关闭操作,出现异常要使用thry-catch-finally方式处理
-
对于输入流,File类对象对应的物理磁盘上文件必须存在
对于输出流,File类对象对应的物理磁盘上文件可以不存在
> 不存在时,在输出过程中,会自动创建此文件
> 存在时,FileWriter(File file) 或 FileWriter(File file, false):会对现有文件进行覆盖
FileWriter(File file, true):在现有文件基础上,末尾追加
4. FileInputStream / FileOutputStream
-
复制一份 sky.jpg 到 sky_copy.jpg
import org.junit.Test; import java.io.*; public class FileStreamTest { //复制一份sky.jpg到sky_copy.jpg @Test public void test1(){ FileInputStream fis = null; FileOutputStream fos = null; try { // 1. 创建File类对象 File src = new File("sky.jpg"); File dest = new File("sky_copy.jpg"); // 2. 创建相关字节流 fis = new FileInputStream(src); fos = new FileOutputStream(dest); // 3. 具体读入和写出操作 byte[] b = new byte[1024]; int len; while((len = fis.read(b)) != -1){ for(int i = 0; i < len; i++){ fos.write(buffer, 0, len); } } System.out.println("复制成功!"); } catch (IOException e) { e.printStackTrace(); } finally { // 4. 关闭流资源 try { fos.close(); fis.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
注意:
-
字符流:用于处理文本文件,不能处理非文本文件
-
字节流:主要用于处理文本文件,如果涉及文本文件复制操作,可以使用字节流
-
文本文件(末尾不能自动换行,只会一直写下去):.txt .java .c .cpp .py
非文本文件:.doc .xls .jpg .mp3 .mp4 .avi等
-
5. 缓冲流
-
缓冲流是处理流中的一种
-
作用:提升文件读取效率(通过减少与磁盘的交互)
-
处理非文本文件的字节流:
使用的字节流 使用方法 BufferedInputStream read(byte[ ] buffer) BufferedOutputStream write(byte[ ] buffer, 0, len) 处理文本文件的字符流:
使用的字符流 使用方法 BufferedReader read(char[ ] cBuffer) / readLine( ) BufferedWriter write(char[ ] cBuffer, 0, len) -
实现步骤
- 1)创建File的对象、流的对象(包括文件流、缓冲流)
- 2)使用缓冲流实现读取数据 或 写出数据的过程
- 3)关闭资源
-
注意
- readLine( ):每次读取一行文本数据,返回的字符串不包含换行符
- flush( ):刷新方法,每当调用此方法时,就会主动将内存中数据写到磁盘文件中
6. 转换流的使用
-
要想读取时不出现乱码:解码时使用的字符集与编码时使用的字符集相同
-
作用:实现字节与字符之间的转换
-
API
InputStreamReader: 将一个输入型的字节流转换为输入型的字符流 OutputStreamWriter: 将一个输出型的字符流转换为输出型的字节流
解码:字节 ——》字符 编码:字符 ——》字节
-
1)存储在文件中的字符
ascii:主要用来存储a、b、c等英文字符和1、2、3、常用标点符号。每个字符占1个字节 iso-8859-1:每个字符占1个字节。向下兼容ascii gbk:用来存储中文简体繁体、a、b、c等英文字符和1、2、3、常用标点符号等字符 中文字符使用2个字节存储。向下兼容ascii,意味着英文字符、1、2、3、常用标点符号仍使用1个字节 utf-8:可以用来存储世界范围内主要语言的所有字符。使用1-4个不等的字节表示一个字符。 中文字符使用3个字节存储。向下兼容ascii.
2)在内存中的字符:
一个字符(char)占用2个字节。在内存中使用的字符集称为Unicode字符集
7. 对象流的使用
-
数据流
DataOutputStream:可以将内存中的基本数据类型的变量、String类型的变量写到具体的文件中 DataInputStream:将文件中保存的数据还原为内存中的基本数据类型的变量、String类型的变量对象流
-
对象流
-
API
ObjectOutputStream ObjectInputStream
-
作用:可读写基本数据类型和应用数据类型
-
对象的序列化机制
指允许把内存中的Java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上或通过网络将这种二进制流传输到另一个网络节点。
—> 当其他程序获取了这种二进制流,就可以恢复成原来的 Java 对象。
-
序列化过程(写出):ObjectOutputStream —— 把内存中的Java对象保存在文件或通过网络传播出去
反序列化过程(读):ObjectInputStream ——将文件中的数据或网络传输来的数据还原为内存中的Java 对象
import java.io.*; public class ObjectStreamTest { /* **序列化过程**(写出):ObjectOutputStream —— 把内存中的Java对象保存在文件或通过网络传播出去 * */ @Test public void test1() throws IOException { //1. 创建对象 File file = new File("object.txt");//把内存中的Java对象保存在的文件名 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); //2. 写出数据 oos.writeUTF("我爱中国!"); oos.flush(); //3. 关闭资源 oos.close(); } /* **反序列化过程**(读):ObjectInputStream ——将文件中的数据或网络传输来的数据==还原==为内存中的==Java 对象== * * */ @Test public void test2() throws IOException { File file = new File("object.txt"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); System.out.println(ois.readUTF()); ois.close(); } }
-
-
自定义类要想实现序列化机制,需要满足:
-
自定义类需要实现接口:Serializable(表示接口)
-
要求自定义声明一个全局常量:static final long serialVersionUID = 42L;
—> 如果不声明全局常量serialVersionUID,系统会自动生成一个针对当前类的serialVersionUID。如果修改当前的自定义类,会导致serialVersionUID发生改变,进而导致反序列化时,出现InvailedClassException异常
-
要求自定义类的各个属性都是可序列化的
- 基本数据类型:本身就是可序列化的
- 引用数据类型:也需要实现序列化机制
-
注意:
- 类中的属性如果声明为transient或static,则不会实现序列化
-
8. 其它流
-
标准输入流、输出流
- System.in:标准输入流
- System.out:标准输出流
-
打印流