目录
IO 简介
在冯诺依曼体系结构我见到了各种各样的输入设备(鼠标、键盘、硬盘、网卡等等)和输出设备(音响、屏幕、硬盘、、网卡等等)。其实,IO(Input/Output)其实解决的就是一个输入输出的问题。
Input:数据从各种输入设备以二进制流输入到内存中
Output:数据从内存以二进制流输出到各种输出设备
因为有各种不同的输入输出设备,才会出现不同的输入输出流。而且,数据天生的格式都是字节流(二进制流)。通过上面的分析,我们会发现硬盘既是一种输入设备 又是一种输出设备。那么如何通过java提供的API把内存中的数据保存到硬盘中,又如何把硬盘中的数据读入到内存中呢?我们必须要了解到下面的File类。
了解File类
1. File类基本介绍
File类其实就是描述文件源信息(属性)的一组类。那么文件是什么呢?
书上是这么描述的:文件是相关记录或者放在一起的数据的集合。其实文件就是OS对硬盘空间一块一块的抽象。在windows操作中,经常在硬盘上创建的各种.txt, .doc, .exe, .java, .lib, .mp3等等,都可以称之为文件。文件简单的可以理解成,在外设硬盘上面保存数据的一种方式。
文件一共可以由两部分构成:属性(文件大小,文件名,文件类型等)+内容(就是文件里面放的是什么) 。 File文件操作类在 java.io 包之中,用 File 类来对文件进行操作(创建、删除、取得信息等)
2. File类常见操作
1. 获取文件基本信息
public static void main(String[] args) throws IOException {
{
// File 对象的实际文件不存在
String path = "D:\\文档\\File类练习\\test.txt";
File file = new File(path);
System.out.println(file);
}
// 传入一个父路径
{
String parent = "D:\\文档\\File类练习";
String path = "test.txt";
File file = new File(parent, path);
System.out.println(file);
// 获取常见的属性
System.out.println(file.exists()); //文件是否存在
System.out.println(file.getAbsolutePath()); //返回绝对路径
System.out.println(file.getName()); //返回文件名
System.out.println(file.getParent()); //返回父路径
System.out.println(file.isAbsolute()); //是否为绝对路径
System.out.println(file.isDirectory()); //是否是目录
System.out.println(file.isFile()); //是否是文件
System.out.println(file.isHidden()); //是否是隐藏的
System.out.println(file.canRead()); //是否可读
System.out.println(file.canWrite()); //是否可写
System.out.println(file.canExecute()); //是否可执行
}
}
2. 文件的创建
//普通文件的创建
String parent = "D:\\文档\\File类练习"; //路径
String fileName = "文件1.txt"; //文件名
File file = new File(parent, fileName);
3. 文件夹的创建
// 文件夹的创建过程
String parent = "D:\\文档\\File类练习"; //父路径
String filename = "文件夹的创建"; //文件夹名称
File file = new File(parent, filename);
4. 文件的删除
file.deleteOnExit(); //请求在虚拟机终止时删除由此抽象路径名表示的文件或目录。
boolean delete = file.delete();// 只能删除一个空的文件夹
5. 文件夹文件的操作
获取文件夹下面的文件
String path = "D:\\文档";
File dir = new File(path);
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
System.out.println(file.getName());
}
}
流
1. 流的基本概念
在Java中所有数据都是使用流读写的。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
2. 输入输出流
3. 字节流
public static void main(String[] args) throws IOException {
try (InputStream is = new FileInputStream("输入文件.txt")) {
byte[] buf = new byte[8192];
int len;
while ((len = is.read(buf)) != -1) {
// 有效数据是 buf[0, len)
for (int i = 0; i < len; i++) {
// 如果直接按照数字打印出来,就是打印 ASCII
// System.out.println(buf[i]);
char c = (char)buf[i];
System.out.print(c);
}
}
}
}
文件输出字节流(写):
public static void main(String[] args) throws IOException {
try (OutputStream os = new FileOutputStream("输出内容.txt")) {
// Second 一次写一个字节的方式
//写法1
os.write('S');
os.write('e');
os.write('c');
os.write('o');
os.write('n');
os.write('d');
os.write('\r');
os.write('\n');
// 写法2
byte[] buf = new byte[1024];
buf[0] = (byte)'T';
buf[1] = (byte)'h';
buf[2] = (byte)'i';
buf[3] = (byte)'r';
buf[4] = (byte)'d';
buf[5] = (byte)'\r';
buf[6] = (byte)'\n';
os.write(buf, 0, 7);
//写法3
String s = "Hello World\r\n";
byte[] bytes = s.getBytes(); //string内部可以把它转为byte类型数组
os.write(bytes);
os.flush(); // 保证把所有缓冲的数据全部写入硬盘中
}
}
}
4. 字符流
字符流:数据流中最小的数据单元是字节, Java中的字符是Unicode编码,一个字符占用两个字节:Reader、Writer
文件输入字节流(读):
private static void read() throws IOException {
try (InputStream is = new FileInputStream("某篇文章.txt")) {
try (InputStreamReader isReader = new InputStreamReader(is, "UTF-8")) {
try (Scanner scanner = new Scanner(isReader)) {
// 按行读
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
}
}
}
}
}
文件输出字节流(写):
private static void write() throws IOException {
try (OutputStream os = new FileOutputStream("某篇文章.txt")) {
try (OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8")) {
try (PrintWriter printWriter = new PrintWriter(osWriter)) {
printWriter.println("");
printWriter.printf("");
printWriter.print("");
printWriter.format("");
printWriter.flush();
}
}
}
}
那么字符流和字节流有什么区别呢?
序列化与反序列化
1. 什么是序列化
序列化:把对象转换为字节序列的过程称为对象的序列化。
2. 序列化使用场景
3. 如何序列化
实现序列化其实有很多方式:Java对象序列化、JSON序列化、XML等等。如果Java对象进行序列化需要实现Serializable接口即可。
用一组例子来说明序列化和反序列化:
package uesFile.com;
import java.io.*;
public class SerializeDemo {
// 声明实现 Serializable 接口
// 声明之后,就拥有了可以序列号和反序列化的功能了
static class Person implements Serializable {
String name;
int age;
}
//读
public static void main(String[] args) throws IOException, ClassNotFoundException {
try (InputStream is = new FileInputStream("名单.binary")) {
try (ObjectInputStream ois = new ObjectInputStream(is)) {
Person p = (Person) ois.readObject();
System.out.println(p.name);
System.out.println(p.age);
Person q = (Person) ois.readObject();
System.out.println(q.name);
System.out.println(q.age);
}
}
}
//写
public static void main(String[] args) throws IOException {
Person p = new Person();
p.name = "人员1"; p.age = 34;
Person q = new Person();
q.name = "人员2"; q.age = 18;
try (OutputStream os = new FileOutputStream("名单.binary")) {
try (ObjectOutputStream oos = new ObjectOutputStream(os)) {
oos.writeObject(p);
oos.writeObject(q);
oos.flush();
}
}
}
}
就算程序关闭,文件中的内容也不会消失。实现了先写,再进行读的序列化。这就实现了Java对象的实例化。