本节内容
1.Java中的文件操作类File类
2. Java中的IO流
字节流
字符流
Java中的缓冲流
字节流与字符流的区别
Java中的转换流
对象的序列化
一、File类
File类是文件和目录路径名的抽象表示形式。也是Java中用来操作磁盘文件的一个类。
创建File对象:
File(String directoryPath)
File(String directoryPath, String filename)
File(File dirObj, String filename)
这里,directoryPath是文件的路径名,filename 是文件名,dirObj 一个指定目录的File 对象
File file1 = new File(“d:/”); File file2 = new File(“d:\” , “test”); File file3 = new File(file1 , “test.txt”);
File的操作:
package com.xk; import java.io.File; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class FileDemo { public static void main(String[] args) { // separatorChar在window下是\ 在UNIX下是/ File file = new File("D:"+File.separatorChar); //exists() file表示的文件或目录是否存在。 System.out.println(file.exists()); //创建文件夹 file.mkdir(); //创建文件夹时父目录必须存在,否则不能创建 file.mkdirs();//创建文件夹时父目录可以不存在,父目录不存在会自动创建 //创建文件 try { file.createNewFile();//创建一个文件 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //判断file是一个文件还是文件夹 file.isDirectory();//判断是不是文件夹 file.isFile();//判读是不是文件 System.out.println(file.getName());//表示的文件或目录的名称。 System.out.println(file.getPath());//路径名转换为一个路径名字符串 System.out.println(file.length());//获取文件的大小 System.out.println(file.renameTo(new File("文件路径")));//对文件重命名 File[] files=file.listFiles();//获取一个路径下所有的文件以及文件夹 System.out.println(file.delete());//删除文件或者文件夹 //如果是文件直接删除 //如果是文件夹,则必须先删除文件夹下的所有文件,才能删除文件夹,否则文件夹不能删除。 } }
递归思想
对刚开始接触计算机编程的人而言,这里有递归的一个简单定义:当函数直接或者间接调用自己时,则发生了递归。
递归是一种常见的解决问题的方法,寄把问题逐渐简单化。递归的基本思想就是
“自己调用自己”,一个使用递归技术的方法会直接或间接的调用自己
递归构造包括两个部分:
定义递归头。什么时候不调用自身方法,如果没有头,将陷入死循环
递归体。什么时候需要调用自身方法
其实递归算法很简单,简单点就是自己调用自己的方法,有条件判断什么时候停止!
列出:一个目录下所有的文件以及文件夹 文件显示文件大小
package com.xk; import java.io.File; /* *作者:吴志龙 *日期:2018年8月3日 */ public class FilesDemo { public static void main(String[] args) { //在这里我显示出D盘下的所有文件以及文件夹 showFile("E:"+File.separatorChar); } public static void showFile(String path){ //使用路径创建一个file对象 File file = new File(path); //判断路径是否真实存在 if(file.exists()){ //获取目录下的所有的文件以及文件夹 File[] files = file.listFiles(); if(files==null){ //如果有隐藏文件夹时会出现的空指针异常 return ; } for(File file1:files){ //判断是文件还文件夹 if(file1.isFile()){ //是文件显示文件名以及文件大小 System.out.println("文件名:"+file1.getName()+"/t文件大小:"+file1.length()); }else if(file1.isDirectory()){ //如果是文件夹 显示文件夹名后继续取出文件夹下的文件以及文件夹 System.out.println("文件夹名: "+file1.getName()); //使用递归来取出文件夹下的文件以及文件夹 showFile(file1.getPath()); } } }else{ System.out.println("路径不存在"); } } }
二、IO流
Java中的IO流:指的是在Java程序中可以对文件进行的读写操作。
流:流是一种数据传输的通道。通过这个通道可以进行数据的传输
输入流:把一个文件的内容传输到程序中来
输出流:把程序中的内容输出到一个文件中去。
Java中的关于流的操作都在Java.io包下:
Java中IO流的API结构图:
字节流: 可以用来处理字节数据,也可以处理字符,一般都是二进制数据,图片 、音频文件等。。。。主要用来处理字节数据
字符流: 是专门用来处理字符数据,处理文本,速度快,只能处理字符
所有的流:都有2个一个输入流、一个输出流
而且有所的流的处理流程是一样的。流的操作:读、写
所有的流的操作流程:
1.打开数据源
2.根据数据源建立相对应的输入输出流
3.根据流来进行读写操作
4.操作完成后关闭输入输出流
字节流的操作:以FileInputStream与FileOutputStream为例
package com.xk; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class FileInputStreamDemo { //字节输入流 public static void main(String[] args) { //step: 打开数据源 File file = new File("E:"+File.separatorChar+"新建文本文档.txt"); FileInputStream in=null; try { //step:根据数据源建立流 in = new FileInputStream(file); //step: 流的操作:读 //字节流的读取方法: //read() 一次读取一个字节 //read(byte[] b) 一次读取 b.length个字节的数据到一个byte数组 //read(byte[] b, int off, int len) 一次读取最多 len个字节的数据到一个byte数组中 //如果文件过大我们需要循环去读 byte[] b = new byte[1024]; int len=0; while ((len=in.read(b))!=-1) { String str = new String(b,0,len); System.out.println(str); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //step:关闭流 try { in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package com.xk; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class FileOutputStreamDemo { //字节输出流 public static void main(String[] args) { //STEP:打开数据源 File file =new File("E:"+File.separatorChar+"说明书.txt"); //STEP:创建对应的流: FileOutputStream out=null; try { out = new FileOutputStream(file); //STEP:流的操作 写 //write(int b) 将指定的字节写入到文件 //write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中 //write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流 String str ="这是字节输出流的操作"; out.write(str.getBytes()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 try { out.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
字节输入流与字节输出流一起使用:
进行图片的复制: 进行边读边写
package com.xk; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class CopyImg { public static void main(String[] args) { //STEP:打开数据源 //原图 File file =new File("E:"+File.separatorChar+"流.png"); //复制 File file1 = new File("E:"+File.separatorChar+"副本-"+file.getName()); //STEP:创建流 FileInputStream in=null; FileOutputStream out =null; try { in = new FileInputStream(file); out = new FileOutputStream(file1); //STEP:流的操作:读 写 边读边写 byte[] b= new byte[1024]; int len=0; //循环读写 while ((len=in.read(b))!=-1) { out.write(b, 0, len); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 先要关输出流,在关闭输入流 try { out.close(); in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
高效的读写操作:缓冲流。
我们普通的流直接操作的是磁盘,高效流操作的是内存。
缓冲流不能单独使用,他必须依赖于普通的流来使用
进行高效的图片复制
package com.xk; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class CopyImg { public static void main(String[] args) { //STEP:打开数据源 //原图 File file =new File("E:"+File.separatorChar+"流.png"); //复制 File file1 = new File("E:"+File.separatorChar+"副本-"+file.getName()); //STEP:创建流 FileInputStream in=null; FileOutputStream out =null; //缓冲流 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { in = new FileInputStream(file); bis = new BufferedInputStream(in); out = new FileOutputStream(file1); bos = new BufferedOutputStream(out); //STEP:流的操作:读 写 边读边写 //使用缓冲流进行读写操作 byte[] b= new byte[1024]; int len=0; //循环读写 while ((len=bis.read(b))!=-1) { bos.write(b, 0, len); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 有缓冲流先关闭缓冲流后关闭普通流 先要关输出流,在关闭输入流 try { bos.close(); bis.close(); out.close(); in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
字符流的操作:同样以FileReader与FileWriter为例
package com.xk; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class ReaderDemo { public static void main(String[] args) { //字符输入流 //STEP:打开数据源 File file = new File("E:"+File.separatorChar+"新建文本文档.txt"); //STEP:创建流 FileReader fileReader=null; try { fileReader = new FileReader(file); //STEP:流的操作 char[] c = new char[1024]; int len=0; //循环读取 while ((len=fileReader.read(c))!=-1) { String str = new String(c,0,len); System.out.println(str); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 try { fileReader.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package com.xk; import java.io.File; import java.io.FileWriter; import java.io.IOException; /* *作者:吴志龙 *日期:2018年8月3日 */ public class WriterDemo { public static void main(String[] args) { //字符输出流 //STEP:打开数据源 File file = new File("E:"+File.separatorChar+"新建文本文档.txt"); //STEP:创建流 FileWriter fileWriter =null; try { fileWriter = new FileWriter(file); //STEP:流的操作 String str ="这是字符的输出操作"; //write(char[] cbuf, int off, int len) 写入字符数组的某一部分。 //write(int c) 写入单个字符。 //write(String str, int off, int len) 写入字符串的某一部分。 fileWriter.write(str); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 try { fileWriter.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
字符的高效流与字节高效流用法相同。
转换流:
字节转字符:
package com.xk; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; /* *作者:吴志龙 *日期:2018年8月3日 */ public class ByteToChar { public static void main(String[] args) { //STEP:打开数据源 File file = new File("E:"+File.separatorChar+"新建文本文档.txt"); //SETP:创建流 FileInputStream in = null; //转换流 InputStreamReader isr = null; try { in = new FileInputStream(file); isr = new InputStreamReader(in); //STEP:流的操作 :使用字符读出 char[] c = new char[1024]; int len=0; while ((len=isr.read(c))!=-1) { String str = new String(c,0,len); System.out.println(str); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 try { isr.close(); in.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
字符转字节:
package com.xk; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; /* *作者:吴志龙 *日期:2018年8月3日 */ public class CharToByte { public static void main(String[] args) { //STEP:打开数据源 File file = new File("E:"+File.separatorChar+"新建文本文档.txt"); //SETP:创建流 FileOutputStream os = null; //转换流 OutputStreamWriter osw = null; try { os = new FileOutputStream(file); osw = new OutputStreamWriter(os); String str ="这是字符转字节"; osw.write(str); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //STEP:关闭流 try { osw.close(); os.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
序列化:
可能在程序中我们经常有这样的情况:将一个对象传递到另一台设备,这就需要有一种可以在2端传输的协议,Java的序列化机制就是为了解决这个问题。
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。
对象序列化:Serialization,是一种将对象以一连串的字节描述的过程,即把对象写入到流中;
对象反序列化:deserialization,是一种将这些字节重建成一个对象的过程,即从流中恢复对象。
注意:对象所在的类必须实现java.io.Serializable接口,才能被序列化。此接口没有方法或字段,是一个声明性接口,表示实现此接口的类可以被序列化
序列化特点:
当不希望类中的某个字段被序列化时,应用transient表示这个字段,如:private transient int age;
如果某个类能够被序列化,其子类也可以被序列化。
如果该类有父类,则分两种情况来考虑,如果该父类已经实现了可序列接口。则其父类的相应字段及属性的处理和该类相同;如果该类的父类没有实现可序列化接口,则该类的父类所有的字段属性将不会序列化。
对于父类的处理,如果父类没有实现串行化接口,则其必须有默认的构造函数(即没有参数的构造函数)。否则编译的时候就会报错。在反串行化的时候,默认构造函数会被调用