首页 > 技术文章 > IO流(字节流主要用于读写二进制文件;字符流主要用于读写文本性文件)

qq2267711589 2019-05-06 22:37 原文

1.  File类

File类在java中表示(带路径的)文件或者目录

1).File常用属性和方法

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          // 给定路径创建File对象
 6 
 7          // File file = new File("D:"+File.separator+"javatest"+File.separator+"a.txt");
 8 
 9          File file = new File("d:\\javatest\\b.mp3");
10 
11          System.out.println(file);
12 
13         
14 
15          // 文件基本属性
16 
17          System.out.println(file.canExecute());
18 
19          System.out.println(file.canRead());
20 
21          System.out.println(file.canWrite());
22 
23         
24 
25          // 文件的创建、删除
26 
27          if(!file.exists()) {
28 
29              
30 
31               booleanr;
32 
33               try {
34 
35                    r = file.createNewFile();
36 
37                    if(r) {
38 
39                        System.out.println("文件创建成功");
40 
41                    }
42 
43               } catch (IOExceptione) {
44 
45                    e.printStackTrace();
46 
47               }
48 
49          }
50 
51         
52 
53          // 删除文件
54 
55          file.delete();
56 
57      }

创建文件时会抛出检查时异常IOException

2).File的路径相关

 

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5           File file = new File("d:\\javatest\\a");
 6 
 7 //       File file = new File("a.txt");
 8 
 9         
10 
11          // 获取file的绝对路径
12 
13          System.out.println(file.getAbsolutePath());
14 
15          // 获取file的创建时的路径字符串
16 
17          System.out.println(file.getPath());
18 
19          // 获取文件或者目录的名字
20 
21          System.out.println(file.getName());
22 
23          // 获取文件或者目录的父目录
24 
25          System.out.println(file.getParent());
26 
27         
28 
29      }

 

注意:如果file是相对路径,相对路径的当前路径是工程目录(java17)

3). 目录的创建

 1 public static void main(String[] args) {
 2 
 3        
 4 
 5          File file = new File("d:\\javatest\\c\\d\\e");
 6 
 7        
 8 
 9         if(!file.exists()) {
10 
11             booleanr;
12 
13            
14 
15             try {
16 
17                 // 一次只能创建一个目录
18 
19                 // r = file.mkdir();
20 
21                 r = file.mkdirs();
22 
23                 if(r) {
24 
25                     System.out.println("目录创建成功");
26 
27                 }
28 
29             } catch (Exception e) {
30 
31                 e.printStackTrace();
32 
33             }
34 
35            
36 
37          }
38 
39     }

4).目录的遍历

list():返回一个file表示的目录中的子目录或者文件,字符串数组类型

listFiles():返回一个file表示的目录中的子目录或者文件,File数组类型

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          // 需求:遍历d:\javatest目录
 6 
 7          // list()
 8 
 9          Filefile=  newFile("d:\\javatest");
10 
11         
12 
13         
14 
15          /*
16 
17          String[] list = file.list();
18 
19         
20 
21          for (String str : list) {
22 
23               System.out.print(str);
24 
25               File f = new File(file.getPath()+"\\"+str);
26 
27               if(f.isDirectory()) {
28 
29                    System.out.println(" 目录");
30 
31               }else {
32 
33                    System.out.println(" 文件");
34 
35               }
36 
37          }*/
38 
39         
40 
41         
42 
43          // listFiles();
44 
45          File[] listFiles = file.listFiles();
46 
47          for (Filef :listFiles) {
48 
49               System.out.print(f.getName());
50 
51               if(f.isDirectory()) {
52 
53                    System.out.println(" 目录");
54 
55               }else {
56 
57                    System.out.println(" 文件");
58 
59               }
60 
61          }
62 
63      }

2. IO流

1).  流

流(stream):流是一连串流动的数据(字节、字符),以先进先出的方式发送的信息的通道中。

2).  输入流和输出流

输入流

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

 

 

 

输出流

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

 

 

 

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

 

3).  流的分类

按照流向分为输入流和输出流

按照处理单元分为字节流和字符流

按照功能分为节点流和转换流。

 

 

 

3 .  InputStream/OutputStream

InputStream  是所有字节输入流的抽象父类,提供了

read   读取一个字节

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

 

OutputStream  是所有字节输出流的抽象父类,提供了

write() 写入一个字节

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

 

FileInputStream文件字节输入流,专门用于从文件中读取字节到程序内存中。

FileOutputStream文件字节输出流,专门用于从内存中写入字节到文件中。

 

需求:从文件读取一个字节

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5          // 需求:读取一个文件中的一个字节
 6 
 7          File file = new File("d:\\javatest\\a.txt");
 8 
 9         
10 
11          // 【1】创建管道
12 
13          FileInputStreamin = null;
14 
15         
16 
17          try {
18 
19               in = newFileInputStream(file);
20 
21              
22 
23               // 【2】从管道读取一个字节
24 
25               /*
26 
27               int t;
28 
29               t = in.read();
30 
31               t = in.read();
32 
33               t = in.read();
34 
35               t = in.read();
36 
37               */
38 
39               // System.out.println(t);
40 
41              
42 
43               // 循环读取一个字节
44 
45               intt;
46 
47               StringBuildersb = newStringBuilder();
48 
49               while( (t=in.read()) != -1 ) {
50 
51                    sb.append((char)t);
52 
53               }
54 
55              
56 
57               System.out.println(sb.toString());
58 
59              
60 
61              
62 
63              
64 
65          } catch (FileNotFoundExceptione) {
66 
67               e.printStackTrace();
68 
69          } catch(IOExceptione) {
70 
71               e.printStackTrace();
72 
73          }
74 
75         
76 
77          // 【3】关闭流管道
78 
79          try {
80 
81               in.close();
82 
83          } catch (IOExceptione) {
84 
85               e.printStackTrace();
86 
87          }
88 
89      }

一次读取多个字节

  1 public static void main(String[] args) {
  2 
  3         
  4 
  5          // 需求:一次读取多个字节
  6 
  7          File file = new File("d:\\javatest\\a.txt");
  8 
  9         
 10 
 11          // 【1】创建管道
 12 
 13           FileInputStreamin = null;
 14 
 15         
 16 
 17          try {
 18 
 19               in = newFileInputStream(file);
 20 
 21              
 22 
 23               // 【2】从管道读取多个字节到缓冲区
 24 
 25               /*
 26 
 27               byte[] buf = new byte[5];
 28 
 29               intlen;
 30 
 31               len = in.read(buf);
 32 
 33               len = in.read(buf);
 34 
 35               len = in.read(buf);
 36 
 37               len = in.read(buf);
 38 
 39              
 40 
 41               for(byte b:buf) {
 42 
 43                    System.out.print((char)b+"\t");
 44 
 45               }
 46 
 47               System.out.println(len);
 48 
 49               */
 50 
 51              
 52 
 53               // 通过循环读取文件
 54 
 55               byte[] buf = newbyte[5];
 56 
 57               intlen;
 58 
 59               StringBuildersb = newStringBuilder();
 60 
 61               while( (len=in.read(buf)) != -1 ) {
 62 
 63                    // 读取的内容是原始二进制流,需要根据编码的字符集解码成对于字符
 64 
 65                    String str = new String(buf,0,len);
 66 
 67                    sb.append(str);
 68 
 69               }
 70 
 71               System.out.println(sb.toString());
 72 
 73              
 74 
 75              
 76 
 77              
 78 
 79              
 80 
 81          } catch (FileNotFoundExceptione) {
 82 
 83               e.printStackTrace();
 84 
 85          } catch(IOExceptione) {
 86 
 87               e.printStackTrace();
 88 
 89          }
 90 
 91         
 92 
 93          // 【3】关闭流管道
 94 
 95          try {
 96 
 97               in.close();
 98 
 99          } catch (IOExceptione) {
100 
101               e.printStackTrace();
102 
103          }
104 
105      }

需求:按照指定编码写入文件

 1 public static void main(String[] args) {
 2 
 3         
 4 
 5         
 6 
 7          File file = new File("d:\\javatest\\c.txt");
 8 
 9         
10 
11          FileOutputStreamout = null;
12 
13         
14 
15          try {
16 
17               // 【1】创建输出流管道
18 
19               out = newFileOutputStream(file);
20 
21              
22 
23               // 【2】写入数据到管道中
24 
25               // 一次写入一个字节
26 
27               /*
28 
29               out.write(97);
30 
31               out.write(98);
32 
33               out.write(99);
34 
35               */
36 
37              
38 
39               // 一次写入多个字节
40 
41               String str = "hello world";
42 
43               // gbk
44 
45               /*
46 
47               byte[] buf = str.getBytes();
48 
49               out.write(buf);
50 
51               */
52 
53              
54 
55               byte[] buf = str.getBytes("UTF-8");
56 
57               out.write(buf);
58 
59              
60 
61               System.out.println("写入完成!");
62 
63              
64 
65          } catch (FileNotFoundExceptione) {
66 
67               e.printStackTrace();
68 
69          } catch (IOExceptione) {
70 
71               e.printStackTrace();
72 
73          }
74 
75         
76 
77          // 【3】关闭流
78 
79          try {
80 
81               out.close();
82 
83          } catch (IOExceptione) {
84 
85               e.printStackTrace();
86 
87          }
88 
89      }

注意:

[1]字符串写入文件时一定会存在编码问题

[2]使用utf8编码写入文件时,如果不含中文时,win系统会对文件的编码造成误判。

[3]通过字节流写入文件时,向管道写入一个字节,该字节立即写入文件中。

 

总结

InputStream/OutputStream用于字节的读写。主要用于读取二进制文件(图片、音频、视频),也可以读取文件性文件。

 

需求:请把d:\\javatest\\logo.png 复制到工程目录中,并显示复制进度。

public static void main(String[] args) throwsFileNotFoundException,IOException {

        File oriFile = new File("d:\\javatest\\logo.jpg");

        File toFile = new File("logo.jpg");

 
        longtotalLen = oriFile.length();    // 文件大小

        longcpyedLen = 0;   // 已复制完成的大小

        floatprogress = 0.0f;

       

        FileInputStreamin = newFileInputStream(oriFile);

        FileOutputStreamout = newFileOutputStream(toFile);

       
        // 一次读取1kb

        byte[] buf = newbyte[512];

        intlen;

        while( (len=in.read(buf)) != -1) {

            out.write(buf, 0, len);

            cpyedLen += len;

            progress = cpyedLen*1.0f/totalLen;

            System.out.println(progress);
         

        }

       

        in.close();

        out.close();

       

        System.out.println("复制完成!");

       

    }

4.Reader/Writer

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

read一次读取一个字符

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

 

Writer是字符输出流的抽象父类,提供了

write

write(char[] cbuf)

write(string)

 

FileReader文件字符输入流,专门用于读取默认字符编码文本性文件。

 

FileWriter文件字符输出流,专门用于写入默认字符编码的文本性文件。为了提高效率,FileWriter内部存在一个字节缓冲区,用于对待写入的字符进行统一编码到字节缓冲区,一定要在关闭流之前,调用flush方法刷新缓冲区。

 

需求:一次读取一个字符/多个字符到cbuf

 1 public static void main(String[] args) throwsIOException {
 2 
 3        
 4 
 5         File file = new File("d:\\javatest\\d.txt");
 6 
 7        
 8 
 9         FileReaderreader = newFileReader(file);
10 
11        
12 
13         // 【1】一次读取一个字符
14 
15         /*
16 
17         int c;
18 
19         c = reader.read();
20 
21         c = reader.read();
22 
23         c = reader.read();
24 
25         c = reader.read();
26 
27         c = reader.read();
28 
29         System.out.println((char)c);
30 
31         */
32 
33        
34 
35         // 【2】一次读取多个字符到cbuf中
36 
37         /*
38 
39         char[] cbuf = new char[2];
40 
41         intlen;
42 
43         len = reader.read(cbuf);
44 
45         len = reader.read(cbuf);
46 
47         len = reader.read(cbuf);
48 
49         len = reader.read(cbuf);
50 
51         System.out.println(Arrays.toString(cbuf));
52 
53         System.out.println(len);
54 
55         */
56 
57        
58 
59         char[] cbuf = newchar[2];
60 
61         intlen;
62 
63         StringBuildersb = newStringBuilder();
64 
65         while( (len=reader.read(cbuf)) != -1 ) {
66 
67             sb.append(cbuf,0,len);
68 
69         }
70 
71        
72 
73         System.out.println(sb);
74 
75     }

需求:写入字符到文件中

 1 public static void main(String[] args) throwsIOException {
 2 
 3         
 4 
 5         
 6 
 7          File file = new File("d:\\javatest\\f.txt");
 8 
 9         
10 
11          FileWriterwriter = newFileWriter(file);
12 
13         
14 
15          // 【1】一次写入一个字符
16 
17          /*writer.write('中');
18 
19          writer.write('国');*/
20 
21         
22 
23          // 【2】一次写入多个字符
24 
25          /*char[] cbuf = {'h','e','l','l','o','中','国'};
26 
27          writer.write(cbuf);*/
28 
29         
30 
31          // 【3】一次写入一个字符串
32 
33          String str = "hello你好";
34 
35          writer.write(str);
36 
37         
38 
39         
40 
41          // 刷新字节缓冲区
42 
43          writer.flush();
44 
45         
46 
47          // 关闭流通道
48 
49          writer.close();
50 
51         
52 
53          System.out.println("写入完成");
54 
55      }

5. 转换流

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

 

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

1.5.1            转换流工作原理

 

 

 

需求:写入utf8文件

 1 /**
 2 
 3  * 把一个字符串以utf8编码写入文件
 4 
 5  */
 6 
 7 publicclass Test01 {
 8 
 9      public static void main(String[] args) throwsIOException {
10 
11         
12 
13         
14 
15          String str = "hello中国";
16 
17          File file = new File("d:\\javatest\\g.txt");
18 
19         
20 
21          // 【1】创建管道
22 
23          FileOutputStreamout = newFileOutputStream(file);
24 
25          OutputStreamWriterwriter = newOutputStreamWriter(out, "utf8");
26 
27         
28 
29          // 【2】写入管道
30 
31          writer.write(str);
32 
33         
34 
35          // 【3】刷新缓冲区
36 
37          writer.flush();
38 
39         
40 
41          // 【4】关闭管道
42 
43          out.close();
44 
45          writer.close();
46 
47         
48 
49          System.out.println("写入完成");
50 
51      }
52 
53 }

 

需求:读取utf8文件

 1 /**
 2 
 3  * 读取utf8编码的文本文件
 4 
 5  */
 6 
 7 public class Test01 {
 8 
 9      public static void main(String[] args) throwsIOException {
10 
11         
12 
13          File file = new File("d:\\javatest\\g.txt");
14 
15         
16 
17          // 【1】建立管道
18 
19          FileInputStreamin = newFileInputStream(file);
20 
21          InputStreamReaderreader = newInputStreamReader(in, "UTF-8");
22 
23         
24 
25          char[] cbuf = newchar[2];
26 
27          intlen;
28 
29         
30 
31          StringBuildersb = newStringBuilder();
32 
33          while( (len=reader.read(cbuf))!=-1 ) {
34 
35               sb.append(cbuf, 0, len);
36 
37          }
38 
39          System.out.println(sb.toString());
40 
41         
42 
43      }
44 
45 }

 

注意:

[1]win平台默认的utf8编码的文本性文件带有BOM,java转换流写入的utf8文件不带BOM。所以用java读取手动创建的utf8文件会出现一点乱码(?hello中国,?是bom导致的)《详情见下篇文章》

[2]一句话:用字符集编码,一定用字符集解码!!

 

总结:

FileReader = InputStreamReader + GBK

 1 packagecn.sxt07.outputstreamwriter;
 2 
 3  
 4 
 5 importjava.io.File;
 6 
 7 importjava.io.FileInputStream;
 8 
 9 importjava.io.FileReader;
10 
11 importjava.io.IOException;
12 
13 importjava.io.InputStreamReader;
14 
15  
16 
17 /**
18 
19  * 读取一个gbk编码的文本性文件
20 
21  */
22 
23 publicclass Test02 {
24 
25      public static void main(String[] args) throwsIOException {
26 
27         
28 
29         
30 
31          File file = new File("d:\\javatest\\f.txt");
32 
33         
34 
35          // 【1】建立管道
36 
37          /*
38 
39           * FileInputStream in = new FileInputStream(file);
40 
41           * InputStreamReader reader =  newInputStreamReader(in, "GBK");
42 
43           */
44 
45  
46 
47          FileReaderreader = newFileReader(file);
48 
49         
50 
51          char[] cbuf = newchar[2];
52 
53          intlen;
54 
55         
56 
57          StringBuildersb = newStringBuilder();
58 
59          while( (len=reader.read(cbuf))!=-1 ) {
60 
61               sb.append(cbuf, 0, len);
62 
63          }
64 
65         
66 
67          reader.close();
68 
69         
70 
71          System.out.println(sb.toString());
72 
73      }
74 
75 }

6. BufferedReader/BufferedWriter

BufferedReader继承于Reader,提供了

read

read(char[] cbuf)

readLine() 用于读取一行文本,实现对文本的高效读取。

BufferedReader初始化时需要一个reader,本质上BufferedReader在reader的基础上增加readLine()的功能。

 

BufferedWriter继承于Writer,提供了

write

write(char[] cbuf)

write(string)

newLine() 写入一个行分隔符。

 

需求:读取一首诗

 1 public static void main(String[] args) throwsIOException {
 2 
 3                   
 4 
 5          // 按行读取gbk文本性文件
 6 
 7         
 8 
 9          File file = new File("d:\\javatest\\i.txt");
10 
11         
12 
13          // 【1】创建管道
14 
15          FileReaderreader = newFileReader(file);
16 
17          BufferedReaderbr = newBufferedReader(reader);
18 
19         
20 
21          // 【2】读取一行
22 
23          /*
24 
25          String line =  br.readLine();
26 
27          line =  br.readLine();
28 
29          line =  br.readLine();
30 
31          line =  br.readLine();
32 
33          */
34 
35         
36 
37          String line;
38 
39          while( (line=br.readLine()) != null) {
40 
41               System.out.println(line);
42 
43          }
44 
45      }

需求:以gbk编码写入一首诗到文件

 1 public static void main(String[] args) throwsIOException {
 2 
 3         
 4 
 5          File file = new File("d:\\javatest\\j.txt");
 6 
 7         
 8 
 9          // 【1】创建gbk管道
10 
11          FileWriterwriter = newFileWriter(file);
12 
13          BufferedWriterbw = newBufferedWriter(writer);
14 
15         
16 
17          // 【2】写入一行
18 
19          bw.write("窗前明月光,");
20 
21          bw.newLine();
22 
23         
24 
25          bw.write("疑似地上霜。");
26 
27         
28 
29          // for win
30 
31          // bw.write("\r\n");
32 
33         
34 
35          // for unix/linux/mac
36 
37          // bw.write("\n");
38 
39         
40 
41          bw.write("举头望明月,");
42 
43          bw.newLine();
44 
45         
46 
47          // 【3】flush
48 
49          bw.flush();
50 
51         
52 
53          // 【4】关闭管道
54 
55          bw.close();
56 
57          writer.close();
58 
59      }

 

 需求:以utf8编码高效写入文件

 1 /**
 2 
 3  * 以utf8写入一首诗
 4 
 5  * @author Administrator
 6 
 7  *
 8 
 9  */
10 
11 public class Test02 {
12 
13      public static void main(String[] args) throwsIOException {
14 
15         
16 
17          File file = new File("d:\\javatest\\j-utf8.txt");
18 
19         
20 
21          // 【1】创建utf8管道
22 
23          FileOutputStream out = newFileOutputStream(file);
24 
25          OutputStreamWriter writer = newOutputStreamWriter(out, "UTF-8");
26 
27          BufferedWriter bw = newBufferedWriter(writer);
28 
29         
30 
31          // 【2】写入一行
32 
33          bw.write("窗前明月光,");
34 
35          bw.newLine();
36 
37         
38 
39          bw.write("疑似地上霜。");
40 
41         
42 
43          // for win
44 
45          bw.write("\r\n");
46 
47         
48 
49          // for unix/linux/mac
50 
51          // bw.write("\n");
52 
53         
54 
55          bw.write("举头望明月,");
56 
57          bw.newLine();
58 
59         
60 
61          // 【3】flush
62 
63          bw.flush();
64 
65         
66 
67          // 【4】关闭管道
68 
69          bw.close();
70      out.close();
71          writer.close();
72 
73      }
74 
75 }

 

需求:以utf-8编码高效读取文件

 1 package bufferedreader;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.BufferedWriter;
 5 import java.io.File;
 6 import java.io.FileInputStream;
 7 import java.io.FileNotFoundException;
 8 import java.io.FileOutputStream;
 9 import java.io.IOException;
10 import java.io.InputStreamReader;
11 import java.io.OutputStreamWriter;
12 
13     //以utf-8读取一首诗
14 public class Test01 {
15     public static void main(String[]args) throws FileNotFoundException,IOException{
16         File file=new File("f:\\javatest\\f.txt");
17         
18         FileInputStream in=new FileInputStream(file);
19         InputStreamReader reader=new InputStreamReader(in,"utf-8");
20         BufferedReader br=new BufferedReader(reader);
21         
22         String line;
23         while( (line=br.readLine())!=null){
24             System.out.println(line);
25         }
26         
27         
28         in.close();
29         reader.close();
30         br.close();
31         
32         
33     }
34 }

7.  标准输入输出流

1) 标准输入流

源数据源是标准输入设备(键盘、鼠标、触摸屏)等输入设备。在java中用System.in 得到一个InputStream字节输入流。

 

需求:在控制台输入一句话,然后原样输出

 1 public static void main(String[] args) throws IOException {
 2 
 3          // 需求:输入一句话,然原样输出
 4 
 5          InputStream in = System.in;
 6 
 7         
 8 
 9          byte[] buf = newbyte[1024];
10 
11          intlen;
12 
13          // buf中包含回车和换行
14 
15          len = in.read(buf);
16 
17         
18 
19          String str = new String(buf, 0, len);
20 
21          // System.out.println(Arrays.toString(buf));
22 
23          System.out.println(str);
24 
25      }

 

 注意:

 标准输入流以字节流流入内存,如果在控制台中输入字符,字符以默认编码(win简体:gbk)编码成字节进入标准输入流。

 1 public static void main(String[] args) throws IOException {
 2 
 3          // 需求:从控制台高效读取一行数据。把一首诗写入文件。
 4 
 5         
 6 
 7          InputStream in = System.in;
 8 
 9          InputStreamReader reader = new InputStreamReader(in, "GBK");
10 
11          BufferedReader br = new BufferedReader(reader);
12 
13         
14 
15          File file = new File("d:\\javatest\\k.txt");
16 
17          FileWriter writer = new FileWriter(file);
18 
19          BufferedWriter bw = new BufferedWriter(writer);
20 
21         
22 
23          String end = "bye";
24 
25          while(true) {
26 
27               String line = br.readLine();
28 
29               if(line.equals(end)) {
30 
31                    break;
32 
33               }
34 
35              
36 
37               bw.write(line);
38 
39               // bw.newLine();
40 
41          }
42 
43         
44 
45          bw.flush();
46 
47         
48 
49          bw.close();
50 
51          writer.close();
52 
53         
54 
55      }

2)   标准输出流(PrintStream)

数据目的地是标准输出设备(显示器)等输出设备。在java中用System.out得到一个PrintStream 字节输出流(字节打印流)。提供了更强大的

print

println

打印方法用于打印各种数据类型。

 

需求:读取文件,显示到标准输出设备

 1 public static void main(String[] args) throws IOException {
 2 
 3         
 4 
 5          Filefile = new File("d:\\javatest\\k.txt");
 6 
 7         
 8 
 9          FileReader reader = new FileReader(file);
10 
11          BufferedReader br = new BufferedReader(reader);
12 
13         
14 
15          PrintStreamps = System.out;
16 
17         
18 
19          String line;
20 
21          while( (line=br.readLine())!=null ) {
22 
23               ps.println(line);
24 
25          }
26 
27      }

 

PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。

 1 public static void main(String[] args) throws IOException {
 2 
 3         
 4 
 5         
 6 
 7          String str = "hello中国";
 8 
 9          byte[] buf = str.getBytes("utf-8");
10 
11         
12 
13          PrintStream ps = System.out;
14 
15          ps.write(buf);
16 
17         
18 
19      }

 

8.  字符打印流PrintWriter

PrintWriter继承Writer

数据目的地是标准输出设备(显示器)等输出设备。在java中用System.out得到一个PrintSWriter 字符输出流(字符打印流)。提供了更强大的

print

println

writer(String str)

打印方法用于打印各种数据类型。

9. Scanner

通过scanner扫描文件、字节流等

 1 public static void main(String[] args) throws IOException {
 2 
 3         
 4 
 5          // 扫描平台默认编码的文件
 6 
 7          /*File file = new File("d:\\javatest\\j.txt");
 8 
 9          Scanner sc = new Scanner(file);
10 
11          */
12 
13         
14 
15          // 扫描指定编码的文件
16 
17          Scanner sc = new Scanner(new FileInputStream(new File("d:\\javatest\\j-utf8.txt")), "UTF-8");
18 
19         
20 
21          String line;
22 
23          while (sc.hasNextLine()) {
24 
25               line = sc.nextLine();
26 
27               System.out.println(line);
28 
29          }
30 
31         
32 
33      }

 

 10. 序列化

把内存中的对象永久保存到硬盘的过程称为对象序列化,也叫做持久化。

把硬盘持久化的内存恢复的内存的过程称为对象反序列化。

 

1)    Serializable

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化,并抛出异常

Exception in thread "main" java.io.NotSerializableException: cn.sxt05.serializable.Student

     at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)

     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)

     at cn.sxt05.serializable.Test01.main(Test01.java:22)

 Serializable接口没有方法或字段,仅用于标识可序列化的语义

public class Student implements Serializable{

// 。。。

 

2)  序列化对象

ObjectOutputStream继承于OutputStream,专门用于把对象序列化到本地。提供了

writeXXX

writeObject() 用于写入一个对象

 1 public static void main(String[] args) throws IOException {
 2 
 3        
 4 
 5         Studentstu = new Student("001", "大狗", 20, Gender.男);
 6 
 7        
 8 
 9         /**
10 
11          *  方案1:取stu所有的属性,通过特定的字符串(-),把各个属性值连接起来
12 
13          *  001-大狗-20-男
14 
15          */
16 
17        
18 
19         File file = new File("d:\\javatest\\l.txt");
20 
21         FileOutputStream out = new FileOutputStream(file);
22 
23         ObjectOutputStream oos = new ObjectOutputStream(out);
24 
25        
26 
27         oos.writeObject(stu);
28 
29        
30 
31         oos.close();
32 
33         out.close();
34 
35     }

3)    反序列化对象

ObjectInputStream继承于InputStream ,专门用于把本地持久化内容反序列化到内存,提供了

readXXX

readObject() 用于读取一个序列化内容并返回一个对象。

 

 1 public static void main(String[] args) throws IOException, ClassNotFoundException {
 2 
 3         
 4 
 5          File file = new File("d:\\javatest\\l.txt");
 6 
 7         
 8 
 9         
10 
11          FileInputStream in = new FileInputStream(file);
12 
13          ObjectInputStreamois = newObjectInputStream(in);
14 
15         
16 
17          Student student = (Student) ois.readObject();
18 
19          System.out.println(student.getId());
20 
21          System.out.println(student.getName());
22 
23          System.out.println(student.getAge());
24 
25          System.out.println(student.getGender());
26 
27         
28 
29          ois.close();
30 
31          in.close();
32 
33      }

 

4) 序列化版本

当序列化完成后,后期升级程序中的类(Student),此时再反序列化时会出现异常。

Exception in thread "main" java.io.InvalidClassException: cn.sxt05.serializable.Student; local class incompatible: stream classdesc serialVersionUID = -6288733824962181189, local class serialVersionUID = 1690603786167234505

     at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)

     at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1876)

     at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1745)

     at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033)

     at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567)

     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427)

     at cn.sxt05.serializable.Test02.main(Test02.java:16)

 

异常原因:序列化流的serialVersionUID和升级后类的版本不匹配。

 

解决方案:给Student类加序列化版本号,有两种方式

 

 

 

default serial version ID 生成默认的serial version ID 一般值都是1L。

generatedserialversion ID根据当前类的属性、方法生成一个唯一ID。

 

public class Student implements Serializable {

 

     private static final long serialVersionUID = -1003763572517930507L;

 

 

5)   transient

开发过程中,如果想忽略某些字段不让其序列化时,可以使用transient修饰。

 1 public class Student implements Serializable {
 2 
 3  
 4 
 5     private static final long serialVersionUID = 7222966748321328300L;
 6 
 7  
 8 
 9     private String id;
10 
11     private transient String name;
12 
13     private transient int age;
14 
15     private Gender gender;
16 
17     private String phone;

 

 

11.  DataInputStream/DataOutputStream

DataOutputStream 继承OutputStream,专门用于把基本java数据类型写入输出流。提供了writeXXX 写入基本java数据类型。

 

DataInputStream继承于InputStream,允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。

 

DataInputStream/DataOutputStream特别适合读取/写入在网络传输过程中的数据流。

 

写入基本java数据类型

 1 public static void main(String[] args) throws IOException {
 2 
 3         
 4 
 5          File file = new File("d:\\javatest\\n.txt");
 6 
 7          FileOutputStream out= new FileOutputStream(file);
 8 
 9          DataOutputStreamdos = newDataOutputStream(out);
10 
11         
12 
13          dos.writeInt(10);
14 
15          dos.writeUTF("hello中国");
16 
17         
18 
19          dos.close();
20 
21          out.close();
22 
23         
24 
25          System.out.println("写入完成");
26 
27         
28 
29      }

 

读取基本java数据类型

 1 public static void main(String[] args) throws IOException {
 2 
 3        
 4 
 5         File file = new File("d:\\javatest\\n.txt");
 6 
 7         FileInputStream in = new FileInputStream(file);
 8 
 9         DataInputStream dis = new DataInputStream(in);
10 
11        
12 
13         inta = dis.readInt();
14 
15         String str = dis.readUTF();
16 
17        
18 
19         System.out.println(a);
20 
21         System.out.println(str);
22 
23        
24 
25     }

 

注意:

以什么顺序写入基本java数据类型,就以什么顺序读取基本java数据类型。

推荐阅读