一、IO原理及流的分类
- IO流用来处理设备之间的数据传输
- Java程序中,对于数据的输入/输出操作以”流(stream)” 的方式进行。是指从源节点到目标节点的数据流动
- 源节点和目标节点可以是文件、网络、内存、键盘、显示器等等。
1.1 原理
输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中
1.2 流的分类
按操作数据单位不同:
字节流(8 bit)
字符流(16 bit)
按照数据流的流向:
输入流
输出流
二、文件流
2.1 步骤
读文件:
- 使用文件输入流打开指定文件:
对于文本文件,应使用字符输入流FileReader流
对于二进制文件,应使用字节输入流FileInputStream流- 读取文件数据
- 关闭输入流
写文件:
- 使用文件输出流打开指定文件:
对于文本文件,应使用字符输出流FileWriter流
对于二进制文件,应使用字节输出流FileOutputStream流- 将数据写入文件
- 关闭输出流
2.2 输入流
Reader(FileReader):
int read() // 读取一个字符
int read(char [] c) //一次性读多个字符到缓冲区数组
int read(char [] c, int off, int len)
InputStream(FileInputStream):
int read() //读取一个字节
int read(byte[] b) //一次性读多个字节到缓冲区数组
int read(byte[] b, int off, int len)
2.3 输出流
Writer:
void write(int b/int c);
void write(byte[] b/char[] cbuf);
void write(byte[] b/char[] buff, int offset, int length);
void flush();
void close(); 需要先刷新,再关闭此流
OutputStream
同上
2.4 示例
@Test
public void test3() {
// 1) 声明引用, 初始化为null
FileReader fileReader = null;
// 2) try catch finally
try {
// 5) 创建流对象, 建立通道
fileReader = new FileReader("一个文件");
//char[] buf = new char[100];
//int realCount = fileReader.read(buf); // 一次性读多个字符到数组中
// 6) 处理数据
int ch = fileReader.read();
while (ch != -1) {
/*
for (int i = 0; i < realCount; i++) { // 只处理实际读到的字符数.
System.out.print(buf[i]);
}
// 2) 继续读后面的数据
realCount = fileReader.read(buf);
*/
// 处理已经读的数据
System.out.print((char)ch);
// 继续读后面的字符, 直至-1为止
ch = fileReader.read();
}
} catch (Exception e) {
// 4) 处理异常, 打印栈踪迹
e.printStackTrace();
} finally {
// 3) 关闭流
if (fileReader != null) {
try {
fileReader.close();
} catch (Exception e2) {
}
}
}
}
三、缓冲流
为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组
3.1 按照数据操作单位
BufferedReader 和 BufferedWriter
BufferedInputStream 和 BufferedOutputStream
3.2 示例
@Test
public void test3() {
// 使用缓冲流(处理流)
FileReader fileReader = null;
BufferedReader bufferedReader = null;
try {
// 包装流, 使用对象关联, 包装流把节点流对象关联为属性.
fileReader = new FileReader("HashMap.java");
bufferedReader = new BufferedReader(fileReader);
// 最有价值方法
String line = bufferedReader.readLine(); // 读到的字符串没有换行
int num = 1;
while (line != null) {
// 处理读到的行
System.out.println(num++ + " " + line);
// 继续读后面的行, 直到null
line = bufferedReader.readLine();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 只需要关闭高级流, 因为低级流被关联, 并且会在关闭高级流时自动关闭
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception e2) {
}
}
}
}
四、对象流
用于存储和读取对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
4.1 分类
ObjectInputStream
OjbectOutputSteam
4.2 序列化
- 序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中
- 反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象
- 机制 : 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
4.3 示例
@Test
public void serialize() {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("对象序列化");
bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
Student s1 = new Student(1, "小明", 3, 90);
Student s2 = new Student(2, "小花", 1, 80);
Student s3 = new Student(3, "小丽", 4, 20);
s1.school = "atguigu";
//oos.writeObject(s1);
//oos.writeObject(s2);
//oos.writeObject(s3);
//Student[] arr = {s1, s2, s3};
//oos.writeObject(arr);
List<Student> list = new ArrayList<Student>();
list.add(s1);
list.add(s2);
list.add(s3);
oos.writeObject(list);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (Exception e2) {
}
}
}
}
五、数据流
DataInputStream(套接在InputStream)
DataOutputStream(套接在OutpuStream)
5.1 示例
DataOutputStream dos = null;
try { //创建连接到指定文件的数据输出流对象
dos = new DataOutputStream(new FileOutputStream(
"d:\\IOTest\\destData.dat"));
dos.writeUTF("ab中国"); //写UTF字符串
dos.writeBoolean(false); //写入布尔值
dos.writeLong(1234567890L); //写入长整数
System.out.println("写文件成功!");
} catch (IOException e) {
e.printStackTrace();
} finally { //关闭流对象
try {
if (dos != null) {
// 关闭过滤流时,会自动关闭它包装的底层节点流
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
} }
六、转换流
InputStreamReader:
用于将字节流中读取到的字节按指定字符集解码成字符。需要和InputStream“套接”。
构造方法:
------public InputStreamReader(InputStream in)
------public InputSreamReader(InputStream in,String charsetName)
OutputStreamWriter:
用于将要写入到字节流中的字符按指定字符集编码成字节。需要和OutputStream“套接”
构造方法:
------public OutputStreamWriter(OutputStream out)
------public OutputSreamWriter(OutputStream out,String charsetName)
6.1 示例
public void testMyInput() throws Exception{
FileInputStream fis = new FileInputStream("dbcp.txt");
FileOutputStream fos = new FileOutputStream("dbcp5.txt");
InputStreamReader isr = new InputStreamReader(fis,"GBK");
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
BufferedReader br = new BufferedReader(isr);
BufferedWriter bw = new BufferedWriter(osw);
String str = null;
while((str = br.readLine()) != null){
bw.write(str);
bw.newLine();
bw.flush();
} bw.close(); br.close();}
七、输入/输出流
System.in
System.out
7.1 示例
// 从键盘输入一些内容, 把内容保存成UTF8格式的文本文件content.txt
// 直到键盘输入over命令, 或ctrl+z
@Test
public void test13() {
InputStream is = System.in; // 以键盘为数据源
InputStreamReader isr = null;
BufferedReader bufferedReader = null;
try {
isr = new InputStreamReader(is);
bufferedReader = new BufferedReader(isr);
String line = bufferedReader.readLine();
while (line != null) {
// 1) 处理数据
if (line.equals("exit")) {
break;
}
System.out.println(line);
// 2) 继续读
line = bufferedReader.readLine(); // ctrl+z 提醒流数据已经结束
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (Exception e2) {
}
}
}
}
八、打印流
PrintStream(字节打印流)
PrintWriter(字符打印流)
8.1 特点
- PrintStream和PrintWriter的输出不会抛出异常
- PrintStream和PrintWriter有自动flush功能
- System.out返回的是PrintStream的实例
8.2 示例
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File("D:\\IO\\text.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}//创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
PrintStream ps = new PrintStream(fos,true);
if (ps != null) { // 把标准输出流(控制台输出)改成文件
System.setOut(ps);}
for (int i = 0; i <= 255; i++) { //输出ASCII字符
System.out.print((char)i);
if (i % 50 == 0) { //每50个数据一行
System.out.println(); // 换行
} }
ps.close();
九、File类
public class FileTest {
public static void main(String[] args) {
// 使用File对象 模拟dir命令
File file = new File("C:\\Windows");
File[] listFiles = file.listFiles(); // 列出目录下的所有子文件和子目录
for (int i = 0; i < listFiles.length; i++) {
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm");
String dateTime = df.format(new Date(listFiles[i].lastModified()));
if(listFiles[i].isDirectory()) {
System.out.println(dateTime + "\tDIR\t\t" + listFiles[i].getName());
}else {
System.out.println(dateTime + "\t\t" + listFiles[i].length() + "\t" + listFiles[i].getName());
}
}
}
}
十、小结
字节流-缓冲流(重点):
输入流InputStream-FileInputStream-BufferedInputStream
输出流OutputStream-FileOutputStream-BufferedOutputStream
字符流-缓冲流(重点):
输入流Reader-FileReader-BufferedReader
输出流Writer-FileWriter-BufferedWriter-PrintWriter
转换流:
InputSteamReader和OutputStreamWriter
对象流:
ObjectInputStream和ObjectOutputStream(重点)
十一、Life
最难熬的状态就是,眼里操心着不再年轻的父母,脑子里想着乱七八糟的事业,心里还藏着一个不可能的姑娘,胸膛里还撑起着一个遥远的远方,像我们这种恶人,怎说得了动听得话
来源:CSDN
作者:SmallScorpion
链接:https://blog.csdn.net/qq_40180229/article/details/103826734