流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入输出都是以流的方式进行。设备可以是文件、网络、内存等。

I/O字节流

InputStream字节输入流
OutputStream字节输出流
用于以字节的形式读取和写入数据

以字节流的形式读取文件内容

InputStream 是字节输入流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。

FileInputStream 是InputStream子类,以FileInputStream 为例进行文件读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.lfh.learn;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Learn {
public static void main(String[] args) {

try {
// 读入文件
File file = new File("D:\\Desktop\\1.txt");
FileInputStream inputStream = new FileInputStream(file);
// 创建基于文件的输入流
byte[] all = new byte[(int) file.length()];
// 以字节流的形式读取文件的全部内容
inputStream.read(all);
for (byte b : all) {
System.out.println(b);
}
// 最后关闭流
inputStream.close();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
kaanKj.png

文件内容

kaallc.png

读取到的内容

以字节流的形式向文件写入数据

OutputStream是字节输出流,同时也是抽象类,只提供方法声明,不提供方法的具体实现。
FileOutputStream 是OutputStream子类,以FileOutputStream 为例向文件写出数据

注: 如果文件D:\Desktop\1.txt不存在,写出操作会自动创建该文件。
但是如果是文件 D:\Desktop\xyz\1.txt,而目录xyz又不存在,会抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.lfh.learn;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Learn {
public static void main(String[] args) {

try {
// 读入文件
File file = new File("D:\\Desktop\\1.txt");
// 创建基于文件的输入流
byte[] all = new byte[] { 98, 99 };
FileOutputStream onputStream = new FileOutputStream(file);
// 以字节流的形式向文件写入数据
onputStream.write(all);
System.out.println("写入成功");
// 最后关闭流
onputStream.close();

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
kaauhK.png

运行后文件中的内容

关闭流的方式

所有的流,无论输入流还是输出流,使用完毕之后,都应该关闭。如果不关闭,会产生对资源占用的浪费。当量比较大的时候,回影响到争正常的业务开展。

(1)在try中关闭(最容易错的方式,不推荐使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package stream;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class TestStream {

public static void main(String[] args) {
try {
File f = new File("D:\\Desktop\\1.txt");
FileInputStream fis = new FileInputStream(f);
byte[] all = new byte[(int) f.length()];
fis.read(all);
for (byte b : all) {
System.out.println(b);
}
// 在try 里关闭流
fis.close();
} catch (IOException e) {
e.printStackTrace();
}

}
}

这种方式存在弊端,即:如果文件不存在或者读取的时候抛出异常,那么就不会执行到关闭流的那一行代码,这就存在巨大的资源隐患。

(2)在finally中关闭(标准的关闭流方式)

  • 首先把流的引用声明在try外面,如果声明在里面的话,其作用域无法到达finally。
  • 在finally关闭之前,要先判断该引用是否为空
  • 关闭的时候,需要再进行以此try catch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.lfh.learn;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Learn {
public static void main(String[] args) {
FileOutputStream onputStream = null;
try {
// 读入文件
File file = new File("D:\\Desktop\\1.txt");
// 创建基于文件的输入流
byte[] all = new byte[] { 98, 99 };
onputStream = new FileOutputStream(file);
// 以字节流的形式向文件写入数据
onputStream.write(all);
System.out.println("写入成功");

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 最后关闭流
if (onputStream != null) {
try {
onputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

}
}

(3)使用try()的方式关闭

把流定义在try()里,try,catch或者finally结束的时候,会自动关闭。这种编写代码的方式叫做 try-with-resources, 这是从JDK7开始支持的技术

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.lfh.learn;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class Learn {
public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");
try (FileOutputStream onputStream = new FileOutputStream(file)) {
// 创建基于文件的输入流
byte[] all = new byte[] { 98, 99 };
// 以字节流的形式向文件写入数据
onputStream.write(all);
System.out.println("写入成功");

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

I/O字符流

Reader字符输入流
Writer字符输出流
专门用于字符的形式读取和写入数据

使用字符流读取文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.lfh.learn;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class Learn {
public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");
//将流放在try()中,不需要手动关闭了
try (FileReader fileReader = new FileReader(file)) {
char[] content = new char[(int) file.length()];
// 以字符流的形式读取文件所有内容
fileReader.read(content);
for (char c : content) {
System.out.println(c);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
kaauhK.png

文件内容

kaabYv.png

读取到的内容

使用字符流把字符写入到文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.lfh.learn;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Learn {
public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");
try (FileWriter fileWriter = new FileWriter(file)) {
char[] content = new char[] {'L','L','L','L'};
// 以字符流的形式写入到文件中
fileWriter.write(content);
System.out.println("写入成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}
kaa9pG.png

写入后的文件内容

I/O缓存流

以介质是硬盘为例,字节流和字符流都存在弊端 ,在每一次读写的时候,都会访问硬盘。如果读写的频率比较高,那么性能表现不佳。为了解决该弊端,则采用缓存流。

缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中去读取。

缓存流在写入数据的时候,会先把数据写入到缓存区中,直到缓存区达到一定量,才把这些数据,一起写到硬盘中。按照这种方式,可以大大减少IO操作。

使用缓存流读取数据

缓存字符输入流 BufferedReader 可以一次读取一行数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.lfh.learn;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

public class Learn {
public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");

// 注意:缓存流必须建立在一个存在流的基础上
try (FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);) {
while (true) {
String line = bufferedReader.readLine();
if (null == line)
break;
System.out.println(line);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

值得注意的是,缓存流必须建立在一个存在的流之上才能使用。

使用缓存流写出数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.lfh.learn;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

public class Learn {
public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");

// 注意:缓存流必须建立在一个存在流的基础上
try (FileWriter fileWriter = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);) {
bufferedWriter.write("123");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

之后文件内容就变为了123

有时候,需要立即把数据写入到硬盘,而不是等缓存满了才写进去,这时候就要用到flush

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.lfh.learn;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

public class Learn {
public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");

// 注意:缓存流必须建立在一个存在流的基础上
try (FileWriter fileWriter = new FileWriter(file);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);) {
bufferedWriter.write("123");
// 强制写入,无论缓存是否已满
bufferedWriter.flush();
bufferedWriter.write("123");
bufferedWriter.flush();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
kabcCv.png

写入后的文件内容

I/O数据流

DataInputStream 数据输入流
DataOutputStream 数据输出流

直接进行字符串的读写

使用数据流的writeUTF()和readUTF() 可以进行数据的格式化顺序读写
如本例,通过DataOutputStream 向文件顺序写出 布尔值,整数和字符串。 然后再通过DataInputStream 顺序读入这些数据。

注: 要用DataInputStream 读取一个文件,这个文件必须是由DataOutputStream 写出的,否则会出现EOFException,因为DataOutputStream 在写出的时候会做一些特殊标记,只有DataInputStream 才能成功的读取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.lfh.learn;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Learn {

public static void read(File file) {
// 注意:数据流必须建立在字节流的基础上
try (FileInputStream fileInputStream = new FileInputStream(file);
DataInputStream dataInputStream = new DataInputStream(fileInputStream);) {

boolean readBoolean = dataInputStream.readBoolean();
int readInt = dataInputStream.readInt();
String readUTF = dataInputStream.readUTF();

System.out.println("读到的布尔值为:" + readBoolean + "");
System.out.println("读到的整型为:" + readInt + "");
System.out.println("读到的字符串为:" + readUTF);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

public static void write(File file) {
// 注意:数据流必须建立在字节流的基础上
try (FileOutputStream fileOutputStream = new FileOutputStream(file);
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);) {
dataOutputStream.writeBoolean(true);
dataOutputStream.writeInt(6);
dataOutputStream.writeUTF("刘方涵");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

public static void main(String[] args) {
File file = new File("D:\\Desktop\\1.txt");
write(file);
read(file);
}
}
kab7Nj.png

写入后的文件内容

kabNWN.png

代码运行输出

相关文章
评论
分享
  • Windows下neo4j的安装

    neo4j是一个高性能的NOSQL图形数据库,他将结构化数据存储在网络上而不是表中。他是一个嵌入式的、基于磁盘的、具备完全的事物特性的Java持久化引擎,neo4j也可看做是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。——百度...

    Windows下neo4j的安装
  • java实现类FTP程序

    继承程序设计实验,实验说明如图所示: 集成程序设计实验 TCP实现首先说明下基于TCP实现的功能: (1)能够实现多用户的同时连接 (2)用户执行成功的命令会在其他用户终端上显式说明 (3)当前用户数以及在线情况会在服务端实时显...

    java实现类FTP程序
  • eclipse使用

    Eclipse是一个开放源代码的、基于Java的可拓展开发平台。 常用快捷键 快捷键 作用 alt+/ 代码快速补全 ctrl+1 快速修复 ctrl+shift+f 代码格式化 ctrl+d 删除一行代码 ...

    eclipse使用
  • Python网络编程

    网络编程从大的方面说就是对信息的发送到接收,中间传输为物理线路的作用。 它的含义是使用套接字来达到进程间的通信。套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点。 套接字Socket=(IP地址:端口号) 端口号是...

    Python网络编程
  • Centos安装

    虚拟机下载及安装1.进入VMware官网,转到下载页面 https://my.vmware.com/cn/web/vmware/info/slug/desktop_end_user_computing/vmware_workstati...

    Centos安装
  • JavaEE开发准备

    个人电脑硬件配置: Windows 10 64位家庭中文版 8G运行内存 Intel(R) Core(TM) i5-7300HQ CPU @ 2.50GHz 1.Java JDK安装及配置(1)下载和安装首先进入oracle网站中Ja...

    JavaEE开发准备
  • Python进阶学习

    假期补习补习Python,防止以后用到炸锅。 闭包在Python语言中,一切皆对象。 闭包:一个函数定义中引用了函数外定义的变量,并且该函数可以在其定义环境外被执行。 闭包 = 函数 + 环境变量 123456789101...

    Python进阶学习
  • 推荐算法研究(一)

    推荐算法大体分为3类:基于系统过滤的推荐、基于内容的推荐、混合推荐 1.基于协同过滤的推荐系统(Collaborative Filtering)使用行为数据,利用集体智慧来推荐。属于有监督学习。基于用户的协同过滤(找和你兴趣相似的人所...

    推荐算法研究(一)
  • dart中HTTP请求的处理

    dio是一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时、自定义适配器等… ,最重要的是国人开发,牛皮。 (1)添加dio库 找到项目中的pu...

    dart中HTTP请求的处理
  • dart底部导航栏的简单编写

    底部导航栏目前在手机应用中非常常见,可见其对于软件设计来说非常的有必要和重要。下面简单总结使用flutter和dart如何实现底部导航栏的制作。 首先值得注意的是底部导航栏为动态的组件,所以继承的话应该是StatefulWidget类...

    dart底部导航栏的简单编写
Please check the comment setting in config.yml of hexo-theme-Annie!