Java - IO
介绍:
Input Output Stream
狭义: 数据在内存中输入和输出, 本地进程间的数据流动
广义: 不同电脑之间的数据流动, 远程进程间的数据流动
流的流动方式(数据的传输方向) :
- 输入流
- 输出流
流的数据格式:
- 字节流
- 字符流
File对象:
Java封装的一个操作文件及文件夹的对象
返回值 | 方法 | 描述 |
---|---|---|
File(String pathname) | 构造方法 | |
File(String parent, String child) | 构造方法 | |
File(File parent, String child) | 构造方法 | |
File(URI uri) | 构造方法, 用于网络 | |
boolean | createNewFile() throws IOException | 创建文件, 已存在就返回 false , 不存在就新建, 需要处理异常 |
boolean | exists() | 是否存在 |
boolean | canExecute() | 是否有执行权限 |
boolean | canWrite() | 是否有写权限 |
boolean | canRead() | 是否有读权限 |
boolean | delete() | 删除文件 |
void | deleteOnExit() | 在JVM退出时删除文件 |
File | getAbsoluteFile() | 返回绝对路径对象 |
String | getAbsolutePath() | 返回绝对路径 |
long | getFreeSpace() | 空闲空间 |
long | getUsableSpace() | 可用空间 |
long | getTotalSpace() | 总空间 |
long | length() | 返回文件大小 |
String | getName() | 获取文件名 |
String | getParent() | 获取父级路径, 必须使用绝对路径对象 |
String | getPath() | 返回全路径 |
String | getParentFile() | |
boolean | isHidden() | 是否为隐藏文件 |
long | lastModified() | 返回最后修改时间戳 |
boolean | isDirectory() | 是否为一个文件夹 |
boolean | mkdir() | 创建文件夹, 只能创建一个不能递归创建 |
boolean | mkdirs() | 递归创建文件夹 |
boolean | renameTo(File dest) | 剪切, 移动文件 |
String[] | list() | 将文件夹下的文件返回成一个字符串数组 |
File[] | listFiles() | 将文件夹下的文件返回成一个 File 对象数组 |
String[] | list(FilenameFilter filter) | 过滤文件 |
File[] | listFiles(FilenameFilter filter) | 过滤文件 |
IO流分类:
- InputStream 字节输入流
- OutputStream 字节输出流
- Reader 字符输入流
- Writer 字符输出流
字节流:
InputStream(抽象类):
直接子类:
AudioStream
ByteArrayInputStream
FileStream
FilterInputStream
ObjectInputStream
PipedInputStream
SequenceInputStream
StringBufferInputStream
write()
写文件
int read()
读文件
close()
关闭流
flush()
刷新缓冲区
FileInputStream:
FileInputStream(String name)
FileInputStream(File file)
read()
读取文件
class Test {
void test() {
InputStream file = null;
try {
file = new FileInputStream(new File("./a.txt")); // 创建一个输入流对象
byte[] buf = new byte[1024]; // 用于缓冲, 大小用2的整数倍, 最好用4k(4k对齐)
int len = 0;
while ((len = file.read(buf)) != -1) {
// System.out.write(buf); // 此方法可能导致读取内容超出
System.out.write(buf, 0, len);
String str = new String(buf, 0, len);
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (file != null) {
try {
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
OutputStream(抽象类):
FileOutputStream
FileOutputStream:
class Test {
void test() {
String msg = "你好";
FileOutputStream file = null;
try {
file_out = new FileOutputStream(new File("b.txt"));
file_in = new FileInputStream(new File("a.txt"));
byte[] buf = new byte[1024];
int len = 0;
while ((len = file_in.read(buf)) != -1) {
file_out = write(buf, 0, len);
}
System.out.ptintln("写入数据成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (file_in != null) {
try {
file_in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (file_out != null) {
try {
file_out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FilterInputStream & FilterOutputStream:
装饰流, 又称为过滤流
不能 直接使用, 主要的作用就是用来装饰节点流
本质是一种装饰者设计模式的体现. 对原有对象的功能进一步的装饰增强
GOF 23 设计模式:
- 单例设计模式
- 装饰者设计模式
子类:
BufferedInputStream
BufferedOutputStream
DataInputStream
DataOutputStream
BufferedInputStream & BufferedOutputStream:
class Test {
void test() {
BufferedInputStream bis = null; // 缓冲池
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream("a.txt")); // 建议把字节流写在里面, 这样不用单独关闭
bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
byte[] buf = new byte[1024 * 8];
int len = 0;
while ((len = bis.read(buf)) != -1) {
bos, write(buf, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 缓存流必须关闭, 因为JVM
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
DataOutputStream:
可以不用转换成字节数组直接就进行写入
class Test {
void test() {
BufferedOutputStream bos = null;
int msg = 1000000;
try {
dos = new DataOutputStream(new FileOutputStream("b.txt"));
dos, writeInt(msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
DataInputStream:
class Test {
void test() {
BufferedOutputStream bos = null;
try {
dis = new DataInputStream(new FileInputStream("a.txt"));
System.out.println(dis.readInt());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流:
计算机底层使用的二进制数据(字节数据)
字符流是为了加快流的操作, 而设计的专门用来操作字符串的一种流
注意: 字符串存在编码问题, 需要保证在读取和写入编码一致
建议使用装饰流按行读取
Reader(输入流):
class Test {
void test() {
Reader reader = null;
try {
reader = new FileReader(new File("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/a.txt"));
char[] buf = new char[1024];
int len = 0;
while ((len = reader.read(buf)) != -1) {
writer.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Writer(输出流):
class Test {
void test() {
Reader reader = null;
Writer writer = null;
try {
writer = new FileWriter("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/b.txt");
reader = new FileReader(new File("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/a.txt"));
char[] buf = new char[1024];
int len = 0;
while ((len = reader.read(buf)) != -1) {
writer.write(buf, 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();
}
}
}
}
}
BufferedReader & BufferedWriter:
class Test {
void test() {
BufferedReader reader = null;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/b.txt"));
reader = new BufferedReader(new FileReader(new File("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/a.txt")));
char[] buf = new char[1024];
int len = 0;
while (reader.readLine(buf) != null) {
writer.write(buf + "\n");
}
} 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();
}
}
}
}
}
PrintWriter(打印输出流):
可以直接操作文件, 也可以操作对象
关闭时不会抛出异常
class Test {
void test() {
Reader reader = null;
PrintWriter writer = null;
try {
PtintWriter = new PrintWriter("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/b.txt");
reader = new BufferedReader(new FileReader(new File("/Users/erzbir/Desktop/IntelliJ Java/JavaTest/a.txt")));
char[] buf = new char[1024];
while (reader.readLine(buf) != null) {
writer.println(buf, 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 (IOExcetion e) {
e.printStackTrace();
}
}
}
}
}
转换流:
将字节流转换为字符流操作
当操作的是文本数据的时候使用
InputStreamReader:
可以将字节输入流转换为字符输入流
class Test {
void test() throws IOException {
BufferedReader br = null;
br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
while ((str = br.readLine()) != null) {
System.out.println(str);
}
br.close();
}
}
OutputStreamWriter:
字节输出流转换成字符输入流
class Test {
void test() throws IOException {
BufferedReader br = null;
PrintWriter out = null;
br = new BufferedReader(new InputStreamReader(System.in));
out = new PrintWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));
String str = null;
while ((str = br.readLine()) != null) {
out.println(str);
}
br.close();
out.close();
}
}
对象流:
ObjectInputStream:
class Test {
void test() {
String msg;
ObjectOutputStream ois = null;
try {
ois = new ObjectOutputStream(new FileOutputStream("a.txt"));
msg = ois.readObject();
System.out.ptintln(msg);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.ptintStackTrace();
}
}
}
}
}
ObjectOutputStream
class Test {
void test() {
String msg = "1asda";
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("a.txt"));
oos.writeObject(msg);
System.out.ptintln("保存成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.ptintStackTrace();
}
}
}
}
}
序列化:
如果一个类没有实现 Serializable
接口,那么它就不能被序列化,写入文件的时候会报异常.如果一个类实现了 Serializable
接口,那么这个类的所有属性和方法都可以自动被序列化
对象序列化:
Serialize: 将虚拟对象转换为一种可以直接传输或者保存的数据(字节, 字符)的过程
对象反序列化:
将序列化后的字节或者字符数据源重新转换为对象
对象持久化:
transient关键字:
被这个关节字修饰的属性, 无法持久化
将数据永久保存(存到磁盘)
java官方提供的序列化, 是将java对象转换为字节数据
注意: java对象序列化必须实现可序列化接口(Serializable
), 这是一个标记接口自动调用底层
try-with-resources:
jdk7的新特性, 如果使用这种结构, 打开的资源会自动完成关闭
class Test {
void test() {
try (InputStream is = new FileInputStream("a.txt")) {
byte[] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
开发中的问题:
在开发过程中, 如果直接将一些确定的值写在代码中, 代码的设计可能有问题, 如果生产环境, 要再次修改值会非常麻烦, 需要重新编译. 这种叫做硬编码
开发环境: development environment
测试环境: test environment
生产环境: product environment
如果值永久不变:
- 做成常量
- 做成枚举
如果有可能变:
可以做成配置文件
Java配置文件:
-
xml
-
json
-
yaml
-
properties