这是我参与 8 月更文挑战的第 27 天,活动详情查看: 8月更文挑战
文件对象
- 文件对象常用方法
import java.io.File;
public class Demo{
public static void main(String[] args){
File f1 = new File("/home/cunyu/soft/Java");
// 绝对路径
System.out.println("f1 绝对路径 :" + f1.getAbsolutePath());
// 将 f1 作为父目录创建文件对象
File f2 = new File(f1, "Demo.java");
System.out.println("f2 绝对路径 :" + f2.getAbsolutePath());
File f3 = new File("/home/cunyu/soft/Java/Demo.java");
// 判断文件是否存在
System.out.println(f3.exists());
// 判断文件是否是文件夹
System.out.println(f3.isDirectory());
// 判断是否是文件
System.out.println(f3.isFile());
// 文件长度
System.out.println(f3.length());
// 最后修改时间
long time = f3.lastModified();
Date date = new Date(time);
System.out.println(d)
// 设置文件修改时间,从 1970.1.1 08:00:00 开始
f3.setLastModified(0);
// 文件重命名
File f4 = new File("/home/cunyu/soft/Java/Test.java");
f3.renameTo(f4);
// 以字符串数组形式返回当前文件夹下所有文件(不含子文件及子文件夹)
String[] filesListStr = f3.list();
// 以文件数组形式返回当前文件夹下所有文件(不含子文件及子文件夹)
File[] filesListFile = f3.listFiles();
// 以字符串形式返回文件所在文件夹
String pathStr = f3.getParent();
// 创建文件夹
f3.mkdir(); // 父文件夹不存在则无效
f3.mkdirs(); // 父文件夹不存在则创建
// 创建空文件
f3.createNewFile();
// 列出盘符
f3.listRoots();
// 删除文件
f3.delete();
// JVM 结束时,删除文件,常用于删除临时文件
f3.deleteOnExit();
}
}
流(Stream)
- 定义 :当数据在不同介质间交互时,
Java则通过流来实现,数据源可以是文件、数据库、网络等。从不同的角度,可以分为 输入流(InputStream) 和 输出流(OutputStream); - 实例
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo{
public static void main(String[] args){
try{
File file = new File("/home/cunyu/soft/Java/Demo.java");
// 输入流
FileInputStream inputStream = new FileInputStream(file);
// 输出流
FileOutputStream outputStream = new FileOutputStream(file);
} catch (IOException e){
e.printStackTrace();
}
}
}
字节流 VS 字符流 VS 缓存流 VS 数据流 VS 对象流
字节流
- 定义 : 分为 输入流(
InputStream) 与 输出流(OutputStream),主要用于 以字节的形式读取和写入数据; - 可见的 ASCII 码对应的十进制和十六进制;
| 字符 | 十进制数字 | 十六进制数字 |
|---|---|---|
| ! | 33 | 21 |
| " | 34 | 22 |
| # | 35 | 23 |
| $ | 36 | 24 |
| % | 37 | 25 |
| & | 38 | 26 |
| ' | 39 | 27 |
| ( | 40 | 28 |
| ) | 41 | 29 |
| * | 42 | 2A |
| + | 43 | 2B |
| , | 44 | 2C |
| - | 45 | 2D |
| . | 46 | 2E |
| / | 47 | 2F |
| 0 | 48 | 30 |
| 1 | 49 | 31 |
| 2 | 50 | 32 |
| 3 | 51 | 33 |
| 4 | 52 | 34 |
| 5 | 53 | 35 |
| 6 | 54 | 36 |
| 7 | 55 | 37 |
| 8 | 56 | 38 |
| 9 | 57 | 39 |
| : | 58 | 3A |
| ; | 59 | 3B |
| < | 60 | 3C |
| = | 61 | 3D |
| 62 | 3E | |
| @ | 64 | 40 |
| A | 65 | 41 |
| B | 66 | 42 |
| C | 67 | 43 |
| D | 68 | 44 |
| E | 69 | 45 |
| F | 70 | 46 |
| G | 71 | 47 |
| H | 72 | 48 |
| I | 73 | 49 |
| J | 74 | 4A |
| K | 75 | 4B |
| L | 76 | 4C |
| M | 77 | 4D |
| N | 78 | 4E |
| O | 79 | 4F |
| P | 80 | 50 |
| Q | 81 | 51 |
| R | 82 | 52 |
| S | 83 | 53 |
| T | 84 | 54 |
| U | 85 | 55 |
| V | 86 | 56 |
| W | 87 | 57 |
| X | 88 | 58 |
| Y | 89 | 59 |
| Z | 90 | 5A |
| [ | 91 | 5B |
| \ | 92 | 5C |
| ] | 93 | 5D |
| 94 | 5E | |
| _ | 95 | 5F |
| ` | 96 | 60 |
| a | 97 | 61 |
| b | 98 | 62 |
| c | 99 | 63 |
| d | 100 | 64 |
| e | 101 | 65 |
| f | 102 | 66 |
| g | 103 | 67 |
| h | 104 | 68 |
| i | 105 | 69 |
| j | 106 | 6A |
| k | 107 | 6B |
| l | 108 | 6C |
| m | 109 | 6D |
| n | 110 | 6E |
| o | 111 | 6F |
| p | 112 | 70 |
| q | 113 | 71 |
| r | 114 | 72 |
| s | 115 | 73 |
| t | 116 | 74 |
| u | 117 | 75 |
| v | 118 | 76 |
| w | 119 | 77 |
| x | 120 | 78 |
| y | 121 | 79 |
| z | 122 | 7A |
| { | 123 | 7B |
| | | 124 | 7C |
| } | 125 | 7D |
| ~ | 126 | 7E |
- 实例 :字节流形式读取和写入数据
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo{
public static void main(String[] args){
// 读取数据
try{
File fileIn = new File("/home/cunyu/soft/Java/Demo.java");
FileInputStream fis = new FileInputStreaam(fileIn);
// 创建字节数组,长度为文件长度
byte[] fileContext = new byte[(int)file.length()];
// 以字节流的方式读取文件内容,使用后关闭流
fis.read(fileContext);
fis.close();
} catch(IOException e){
e.printStackTrace();
}
// 写入数据
try{
File fileOut = new File("/home/cunyu/soft/Java/Demo.java");
FileOutputStream fos = new FileOutputStream(fileOutput);
// 写入数据对应的字节数组
byte[] data = {65, 66, 67};
// 以字节流的方式写入数据,然后关闭流
fos.write(data);
fos.close()
} catch(IOException e){
e.printStackTrace();
}
}
}
字符流
- 定义:分为 字符输入流(
Reader) 和 字符输出流(Writer),用于 字符形式 的读取和输入数据; - 实例:字符流读取和输入数据
import java.io.IOException;
import java.io.FileReader;
import java.io.File;
public class Demo{
public void main(String[] args){
// 读取
File file = new File("/home/cunyu/soft/Java/Demo.java");
try(FileReader fileReader = new FileReader(file)){
char[] all = new char[(int) file.length()];
fileReader.read(all);
} catch (IOException e){
e.printStackTrace();
}
// 写入
try(FileWriter fileWriter = new FileWriter(file)){
String data = "System.out.println("hello world");";
char[] strArray = data.toCharArray();
fileWriter.write(strArray);
} catch (IOException e){
e.printStackTrace();
}
}
}
缓存流
- 定义 :针对 字节流 和 字符流 在每次读写都会访问硬盘的特点,若读写频率较高时,性能较弱的 弊端,因而采用 缓存流。缓存流 一次性读取较多数据到缓存,后面的每次读取都是在缓存中访问,直到缓存中数据读取完毕,再到硬盘读取。
- 实例 :缓存流读取和写入数据;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class Demo{
public static void main(String[] args){
File file = new File("/home/cunyu/soft/Java/Demo.java");
// 读取
try(
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
)
{
while(true){
// 每次一行
String line = br.readLine();
if(line != null){
System.out.println(line)
}else{
break;
}
}
} catch (IOException){
e.printStackTrace();
}
// 写入
try(
FileWriter fw = new FileWriter(file);
BufferedWriter wr = new BufferedWriter(fw);
)
{
while(true){
// 每次一行
String line = wr.writeLine();
if(line != null){
System.out.println(line)
}else{
break;
}
}
} catch (IOException){
e.printStackTrace();
}
}
}
- flush :缓存无论读写都需要先等缓存满,但有时需要立即读取写入时,可以利用
flush立即读取写入;
package stream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Demo {
public static void main(String[] args) {
File file = new File("/home/cunyu/soft/Java/Demo.java");
// 创建文件字符流
// 缓存流必须建立在一个存在的流的基础上
try(FileWriter fr = new FileWriter(f);PrintWriter pw = new PrintWriter(fr);) {
pw.println("garen kill teemo");
// 强制把缓存中的数据写入硬盘,无论缓存是否已满
pw.flush();
pw.println("teemo revive after 1 minutes");
pw.flush();
pw.println("teemo try to garen, but killed again");
pw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
数据流
- 定义 :分为 数据输入流(DataInputStream) 和 数据输出流(DataOutputStream);
- 实例 :直接进行字符串的读写;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo{
public static void main(String[] args){
File file = new File("/home/cunyu/soft/Java/Demo.java");
write();
read();
}
/**
* 数据流写入
* @param: file 待写入的文件
*/
public static viod write(File file){
try(FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);){
dos.writeBoolean(true);
dos.writeInt(250);
dos.writeUTF("你是 250 ?");
} catch (IOException e){
e.printStackTrace();
}
}
/**
* 数据流读取
* @param: file 待写入的文件
*/
public static viod read(File file){
try(
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
){
boolean b = dis.readBoolean();
int i = dis.readInt();
String str = dis.readUTF();
} catch(IOException e){
e.printStackTrace();
}
}
}
对象流
- 定义 :指直接 将一个对象以流的形式 传输给其他介质。一个对象以流的形式进行传输叫做 序列化,该对象所属类必须实现
Serializable接口; - 实例 :序列化一个对象;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
class Hero implements Serializable{
private static final long serialVersionUID = 1L;
public String name;
public float hp;
}
public class Demo{
public static void main(String[] args){
Hero hero = new Hero();
hero.name = "铠";
hero.hp = 1000;
// 用于保存对象的文
File file = new File("/home/cunyu/soft/Java/k.honor");
try(
// 对象输入流
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
// 对象输出流
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
){
oos.writeObject(hero);
Hero hero2 = (Hero) ois.readObject();
System.out.println(hero2.name + " : " + hero2.hp);
} catch (IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e){
e.printStackTrace();
}
}
}
中文问题
- 常用编码:
ISO-8859-1 ASCII: 数字和西欧字母;GBK GB2312 BIG5: 中文;UNICODE: 统一编码;
- 实例:读取中文;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
public class Demo {
public static void main(String[] args) throws UnsupportedEncodingException, FileNotFoundException {
File f = new File("/home/cunyu/tmp/test.txt");
System.out.println("默认编码方式: " + Charset.defaultCharset());
//FileReader得到的是字符,所以一定是已经把字节根据某种编码识别成了字符了
//而FileReader使用的编码方式是Charset.defaultCharset()的返回值,
try (FileReader fr = new FileReader(f)) {
char[] cs = new char[(int) f.length()];
fr.read(cs);
System.out.println("默认编码方式 : %s",Charset.defaultCharset());
System.out.println(new String(cs));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// FileReader 无法手动设置编码,因此用 InputStreamReader 代替
try (InputStreamReader isr = new InputStreamReader(new FileInputStream(f),Charset.forName("UTF-8"))) {
char[] cs = new char[(int) f.length()];
isr.read(cs);
System.out.printf("InputStreamReader 指定编码方式UTF-8,识别出来的字符是:%n");
System.out.println(new String(cs));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
关闭流的方式
无论是什么流,在我们使用之后,都应该对其关闭,否则将会造成资源的浪费,严重时可能会影响后续业务的展开,此处主要介绍 3 种关闭流的方式;
try中关闭 :此时存在一个 弊端 :当文件不存在或读取时出现问题会抛出异常,从而引起无法触发关闭流的代码,存在巨大的资源占用隐患,不推荐 使用;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo{
public static void main(String[] args){
// 读取数据
try{
File fileIn = new File("/home/cunyu/soft/Java/Demo.java");
FileInputStream fis = new FileInputStreaam(fileIn);
// 创建字节数组,长度为文件长度
byte[] fileContext = new byte[(int)file.length()];
// 以字节流的方式读取文件内容,使用后关闭流
fis.read(fileContext);
// try 中关闭
fis.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
finally中关闭 :关闭流的标准方式:
- 先将流的引用声明在
try的外面,以方便finally访问; - 关闭
finally之前,判断该引用是否为null; - 关闭时,再次进行
try catch处理;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo{
public static void main(String[] args){
File fileIn = new File("/home/cunyu/soft/Java/Demo.java");
FileInputStream fis = null;
// 读取数据
try{
fis = new FileInputStream(fileIn);
// 创建字节数组,长度为文件长度
byte[] fileContext = new byte[(int)file.length()];
// 以字节流的方式读取文件内容,使用后关闭流
fis.read(fileContext);
// try 中关闭
fis.close();
} catch(IOException e){
e.printStackTrace();
} finally{
if(fis != null){
try{
fis.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
try()的方式 :将流定义在try()中,当try、catch、finally结束时,会自动关闭流;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) {
File fileIn = new File("/home/cunyu/soft/Java/Demo.java");
//把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
try (FileInputStream fis = new FileInputStream(fileIn)) {
byte[] all = new byte[(int) f.length()];
fis.read(all);
} catch (IOException e) {
e.printStackTrace();
}
}
}
输入输出
- 定义 :
System.in用于从控制台输入数据,System.out用于在控制台输出数据;
流关系图
graph RL
B[字节流] --> A[流]
C[字符流] --> A[流]
D[缓存流] --> C[字符流]
数据流 --> B[字节流]
对象流 --> B[字节流]
总结
以上就是关于 IO 流的所有内容了,如果你觉得本文对你有所帮助,那就点赞关注吧!