第10章 文件与流
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 }