IO(上)

1 输入流和输出流

输入流,数据从源数据源流入程序的过程称为输入流。可以理解为从源数据源读取数据到程序的过程。

输出流,数据从程序流出到目的地的过程称为输出流。可以理解为把数据从程序写入目的地的过程。

数据源一般指提供数据的原始媒介,一般常见有文件、数据库、云端、其他硬件等能提供数据的媒介。

2 流的分类

3 InputStream/OutputStream

InputStream 是所有字节输入流的抽象父类,提供了以下方法:

  • read() 读取一个字节
  • read(byte[] buf) 读取一定量的字节到缓冲区数组 buf中。

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 是所有字节输出流的抽象父类,提供了以下方法

  • write() 写入一个字节
  • write(byte[] buf) 写入一定量的字节到输出流

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 }

注意:

  1. 字符串写入文件时一定会存在编码问题。
  2. 通过字节流写入文件时,向管道写入一个字节,该字节立即写入文件中。

InputStream/OutputStream 用于字节的读写。主要用于读写二进制文件(图片、音频、视频),较少用于读写文本型文件。对于文本型文件可以使用 Reader/Writer 类。

4 Reader/Writer

Reader 是字符输入流的抽象父类,提供了

  • read() 一次读取一个字符
  • read(char[] cbuf) 一次读取多个字符到字符缓冲区cbuf,返回长度表示读取的字符个数。

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 是字符输出流的抽象父类,提供了

  • write()
  • write(char[] cbuf)
  • write(String str)

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 }

5 转换流

InputStreamReader继承于Reader,是字节流通向字符流的桥梁,可以把字节流按照指定编码 解码 成字符流。

OutputStreamWriter 继承于 Writer,是字符流通向字节流的桥梁,可以把字符流按照指定的编码 编码 成字节流。

  • 把一个字符串以utf8编码写入文件
 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 }
  • 读取utf8文件
 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 标识导致的)。

6 BufferedReader/BufferedWriter

BufferedReader 继承于Reader,提供了

  • read()
  • read(char[] cbuf)
  • readLine() 用于读取一行文本,实现对文本的高效读取。

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,提供了

  • write()
  • write(char[] cbuf)
  • write(String str)
  • newline() 写入一个行分隔符。
 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 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券