JAVA之旅(三十)——打印流PrintWriter,合并流,切割文件并且合并,对象的序列化Serializable,管道流,RandomAccessFile,IO其他类,字符编码
一.打印流PrintWriter
打印流有PrintWriter和PrintStream,他的特点可以直接操作输入流还有文件
-
该流提供了打印方法,可以将各种数据类型原样打印
-
file对象 File
- 字符串路径 String
- 字节打印流
- 字符打印流
我们演示一遍大家就对此有所了解了
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 1package com.lgl.hellojava;
2
3import java.io.BufferedReader;
4import java.io.IOException;
5import java.io.InputStreamReader;
6import java.io.PrintWriter;
7
8public class HelloJJAVA {
9 public static void main(String[] args) {
10
11 try {
12 BufferedReader bufr = new BufferedReader(new InputStreamReader(
13 System.in));
14
15 PrintWriter oWriter = new PrintWriter(System.out, true);
16 String line = null;
17 while ((line = bufr.readLine()) != null) {
18 if (line.equals("over")) {
19 break;
20 }
21 oWriter.write(line);
22 }
23 oWriter.close();
24 bufr.close();
25 } catch (IOException e) {
26 // TODO Auto-generated catch block
27 e.printStackTrace();
28 }
29 }
30}
31
32
要想存到文件里,也是可以直接把文件给放进去的
二.合并流
我们来看看什么是合并流,在API文档上说,他可以串联流
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 1package com.lgl.hellojava;
2
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.SequenceInputStream;
8import java.util.Enumeration;
9import java.util.Vector;
10
11public class HelloJJAVA {
12 public static void main(String[] args) {
13 try {
14 Vector<FileInputStream> v = new Vector<FileInputStream>();
15 v.add(new FileInputStream("1.txt"));
16 v.add(new FileInputStream("2.txt"));
17 Enumeration<FileInputStream> elements = v.elements();
18 SequenceInputStream sis = new SequenceInputStream(elements);
19
20 FileOutputStream fos = new FileOutputStream("3.txt");
21
22 byte[] buf = new byte[1024];
23 int len = 0;
24 while ((len = sis.read(buf)) != -1) {
25 fos.write(buf, 0, len);
26 }
27
28 fos.close();
29 sis.close();
30
31 } catch (FileNotFoundException e) {
32 // TODO Auto-generated catch block
33 e.printStackTrace();
34 } catch (IOException e) {
35 // TODO Auto-generated catch block
36 e.printStackTrace();
37 }
38 }
39}
40
41
把1.txt和2.txt乃至add更多的内容合并到3.txt文件中,这就是流的合并
三.切割文件
合并文件可以,那肯定可以切割了,我们来看下具体是怎么去制作的
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 1// 切割文件
2 public static void splitFile() {
3 try {
4 FileInputStream fis = new FileInputStream("1.jpg");
5 FileOutputStream fos = null;
6 byte[] buf = new byte[1024 * 1024];
7
8 int len = 0;
9 int count = 1;
10 while ((len = fis.read(buf)) != -1) {
11 fos = new FileOutputStream((count++) + ".patch");
12 fos.write(buf, 0, len);
13 fos.close();
14 }
15
16 fis.close();
17 } catch (FileNotFoundException e) {
18 // TODO Auto-generated catch block
19 e.printStackTrace();
20 } catch (IOException e) {
21 // TODO Auto-generated catch block
22 e.printStackTrace();
23 }
24 }
25
当运行结束之后,我们可以看到
已经成功切割了
切割完我们可以合并了
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
48
49
50
51
52 1// 合并文件
2 public static void merge() {
3 ArrayList<FileInputStream> al = new ArrayList<>();
4 for (int i = 1; i <= 2; i++) {
5 try {
6 al.add(new FileInputStream(i + ".patch"));
7 } catch (FileNotFoundException e) {
8 // TODO Auto-generated catch block
9 e.printStackTrace();
10 }
11 }
12 Iterator<FileInputStream> iterator = al.iterator();
13 Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {
14
15 @Override
16 public boolean hasMoreElements() {
17 // TODO Auto-generated method stub
18 return iterator.hasNext();
19 }
20
21 @Override
22 public FileInputStream nextElement() {
23 // TODO Auto-generated method stub
24 return iterator.next();
25 }
26
27 };
28 try {
29 SequenceInputStream seq = new SequenceInputStream(en);
30 FileOutputStream fos = new FileOutputStream("2.jpg");
31
32 byte[] buf = new byte[1024];
33
34 int len = 0;
35
36 while ((len = seq.read(buf)) != -1) {
37 fos.write(buf, 0, len);
38 }
39
40 fos.close();
41 seq.close();
42
43 } catch (FileNotFoundException e) {
44 // TODO Auto-generated catch block
45 e.printStackTrace();
46 } catch (IOException e) {
47 // TODO Auto-generated catch block
48 e.printStackTrace();
49 }
50 }
51
52
这样我们就把图片拷贝出来了,可以看到
这段代码是非常帮的,我们一定会用到的,希望能用的上
四.对象的序列化Serializable
其实就是可以直接操作对象的流,他会实现一个Serializable()接口,我们用代码来看下他是怎么用的,我们直接写读取对象的类了
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
48
49
50
51
52
53
54
55
56
57
58 1package com.lgl.hellojava;
2
3import java.io.FileInputStream;
4import java.io.FileOutputStream;
5import java.io.IOException;
6import java.io.ObjectInputStream;
7import java.io.ObjectOutputStream;
8import java.io.Serializable;
9
10public class HelloJJAVA {
11 public static void main(String[] args) {
12 // writeObj();
13 readObj();
14 }
15
16 private static void readObj() {
17 try {
18 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
19 "obj.txt"));
20 Person p = (Person) ois.readObject();
21 System.out.println(p);
22 ois.close();
23 } catch (IOException e) {
24 // TODO Auto-generated catch block
25 e.printStackTrace();
26 } catch (ClassNotFoundException e) {
27 // TODO Auto-generated catch block
28 e.printStackTrace();
29 }
30
31 }
32
33 private static void writeObj() {
34 try {
35 ObjectOutputStream oos = new ObjectOutputStream(
36 new FileOutputStream("obj.txt"));
37 oos.writeObject(new Person("zhangsan", 20));
38 oos.close();
39 } catch (IOException e) {
40 // TODO Auto-generated catch block
41 e.printStackTrace();
42 }
43
44 }
45}
46
47class Person implements Serializable {
48
49 String name;
50 int age;
51
52 public Person(String name, int age) {
53 this.name = name;
54 this.age = age;
55 }
56
57}
58
OK,自己去验证一下
五.管道流
输入输出可以直接进行连接,通常结合线程使用
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 1package com.lgl.hellojava;
2
3import java.io.IOException;
4import java.io.PipedInputStream;
5import java.io.PipedOutputStream;
6
7public class HelloJJAVA {
8 public static void main(String[] args) {
9
10 PipedInputStream pi = new PipedInputStream();
11 PipedOutputStream po = new PipedOutputStream();
12
13 try {
14 pi.connect(po);
15 } catch (IOException e) {
16 // TODO Auto-generated catch block
17 e.printStackTrace();
18 }
19
20 Read read = new Read(pi);
21 Write write = new Write(po);
22
23 new Thread(read).start();
24 new Thread(write).start();
25 }
26}
27
28class Read implements Runnable {
29
30 private PipedInputStream in;
31
32 public Read(PipedInputStream in) {
33 this.in = in;
34 }
35
36 @Override
37 public void run() {
38 try {
39 byte[] buf = new byte[1024];
40 int len = in.read(buf);
41 String s = new String(buf, 0, len);
42 System.out.println(s);
43 in.close();
44 } catch (IOException e) {
45 // TODO Auto-generated catch block
46 e.printStackTrace();
47 }
48
49 }
50
51}
52
53class Write implements Runnable {
54
55 private PipedOutputStream out;
56
57 public Write(PipedOutputStream out) {
58 this.out = out;
59 }
60
61 @Override
62 public void run() {
63 try {
64 out.write("yes".getBytes());
65 out.close();
66 } catch (IOException e) {
67 // TODO Auto-generated catch block
68 e.printStackTrace();
69 }
70 }
71
72}
73
现在就可以联通了
六.RandomAccessFile
这是一个很特别的家伙,他继承的是Object
- 该类不是IO体系中的子类
- 但是他是IO包中的成员,他同时具备读写功能
- 内部封装了一个数组,而且通过指针对数组中的元素进行操作
- 可以通过getFilePointer或者指针位置同时可以通过seek改变指针的位置
其实完成读写的原理就是内部封装了字节输入,输出流,通过构造函数可以看出该类具备操作文件的能力,而且操作文件还有模式
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 1package com.lgl.hellojava;
2
3import java.io.FileNotFoundException;
4import java.io.IOException;
5import java.io.RandomAccessFile;
6
7public class HelloJJAVA {
8 public static void main(String[] args) {
9 writeFile();
10 }
11
12 public static void writeFile() {
13 try {
14 RandomAccessFile raf = new RandomAccessFile("1.txt", "rw");
15 raf.write("zhangssan".getBytes());
16 raf.writeInt(99);
17
18 raf.close();
19 } catch (FileNotFoundException e) {
20 // TODO Auto-generated catch block
21 e.printStackTrace();
22 } catch (IOException e) {
23 // TODO Auto-generated catch block
24 e.printStackTrace();
25 }
26 }
27}
28
29
这只是一个写的过程,我们的特性还没有体现出来,我们来看下他是怎么读的
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 1private static void ReadFile() {
2 try {
3 RandomAccessFile raf = new RandomAccessFile("1.txt", "r");
4
5 // 调整对象指针
6 raf.seek(8 * 0);
7
8 byte[] buf = new byte[1024];
9
10 raf.read(buf);
11
12 String s = new String(buf);
13
14 System.out.println(s);
15
16 raf.close();
17 } catch (FileNotFoundException e) {
18 // TODO Auto-generated catch block
19 e.printStackTrace();
20 } catch (IOException e) {
21 // TODO Auto-generated catch block
22 e.printStackTrace();
23 }
24
25 }
26
27
如果操作的文件不存在,就会自动创建,如果存在,直接覆盖
七.IO其他类
IO其他包里,还有一些其他的使用
- 操作基本数据类型
- 字节数组
- 字符数组
1.基本数据类型
我们先来看下基本数据类型的,我直接读写都写出来
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 1
2 public static void readData() {
3 try {
4 DataInputStream dis = new DataInputStream(new FileInputStream(
5 "data.txt"));
6 int num = dis.readInt();
7 boolean d = dis.readBoolean();
8
9 System.out.println(num + "" + d + "");
10
11 dis.close();
12
13 } catch (FileNotFoundException e) {
14 // TODO Auto-generated catch block
15 e.printStackTrace();
16 } catch (IOException e) {
17 // TODO Auto-generated catch block
18 e.printStackTrace();
19 }
20
21 }
22
23 // 基本数据类型
24 public static void writeDatea() {
25 try {
26 DataOutputStream dos = new DataOutputStream(new FileOutputStream(
27 "data.txt"));
28
29 dos.writeInt(55);
30 dos.writeBoolean(true);
31
32 dos.close();
33
34 } catch (FileNotFoundException e) {
35 // TODO Auto-generated catch block
36 e.printStackTrace();
37 } catch (IOException e) {
38 // TODO Auto-generated catch block
39 e.printStackTrace();
40 }
41
42 }
43
读取基本数据类型
二.字节数组
这个偶尔用下,但是我们还是要去学习一下的
- ByteArrayInputStream: 在构造的时候,需要接收数据源,而且数据源是一个字节数组
- ByteArrayOutputStream:在构造的时候,不用定义数据的目的,因为该对象中已经内部封装了可变程度的字节数组
因为这两个流的对象都操作的数组,并且没有使用系统资源,所以,不用进行close关闭!
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 1package com.lgl.hellojava;
2
3import java.io.ByteArrayInputStream;
4import java.io.ByteArrayOutputStream;
5
6public class HelloJJAVA {
7 public static void main(String[] args) {
8
9 // 数据源
10 ByteArrayInputStream bis = new ByteArrayInputStream("123".getBytes());
11 // 数据目的
12 ByteArrayOutputStream bos = new ByteArrayOutputStream();
13
14 int ch = 0;
15
16 while ((ch = bis.read()) != -1) {
17 bos.write(ch);
18 }
19
20 System.out.println(bos.size());
21 System.out.println(bos.toString());
22
23 }
24}
25
26
是不是比较简单,字符流我就不说了,和字节流是类似的,但是他会衍生出一个新的内容就是字符编码
八.字符编码
这些乱七八糟的编码说真的,东西还是挺多的,但是我并不想讲那么多,因为本身我也不是很清楚,其次这玩意大致的知道一点就可以了(个人觉得),什么ASCLL,GBK,UTF-8之类的
1
2
3
4 1 String s = "hello java";
2 byte [] b1 = s.getBytes();
3 System.out.println(Arrays.toString(b1));
4
他得到的是什么?
现在我换一个编码
1
2 1byte [] b1 = s.getBytes("GBK");
2
我设置成GBK,他的值是一样的,说明默认的是GBK
九.练习
写完这个练习,我们的I/O流就GG了,感慨颇多,写I/O写了很多篇,但是仍然晕乎乎的,应该继续加深印象的,我们来看下需求
- 有五个学生,每个学生有三门课程,从键盘输入以下数据(包括姓名,三门课成绩),输入的格式,如zhangsan,30,60,96计算出总成绩,并把学生的信息和计算出的总分数高低顺序存入文件student.txt中去;
好了,开始撸代码了
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 1package com.lgl.hellojava;
2
3import java.io.BufferedReader;
4import java.io.BufferedWriter;
5import java.io.FileWriter;
6import java.io.IOException;
7import java.io.InputStreamReader;
8import java.util.Set;
9import java.util.TreeSet;
10
11public class HelloJJAVA {
12 public static void main(String[] args) {
13
14 /**
15 * 逻辑:
16 * 1.通过获取键盘录入一行数据,然后取出数据封装成学生对象
17 * 2.需要从高到低排列,需要排序,使用集合TreeSet就可以了
18 * 3.写入文件
19 */
20
21 try {
22 Set<Student> stus = StudentInfoTool.getStudents();
23 StudentInfoTool.writeFile(stus);
24
25 } catch (IOException e) {
26 // TODO Auto-generated catch block
27 e.printStackTrace();
28 }
29
30 }
31}
32
33// 比较数据,Comparable接口
34class Student implements Comparable<Student> {
35
36 // 姓名
37 private String name;
38 // 三科分数
39 private int n1, n2, n3;
40 // 总分
41 private int sum;
42
43 // 构造函数
44 public Student(String name, int n1, int n2, int n3) {
45 this.name = name;
46 this.n1 = n1;
47 this.n2 = n2;
48 this.n3 = n3;
49 sum = n1 + n2 + n3;
50 }
51
52 public String getName() {
53 return name;
54 }
55
56 public void setName(String name) {
57 this.name = name;
58 }
59
60 public int getSum() {
61 return sum;
62 }
63
64 public void setSum(int sum) {
65 this.sum = sum;
66 }
67
68 @Override
69 public int compareTo(Student o) {
70 int num = new Integer(this.sum).compareTo(new Integer(o.sum));
71 if (num == 0) {
72 return this.name.compareTo(o.name);
73 }
74 return num;
75 }
76
77 @Override
78 public int hashCode() {
79 // TODO Auto-generated method stub
80 return name.hashCode() + sum * 78;
81 }
82
83 @Override
84 public boolean equals(Object obj) {
85 if (!(obj instanceof Student)) {
86 throw new ClassCastException("Type Error");
87 }
88 Student s = (Student) obj;
89 return this.name.equals(s.name) && this.sum == s.sum;
90 }
91
92}
93
94// 工具类
95class StudentInfoTool {
96 public static Set<Student> getStudents() throws IOException {
97 BufferedReader bufr = new BufferedReader(new InputStreamReader(
98 System.in));
99 String line = null;
100 // 集合
101 Set<Student> stus = new TreeSet<>();
102
103 while ((line = bufr.readLine()) != null) {
104 if (line.equals("over")) {
105 break;
106 }
107 String[] info = line.split(",");
108 Student student = new Student(info[0], Integer.parseInt(info[1]),
109 Integer.parseInt(info[2]), Integer.parseInt(info[3]));
110 stus.add(student);
111 }
112 bufr.close();
113 return stus;
114 }
115
116 // 写入文件
117 public static void writeFile(Set<Student> stus) {
118 try {
119 BufferedWriter bufw = new BufferedWriter(new FileWriter(
120 "student.txt"));
121 for (Student stu : stus) {
122 bufw.write(stu.getName());
123 bufw.write(stu.getSum() + "");
124 bufw.newLine();
125 bufw.flush();
126 }
127
128 bufw.close();
129 } catch (IOException e) {
130 // TODO Auto-generated catch block
131 e.printStackTrace();
132 }
133
134 }
135}
136
137
输出的结果,可以看到
总数,从小到大,如果你想从高到低的话,自己去实现下排序,看看你们学的怎么样了
好的,我们本篇到这里就结束了,这篇也是憋了挺久的才别出来的,终于把IO写完了