输入流,数据从源数据源流入程序的过程称为输入流。可以理解为从源数据源读取数据到程序的过程。
输出流,数据从程序流出到目的地的过程称为输出流。可以理解为把数据从程序写入目的地的过程。
数据源一般指提供数据的原始媒介,一般常见有文件、数据库、云端、其他硬件等能提供数据的媒介。
InputStream 是所有字节输入流的抽象父类,提供了以下方法:
FileInputStream 文件字节输入流,是 InputStream 的一个子类,专门用于从文件中读取字节到程序内存中。
1 //需求:从文件读取一个字节
2 public static void main(String[] args) {
3 File file = new File("d:\\javatest\\a.txt");
4
5 // 【1】创建管道
6 FileInputStream in = null;
7
8 try {
9 in = new FileInputStream(file);
10
11 // 【2】从管道读取一个字节
12 /*
13 int t;
14 t = in.read();
15 t = in.read();
16 t = in.read();
17 t = in.read();
18 */
19 // System.out.println(t);
20
21 // 循环读取一个字节
22 int t;
23 StringBuilder sb = new StringBuilder();
24 while( (t=in.read()) != -1 ) {
25 sb.append((char)t);
26 }
27 System.out.println(sb.toString());
28 } catch (FileNotFoundException e) {
29 e.printStackTrace();
30 } catch(IOException e) {
31 e.printStackTrace();
32 }
33
34 // 【3】关闭流管道
35 try {
36 in.close();
37 } catch (IOException e) {
38 e.printStackTrace();
39 }
40 }
1 //一次读取多个字节
2 public static void main(String[] args) {
3 File file = new File("d:\\javatest\\a.txt");
4
5 // 【1】创建管道
6 FileInputStream in = null;
7
8 try {
9 in = new FileInputStream(file);
10
11 // 【2】从管道读取多个字节到缓冲区
12 /*
13 byte[] buf = new byte[5];
14 int len;
15 len = in.read(buf);
16 len = in.read(buf);
17 len = in.read(buf);
18 len = in.read(buf);
19
20 for(byte b:buf) {
21 System.out.print((char)b+"\t");
22 }
23 System.out.println(len);
24 */
25
26 // 通过循环读取文件
27 byte[] buf = new byte[5];
28 int len;
29 StringBuilder sb = new StringBuilder();
30 while( (len=in.read(buf)) != -1 ) {
31 // 读取的内容是原始二进制流,需要根据编码的字符集解码成对于字符
32 String str = new String(buf,0,len);
33 sb.append(str);
34 }
35 System.out.println(sb.toString());
36 } catch (FileNotFoundException e) {
37 e.printStackTrace();
38 } catch(IOException e) {
39 e.printStackTrace();
40 }
41
42 // 【3】关闭流管道
43 try {
44 in.close();
45 } catch (IOException e) {
46 e.printStackTrace();
47 }
48 }
OutputStream 是所有字节输出流的抽象父类,提供了以下方法
FileOutputStream 文件字节输出流,专门用于从内存中写入字节到文件中。
1 public static void main(String[] args) {
2 File file = new File("d:\\javatest\\c.txt");
3
4 FileOutputStream out = null;
5
6 try {
7 // 【1】创建输出流管道
8 out = new FileOutputStream(file);
9
10 // 【2】写入数据到管道中
11 // 一次写入一个字节
12 /*
13 out.write(97);
14 out.write(98);
15 out.write(99);
16 */
17
18 // 一次写入多个字节
19 String str = "hello world";
20 // gbk
21 /*
22 byte[] buf = str.getBytes();
23 out.write(buf);
24 */
25
26 byte[] buf = str.getBytes("UTF-8");
27 out.write(buf);
28
29 System.out.println("写入完成!");
30
31 } catch (FileNotFoundException e) {
32 e.printStackTrace();
33 } catch (IOException e) {
34 e.printStackTrace();
35 }
36
37 // 【3】关闭流
38 try {
39 out.close();
40 } catch (IOException e) {
41 e.printStackTrace();
42 }
43 }
注意:
InputStream/OutputStream 用于字节的读写。主要用于读写二进制文件(图片、音频、视频),较少用于读写文本型文件。对于文本型文件可以使用 Reader/Writer 类。
Reader 是字符输入流的抽象父类,提供了
FileReader 文件字符输入流,专门用于读取默认字符编码文本性文件。
1 //需求:一次读取一个字符/多个字符到cbuf
2 public static void main(String[] args) throws IOException {
3
4 File file = new File("d:\\javatest\\d.txt");
5
6 FileReader reader = new FileReader(file);
7
8 // 【1】一次读取一个字符
9 /*
10 int c;
11 c = reader.read();
12 c = reader.read();
13 c = reader.read();
14 c = reader.read();
15 c = reader.read();
16 System.out.println((char)c);
17 */
18
19 // 【2】一次读取多个字符到cbuf中
20 /*
21 char[] cbuf = new char[2];
22 int len;
23 len = reader.read(cbuf);
24 len = reader.read(cbuf);
25 len = reader.read(cbuf);
26 len = reader.read(cbuf);
27 System.out.println(Arrays.toString(cbuf));
28 System.out.println(len);
29 */
30
31 char[] cbuf = new char[2];
32 int len;
33 StringBuilder sb = new StringBuilder();
34 while( (len=reader.read(cbuf)) != -1 ) {
35 sb.append(cbuf,0,len);
36 }
37
38 System.out.println(sb);
39 }
Writer 是字符输出流的抽象父类,提供了
FileWriter 文件字符输出流,专门用于写入默认字符编码的文本性文件。为了提高效率,File-Writer内部存在一个字节缓冲区,用于对待写入的字符进行统一编码到字节缓冲区,一定要在关闭流之前,调用flush方法刷新缓冲区,才能完成写入。
1 //需求:写入字符到文件中
2 public static void main(String[] args) throws IOException {
3 File file = new File("d:\\javatest\\f.txt");
4
5 FileWriter writer = new FileWriter(file);
6
7 // 【1】一次写入一个字符
8 /*writer.write('中');
9 writer.write('国');*/
10
11 // 【2】一次写入多个字符
12 /*char[] cbuf = {'h','e','l','l','o','中','国'};
13 writer.write(cbuf);*/
14
15 // 【3】一次写入一个字符串
16 String str = "hello你好";
17 writer.write(str);
18
19
20 // 刷新字节缓冲区
21 writer.flush();
22
23 // 关闭流通道
24 writer.close();
25
26 System.out.println("写入完成");
27 }
InputStreamReader继承于Reader,是字节流通向字符流的桥梁,可以把字节流按照指定编码 解码 成字符流。
OutputStreamWriter 继承于 Writer,是字符流通向字节流的桥梁,可以把字符流按照指定的编码 编码 成字节流。
1 public class Test {
2 public static void main(String[] args) throws IOException {
3
4
5 String str = "hello中国";
6 File file = new File("d:\\javatest\\g.txt");
7
8 // 【1】创建管道
9 FileOutputStream out = new FileOutputStream(file);
10 OutputStreamWriter writer = new OutputStreamWriter(out, "utf8");
11
12 // 【2】写入管道
13 writer.write(str);
14
15 // 【3】刷新缓冲区
16 writer.flush();
17
18 // 【4】关闭管道
19 out.close();
20 writer.close();
21
22 System.out.println("写入完成");
23 }
24 }
1 public class Test01 {
2 public static void main(String[] args) throws IOException {
3
4 File file = new File("d:\\javatest\\g.txt");
5
6 // 【1】建立管道
7 FileInputStream in = new FileInputStream(file);
8 InputStreamReader reader = new InputStreamReader(in, "UTF-8");
9
10 char[] cbuf = new char[2];
11 int len;
12
13 StringBuilder sb = new StringBuilder();
14 while( (len=reader.read(cbuf))!=-1 ) {
15 sb.append(cbuf, 0, len);
16 }
17 System.out.println(sb.toString());
18
19 }
20 }
Windows 平台默认的 utf8 编码的文本性文件带有 BOM 标识,java 转换流写入的 utf8 文件不带 BOM 标识。所以用 java 读取手动创建的 utf8 文件会出现一点乱码(?hello中国,"?"是 BOM 标识导致的)。
BufferedReader 继承于Reader,提供了
BufferedReader 初始化时需要一个 Reader,本质上 BufferedReader 在 Reader 的基础上增加 readLine() 的功能。
1 //需求:读取一首诗
2 public static void main(String[] args) throws IOException {
3
4 // 按行读取gbk文本性文件
5
6 File file = new File("d:\\javatest\\i.txt");
7
8 // 【1】创建管道
9 FileReader reader = new FileReader(file);
10 BufferedReader br = new BufferedReader(reader);
11
12 // 【2】读取一行
13 /*
14 String line = br.readLine();
15 line = br.readLine();
16 line = br.readLine();
17 line = br.readLine();
18 */
19
20 String line;
21 while( (line=br.readLine()) != null) {
22 System.out.println(line);
23 }
24 }
BufferedWriter继承于Writer,提供了
1 //需求:以gbk编码写入一首诗到文件
2 public static void main(String[] args) throws IOException {
3
4 File file = new File("d:\\javatest\\j.txt");
5
6 // 【1】创建gbk管道
7 FileWriter writer = new FileWriter(file);
8 BufferedWriter bw = new BufferedWriter(writer);
9
10 // 【2】写入一行
11 bw.write("窗前明月光,");
12 bw.newLine();
13
14 bw.write("疑似地上霜。");
15
16 // for win
17 // bw.write("\r\n");
18
19 // for unix/linux/mac
20 // bw.write("\n");
21
22 bw.write("举头望明月,");
23 bw.newLine();
24
25 // 【3】flush
26 bw.flush();
27
28 // 【4】关闭管道
29 bw.close();
30 writer.close();
31 }
1 //需求:以utf8编码高效写入文件
2 public static void main(String[] args) throws IOException {
3
4 File file = new File("d:\\javatest\\j-utf8.txt");
5
6 // 【1】创建utf8管道
7 FileOutputStream out = new FileOutputStream(file);
8 OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
9 BufferedWriter bw = new BufferedWriter(writer);
10
11 // 【2】写入一行
12 bw.write("窗前明月光,");
13 bw.newLine();
14
15 bw.write("疑似地上霜。");
16
17 // for win
18 bw.write("\r\n");
19
20 // for unix/linux/mac
21 // bw.write("\n");
22
23 bw.write("举头望明月,");
24 bw.newLine();
25
26 // 【3】flush
27 bw.flush();
28
29 // 【4】关闭管道
30 bw.close();
31 writer.close();
32 }