1 /*****************
2 ***第10章 文件与流
3 *******知识点:
4 **************1.文件类
5 ******************1.1 文件的基本操作
6 ******************1.2 文件遍历
7 ******************1.3 文件过滤器
8 **************2.IO流
9 ******************2.1 输入流
10 **************************2.1.1 字节流
11 **************************2.1.2 字符流
12 ******************2.2 输出流
13 **************************2.2.1 字节流
14 **************************2.2.2 字符流
15 ******************2.3 缓冲流
16 **************************2.3.1 输入缓冲流
17 **************************2.3.2 输出缓冲流
18 ******************2.4 序列化
19 ******************2.5 随机访问
20 **************3.编码集
21
22
23 */
24 import java.io.*;
25 /*
26 *自定义文件过滤器
27 * 1.实现FilenameFilter接口
28 * 2.重写accept方法
29 */
30 class DirFilter implements FilenameFilter {
31 private String type;
32
33 public DirFilter(String type){
34 this.type = type;
35 }
36
37 public boolean accept(File dir,String name){
38 return name.endsWith(type) || new File(name).isDirectory();
39 }
40 }
41
42 class Person implements Serializable{
43 private String id,name;
44 Person(){
45 this.id = "0000";
46 this.name = "无名氏";
47 }
48 Person(String id, String name){
49 this.id = id;
50 this.name = name;
51 }
52
53 public String toString(){
54 return "{编码:" + id +",姓名:" + name +"}\r\n";
55 }
56 }
57
58 public class test10{
59 public static final String filePath = "F:\\ciade\\学习\\学习笔记\\Java\\第10章(文件和流)";
60
61 public static void main(String[] args){
62 showDemo("1.文件类");//演示1.文件类
63 demoFile();
64
65 showDemo("2.IO流");//演示2.IO流
66 demoIO();
67
68 showDemo("3.编码集");//演示3.编码集
69 demoCodeSet();
70 }
71
72 /*
73 *1.文件类
74 */
75 public static void demoFile(){
76
77 /**1.1 文件的基本操作**/
78 System.out.println("返回系统默认分隔符:" + File.pathSeparator);//返回系统默认分隔符
79 System.out.println("返回系统默认路径分隔符:" + File.separator);//返回系统默认路径分隔符
80 File f_File = new File(filePath + "\\test10_1.class");
81 System.out.println("是否存在文件:" + f_File.exists());//判断文件是否存在
82 System.out.println("是否为文件:" + f_File.isFile());//判断是否是文件
83 System.out.println("是否为目录:" + f_File.isDirectory());//判断是否是文件夹
84 System.out.println("返回文件绝对路径:" + f_File.getPath());//返回文件绝对路径
85 System.out.println("返回父级目录绝对路径:" + f_File.getParent());//返回父级目录绝对路径
86 System.out.println("返回文件长度大小:" + f_File.length());//单位:字节
87
88 //文件增加和删除
89 File f_New = new File(filePath + "\\test.txt");
90 if(!f_New.exists()){//判断是否存在
91 try{
92 System.out.println("创建文件:" + f_New.createNewFile());//创建新的文件
93
94 }catch(Exception e){
95 System.out.println("创建文件失败,失败原因" + e);
96
97 }
98 }else{
99 try{
100 System.out.println("删除文件成功:" + f_New.delete());//删除文件
101 }catch(Exception e){
102 System.out.println("删除文件失败,失败原因" + e);
103 }
104 }
105
106 /**1.2 文件遍历**/
107 try{
108 //初始化创建文件和文件夹
109 File f_file,f_fold;
110 for(int i = 0; i<10;i++){
111 f_file = new File(filePath + "\\" + i + ".txt");
112 f_fold = new File(filePath + "\\" + i + "_");
113 f_file.createNewFile();//创建文件
114 f_fold.mkdir();//创建目录
115 }
116 System.out.println("初始化文件成功!");
117
118 File file = new File(filePath);
119 File[] file_list = file.listFiles();//得到所有文件对象和文件夹对象
120
121 //遍历文件列表
122 for(File f:file_list){
123 if(f.isFile() && f.getName().endsWith(".txt")){
124 System.out.println("找到文件:" + f.getName());
125 f.delete();
126 System.out.println("文件"+ f.getName() + "删除成功");
127
128 }else if(f.isDirectory()){
129 System.out.println("找到文件夹:" + f.getName());
130 f.delete();
131 System.out.println("文件夹"+ f.getName() + "删除成功");
132 }else{
133 System.out.println("找到文件:" + f.getName());
134 }
135 }
136
137 /**1.3 文件过滤器**/
138 String[] str_file = file.list(new DirFilter(".java"));//得到所有.java文件名
139 for(String str:str_file){
140 System.out.println("找到.java文件:" + str);
141 }
142 }catch(IOException e){
143 System.out.println("操作失败,失败原因" + e);
144 }
145 }
146
147 /*
148 *2.IO流
149 */
150 public static void demoIO(){
151 //流————一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。本质就是数据传输
152 //IO流————输入输出流
153 //分类————————1.根据数据类型不同分为:字符流和字节流 2.根据数据流方向不同分为:输入流和输出流
154 //字节流:以字节(8bit)为传输单位的流
155 //字符流:以字符为传输单位的流
156 //两者区别:
157 // 1.读写单位不同
158 // 2.处理对象不同(字节流能处理所有类型的数据 如图片等 而字符流只能处理字符类的数据)
159 // 3.字节流本身不会使用到缓冲区,字符流会通过缓冲区操作文件
160 //结论:推荐使用字节流,原因是硬盘上的所有文件都是以字节的形式进行传输和存储的。而字符只是在内存才会形成
161
162 /**2.1 输入流**/
163 //2.1.1 字节流
164 //InputStream 是所有输入字节流的父类,它是一个抽象类
165 //其中有ByteArrayInputStream/StringBufferInputStream/FileInputStream/ObjectInputStream/FilterInputStream/DataInputStream等子类
166 //ByteArrayInputStream:从Byte数组中读取数据 //意义不大。读取数组直接数组遍历即可 无需使用IO流
167
168 /*byte[] byte_b = new byte[1024];
169 byte[] byte_b1 = new byte[1024];
170 int count = 0;
171 for(int i = 0;i<1024;i++){
172 byte_b[i] = (byte)(i % 10);
173 }
174 System.out.println(new String(byte_b));
175
176 ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byte_b);
177 while (byteInputStream.read() != -1){
178 byte_b1[count++] = (byte)byteInputStream.read();
179
180 }
181 byteInputStream.close();//关闭
182 byteInputStream = null //释放资源
183 System.out.println(new String(byte_b1));
184 */
185
186 //StringBufferInputStream:从StringBuffer中读取数据 已过时
187 //FileInputStream:从文件读取数据
188 /*
189 File file = new File(filePath + "\\test.ini");
190 InputStream in = new FileInputStream(file);
191 byte[] byte_b = new byte[1024];
192 int count = 0;
193 int temp = 0;
194 while((temp=in.read()) != -1){//注意:当读到文件末尾的时候会返回-1.正常情况下是不会返回-1的。
195 byte_b[count++] = (byte)temp;
196 }
197 in.close();//关闭连接
198 in = null ;
199 String str = new String(byte_b);
200 System.out.println("读取数据有:" + str);
201 */
202
203 //ObjectInputStream/FilterInputStream/DataInputStream和其子类都是装饰流
204 //装饰流:不直接链接数据流,而是以其他流对象为基础建立的流类,该类流实现了将实体流中的数据进行转换,增强流对象的读写能力
205 /*
206 DataInputStream dataInput = new DataInputStream(in);
207 byte[] byte_b = new byte[(int)file.length()];
208 dataInput.read(byte_b);
209 dataInput.close();
210 dataInput = null;
211 System.out.println(new String(byte_b));
212 */
213 //使用同FileInputStream一致。相关方法查看API
214
215 //PipedInputStream:是从与其它线程共用的管道中读取数据
216
217 //所以字节流推荐使用FileInputStream 可配合 FilterInputStream 装饰流一同使用
218
219
220 //2.1.2 字符流
221 //Reader 是所有的输入字符流的父类,它是一个抽象类。
222 //其中有CharReader/StringReader/FileReader/FilterReader 等子类
223 //CharReader:读取Char数组
224 //StringReader:读取String
225 //FileReader:读取文件
226 //BufferedReader /FilterReader为装饰流
227 //InputStreamReader 是链接字节流和字符流的桥梁它将字节流转变成字符流
228 /*
229 FilterReader reader = new FilterReader(new FileReader(file));
230 String str_temp = null;
231 while((str_temp = reader.readLine()) != null){
232 System.out.println("行内容:" + str_temp);
233 }
234 reader.close();
235 reader = null;
236 */
237 //所以推荐使用FileReader(继承了InputStreamReader) 配合FilterReader一同使用
238
239 /**2.2 输出流**/
240 //2.2.1 字节流
241 //OutputStream 是所有输出字节流的父类,它是一个抽象类
242 //其中有ByteArrayOutputStream/FileOutputStream/ObjectOutputStream/FilterOutputStream等子类
243
244 //ByteArrayOutputStream:写入Byte数组数据 //意义不大。直接循环初始化数组值即可 无需使用IO流
245
246 //FileOutputStream:写入文件数据
247 /*
248 File file = new File(filePath + "\\testOutFile.ini");
249 Person p1 = new Person();
250 Person p2 = new Person("0001","李四");
251 Person p3 = new Person("0002","王五");
252 Person p4 = new Person("0003","ciade");
253 Person[] p_Array = new Person[4];
254 p_Array[0] = p1;
255 p_Array[1] = p2;
256 p_Array[2] = p3;
257 p_Array[3] = p4;
258
259 OutputStream out = new FileOutputStream(file,true);//参数1为文件名,参数2为true是追加模式 为false是重写模式
260 byte[] byte_b ;
261 for(Person p:p_Array){
262 byte_b = p.toString().getBytes();
263 for(int i=0; i < byte_b.length;i++){
264 if(byte_b[i] >= 97 && byte_b[i] <= 122)
265 byte_b[i] = (byte)(byte_b[i] - 32); //如果是小写字母转换成大写字母
266 }
267 out.write(byte_b);
268 }
269 out.close();
270 out = null;
271
272 BufferedReader reader = new BufferedReader(new FileReader(file));
273 String str = null;
274 while((str = reader.readLine())!=null){
275 System.out.println("行内容:" + str);
276 }
277 reader.close();
278 reader = null;
279 */
280 //ObjectOutputStream/FilterOutputStream 装饰流
281 /*
282 FilterOutputStream ft = new FilterOutputStream(new FileOutputStream(file,true));
283 byte[] byte_b ;
284 for(Person p:p_Array){
285 byte_b = p.toString().getBytes();
286 for(int i=0; i < byte_b.length;i++){
287 if(byte_b[i] >= 97 && byte_b[i] <= 122)
288 byte_b[i] = (byte)(byte_b[i] - 32); //如果是小写字母转换成大写字母
289 }
290 ft.write(byte_b);
291 }
292 ft.flush();//刷新此输出流,并强制将所有缓冲数据写入该流中
293 ft.close();
294 ft = null;
295 */
296
297 //读写文件 字节流方式
298 /*FileInputStream in = new FileInputStream(file);
299 FilterOutputStream out = new FilterOutputStream(new FileOutputStream(new File(filePath + "\\test1.jpg")));
300 int temp;
301 int count = 0;
302 byte[] out_file = new byte[(int)file.length()];
303 while((temp=in.read())!=-1){
304 out_file[count++] = (byte)temp;
305 }
306 in.close();
307 in = null;
308
309 out.write(out_file);
310 out.flush();
311 out.close();
312 out = null;*/
313
314 //PipedOutputStream:是向与其它线程共用的管道中写入数据
315 //推荐使用FileOutputStream 可配合FilterOutputStream 装饰流一同使用
316
317 //2.2.2 字符流
318 //Writer 是所有的输出字符流的父类,它是一个抽象类。
319 //其中有CharArrayWriter/StringWriter/FileWriter/BufferedWriter/FilterWriter 等子类
320 //CharArrayWriter:写入Char数组
321 //StringWriter:写入String
322 //FileWriter:写入文件
323 //BufferedWriter /FilterWriter为装饰流
324 //OutputStreamWriter 是链接字节流和字符流的桥梁它将字节流转变成字符流
325 //推荐FileWriter 配合FilterWriter 一同使用
326
327 /**2.3 缓冲流**/
328 //缓冲处理流包括:BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter
329 //BufferedInputStream,BufferedOutputStream 针对的是字节
330 //BufferedReader,BufferedWriter 针对的是字符
331 //更多使用方法可查看API
332
333
334 /**2.4 序列化**/
335 //序列化是一种将对象以一连串的字节描述的过程
336 //反序列化是将这些字节重建成一个对象的过程
337 //实现方式:需要序列化的类实现Serializable接口就可以了,用于标记这个类可以序列化
338 //对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的值。
339 //注意:
340 // 1.当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口
341 // 2.当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化
342 // 3.static,transient后的变量不能被序列化
343
344 //演示序列化
345 //步骤:需要序列化的类实现Serializable接口 使用ObjectOutputStream对象写入文件
346 /*ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
347 Person p1 = new Person();
348 Person p2 = new Person("0001","李四");
349 Person p3 = new Person("0002","王五");
350 Person p4 = new Person("0003","ciade");
351
352 List<Person> list = new ArrayList<Person>();
353 list.add(p1);
354 list.add(p2);
355 list.add(p3);
356 list.add(p4);
357 oos.writeObject(list);
358
359 oos.flush();
360 oos.close();
361 */
362
363 //演示反序列化
364 /*
365 ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
366 List<Person> list = (ArrayList<Person>)oin.readObject();
367 oin.close();
368 for(Object o : list){
369 System.out.println(o);
370
371 }
372 System.out.println("序列化类的类名是:" + list.get(0).getClass());//获取序列化类的类名
373
374 */
375
376 /**2.5 随机访问**/
377 //RandomAccessFile类:用于随机访问文件的类
378 //特点:1.支持随机访问任意位置进行读写 2.支持指定位置进行读写
379 //应用场景:断点续传,多线程下载
380 //写入文件
381 /*
382 File file = new File(filePath + "\\testOutRandomFile.ini");
383 RandomAccessFile rm = new RandomAccessFile(file,"rwd");
384
385 Person p1 = new Person();
386 Person p2 = new Person("0001","lisi");
387 Person p3 = new Person("0002","wang");
388 Person p4 = new Person("0003","ciade");
389 Person[] p_Array = new Person[4];
390 p_Array[0] = p1;
391 p_Array[1] = p2;
392 p_Array[2] = p3;
393 p_Array[3] = p4;
394 long pos = 1024;
395 rm.seek(pos);//设置写入位置 参数为long型
396 for(Person p: p_Array){
397 rm.writeUTF(p.toString());//使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。
398 }
399 rm.close();
400 */
401
402 //读取文件
403 /*
404 File file = new File(filePath + "\\testOutRandomFile.ini");
405 RandomAccessFile rm = new RandomAccessFile(file,"r");//只读模式
406 String str = null;
407 long pos = 1024;//设置读取位置 参数为long型
408 rm.seek(pos);
409 while((str = rm.readLine())!= null){
410 System.out.println("行内容:" + str);
411 }
412 */
413
414 /**总结常有IO类图**/
415 //1.字节流
416 // 1.1输入————InputStream->FileInputStream->FilterInputStream
417 // 1.2输出————OutputStream->FileOutputStream->FilterOutputStream
418 //2.字符流
419 // 2.1输入————Reader->FileReader->FilterReader
420 // 2.2输出————Writer->FileWriter->FilterWriter
421 //3.缓存流
422 // 3.1 字节型—————BufferedInputStream、BufferedOutputStream
423 // 3.2 字符型—————BufferedReader、BufferedWriter
424 //4.桥接流
425 // 4.1输入————InputStreamReader(实现子类有 FileReader)
426 // 4.2输出————OutputStreamWriter(实现子类有 FileWriter)
427 //5.序列化类
428 // 5.1输入————ObjectInputStream
429 // 5.2输出————ObjectOutputStream
430 //6.RandomAccessFile————随机文件类
431 }
432
433 /*
434 *3.编码集
435 */
436 public static void demoCodeSet() {
437 //FileWriter和FileReader使用系统当前默认的编码方式
438 //如果需要创建或者读取一个编码格式为utf-8的文件通过FileWriter和FileReader这两个类是不能实现的
439 //但可以通过桥接类OutputStreamWriter和InputStreamReader来指定格式
440 //获取系统文件编码集
441 System.out.println("系统文件编码集为:" + System.getProperty("file.encoding"));
442 //获取虚拟机编码集
443 System.out.println("虚拟机编码集为:" + java.nio.charset.Charset.defaultCharset().toString());//注意此包为第三方包
444
445 try{
446 FileWriter fw = new FileWriter(new File(filePath + "\\testOutCodeSetFile.ini"));//与系统当前默认的编码方式相同
447 FileReader fr = new FileReader(new File(filePath + "\\testOutCodeSetFile.ini"));//与系统当前默认的编码方式相同
448 //获取FileWriter编码集
449 System.out.println("FileWriter编码集为:" + fw.getEncoding());//
450
451 //获取FileReader编码集
452 System.out.println("FileReader编码集为:" + fr.getEncoding());
453 }catch(Exception e){
454 System.out.println("操作失败!");
455 }
456
457 try{
458 File file = new File(filePath + "\\testOutCodeSetFile.ini");
459 OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file),"utf-8");//以utf-8格式写入数据到文件中
460
461 Person p1 = new Person();
462 Person p2 = new Person("0001","lisi");
463 Person p3 = new Person("0002","wang");
464 Person p4 = new Person("0003","ciade");
465
466 out.write(p1.toString());
467 System.out.println("成功写入Person1数据:" + p1);
468 out.write(p2.toString());
469 System.out.println("成功写入Person2数据:" + p2);
470 out.write(p3.toString());
471 System.out.println("成功写入Person3数据:" + p3);
472 out.write(p4.toString());
473 System.out.println("成功写入Person4数据:" + p4);
474 out.flush();
475 out.close();
476
477 InputStreamReader in = new InputStreamReader(
478 new FileInputStream(file),"utf-8"
479 );//以utf-8格式读取文件数据 注意如果格式不对会产生乱码现象
480 StringBuffer sb = new StringBuffer();
481 while(in.ready()){
482 sb.append((char) in.read());
483 }
484 in.close();
485 System.out.println("读取内容是:" + sb.toString());
486 }catch(Exception e){
487 System.out.println("操作异常!");
488 }
489
490 }
491 /*
492 * 抽取打印演示函数 用于打印演示功能提示
493 */
494 public static void showDemo(String demoStr){
495 System.out.println("演示:" + demoStr);
496 }
497 }