文件操作
一、File类
File类:主要用来创建文件或者目录,它位于java.io.File包中
主要方法:
返回类型 方法
boolean createNewFile()//用于创建一个新文件,不创建目录
boolean mkdir()//用于创建一个新目录
boolean mkdirs()//用于创建多级目录
String getName()//获取文件的文件名
String getAbsolutePath()//获取文件的绝对路径
long length()//返回文件长度,文件大小以字节单位
例子:
(1)创建单个文件夹目录(file.mkdir())
package com.file.demo; import java.io.File; public class fileTest { public static void main(String[] args) { String path="D:\\temp"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 file.mkdir(); } } }
(2)创建多个文件夹目录(file.mkdis())
package com.file.demo; import java.io.File; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 file.mkdirs(); } } }
(3)创建一个新文件
package com.file.demo; import java.io.File; import java.io.IOException; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } } }
(4)获取文件的名字、文件的绝对路径、文件长度(文件大小以字节单位)
package com.file.demo; import java.io.File; import java.io.IOException; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } String fileName = file.getName();//获取文件的名字 String absolutePath = file.getAbsolutePath();//获取文件的绝对路径 long length = file.length();//获取文件的长度,如果里面没有内容,则长度为0 System.out.println("文件的名字为:"+fileName+"\n文件的绝对路径为:"+absolutePath+"\n文件的长度为:"+length); } }
二、IO流
I:Input
O:Outpt
文件:文件夹、具体的文件夹
根据File路径来实例化具体的对象
文件可以做的事情:获取文件的名字、路径、绝对路径、创建路径、判断文件是否存在、创建文件等(更多的功能可查看File的API)
文件的缺陷:不能够读取具体文件的内容(由此引入了流的概念)
三、流的概念
1、流的分类
(1)根据文件的流向:输入流、输出流
输入流:从文件————>控制台、程序(字节处理的单位是byte)
InputStream(抽象类) FileInputStream(file(或者是字符串,字符串是路径))
InputStream is=new FileInputStream();(InputStream是抽象类不能被实例化,所以用其子类对它进行实例化)
字节流(byte):
a、一个字节一个字节的读:效率不高、读取中文时易出现乱码
b、byte[] b=new byte[(int) file.length()];(类型是long,需要的是int类型,所以要强转)
c、BufferInputStream(InputStream is)(包装InputStream效率不高的流)
字符流(char):
Reader(抽象类) FileReader BufferReader(读一行)
例子:
1、字节流(byte):xbbxb122(非中文)、图片、音频、视频
(1)将信息从文件———>控制台(InputStream),一个字节一个字节的读,效率很低
package com.file.demo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } InputStream is=null; try { is = new FileInputStream(file); int msg = is.read();//一个字节一个字节的读取,效率非常低 while(msg!=-1){//判断是否读取到最后面 System.out.print((char)msg);//会输出ascll码表对应的数字,所以要进行转型为字符类型 msg = is.read(); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ if(is!=null){ try { is.close();//关闭流 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
(2)将信息从文件———>控制台(InputStream),一个字节一个字节存入到字节数组里并将其转换成字符串类型输出,这种方法效率比上面的高,但还是很低。
package com.file.demo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } InputStream is=null; try { is = new FileInputStream(file); //字符数组的长度是文件内容的长度,因为byte里面的类型是int,而file.length()类型是long,所以要转换成int类型 byte[] b=new byte[(int) file.length()]; is.read(b); String msg=new String(b);//将字节数组转换成字符串 System.out.println(msg); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ if(is!=null){ try { is.close();//关闭流 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
(3)将信息从文件———>控制台(InputStream),一个字节一个字节存入到字节数组里,并将其放到 BufferedInputStream,它是一个带有缓冲区的输入流,它可以提高我们的读取效率,效率最高
package com.file.demo; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } InputStream is=null; BufferedInputStream bis=null; try { is = new FileInputStream(file); //字符数组的长度是文件内容的长度,因为byte里面的类型是int,而file.length()类型是long,所以要转换成int类型 byte[] b=new byte[(int) file.length()]; //BufferedInputStream缓冲区输入流 bis=new BufferedInputStream(is); bis.read(b); String msg=new String(b); System.out.println(msg); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{ try { if(is!=null){ is.close(); } if(bis!=null){ bis.close(); } } catch (Exception e2) { } } } }
2、字符流(char):纯文字 将信息从文件———>控制台(Reader)
package com.file.demo; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.util.Scanner; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } Reader read=null; BufferedReader br=null; try { read=new FileReader(file); br=new BufferedReader(read); //方法一: char[] c=new char[(int) file.length()]; br.read(c); System.out.println(c); //方法二: // String readLine = br.readLine();//读取一整行的内容 // while(readLine!=null){//判断是否还有信息存在 // System.out.println(readLine); // readLine = br.readLine(); // } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{//关闭流 try { if(br!=null){ br.close(); } if(read!=null){ read.close(); } } catch (Exception e2) { } } } }
输出流:从控制台————>文件
字节流(byte):
OutputStream(抽象类) FileOutputStream BufferOutputStream
例如:String str="中国万岁!" 将String转换为byte:str.getBytes()
byte[] b 将byte转换为String:String str=new String(b)
字符流(char):
Writer(抽象类) FileWriter BufferWriter(String str)
例子:
字节流:
(1)将信息从控制台———>文件(OutputStream),进化跟上面的InputStream一致,所以写一个最高效率的
package com.file.demo; 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; import java.io.InputStream; import java.io.OutputStream; import java.util.Scanner; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } Scanner input=new Scanner(System.in); System.out.print("请输入您要写的内容:"); String str=input.next(); OutputStream os=null; BufferedOutputStream bos=null; try { //true是在原本的内容的基础上进行追加,如果没有加true写入txt的内容会覆盖原本的内容 os=new FileOutputStream(file,true); //将字符转换成字符数组 byte[] b=str.getBytes(); bos=new BufferedOutputStream(os); bos.write(b); // 刷新此缓冲的输出流,这个最好写上,如果写的内容多了,它可能没有写进去 bos.flush(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{//关闭流 try { if(bos!=null){ bos.close(); } if(os!=null){ os.close(); } } catch (Exception e2) { } } } }
字符流(char):纯文字 将信息从控制台———>文件(Writer)
package com.file.demo; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.util.Scanner; public class fileTest { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); if(!file.exists()){//判断文件是否存在,不存在则创建文件 try { file.createNewFile();//前提条件是存在D:\\temp路径才能创建,否则会提示系统找不到指定路径错误 } catch (IOException e) { e.printStackTrace(); } } Scanner input=new Scanner(System.in); System.out.print("请输入您要写的内容:"); String str=input.next(); Writer writer=null; BufferedWriter bw=null; try { //true是在原本的内容的基础上进行追加,如果没有加true写入txt的内容会覆盖原本的内容 writer=new FileWriter(file,true); bw=new BufferedWriter(writer); //换行的方法 bw.newLine(); bw.write(str); bw.flush(); } catch (IOException e) { e.printStackTrace(); } finally{//关闭流 try { if(bw!=null){ bw.close(); } if(writer!=null){ writer.close(); } } catch (Exception e2) { } } } }
(2)根据处理的字节数
字节流:xbbxb122(非中文)、图片、音频、视频(byte)
字符流:纯文字(char)
需要将字节流——>字符流:(可设置字符编码,就是设置它的编码个格式)
输入:InputStreamReader
输出:OutputStream
例子:将字节流转换成字符流
package com.file.demo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; public class fileTest { public static void main(String[] args) { System.out.println("请输入:"); InputStream in=System.in; InputStreamReader isr=null; try { //"GBK"设置字符编码的格式 isr=new InputStreamReader(in,"GBK"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } BufferedReader br=new BufferedReader(isr); try { String str=br.readLine(); System.out.println(str); } catch (IOException e) { e.printStackTrace(); } finally{ try { if(br!=null){ br.close(); } if(isr!=null){ isr.close(); } if(in!=null){ in.close(); } } catch (Exception e2) { } } } }
(3)应用
思路:分析题目(输入还是输出、是否是纯文本)
a、输入还是输出
b、是否是纯文本
c、是否高效:默认条件是,结合buffer去用
(4)序列化和反序列化
序列化:将对象进行流化写入某个文件中去:ObjectOutputStream(new FileOutputStream())//需要一个流的参数
反序列化:将已经被流化在某个文件中的对象进行恢复(恢复成对象)
输入:ObjectInputStream(new FileInputStream)
序列化步骤:
a、对象必须实现Serializable
注意:序列化接口没有方法或字段,仅用于标识可序列化的语义
建议写一个默认的序列号(因为序列化和反序列化都是根据这个ID进行对接)
b、ObjectOutputStream(new FileOutputStream())
c、oos.writerObject(obj)
d、关闭相关的流
例子:序列化和反序列化
序列化和反序列化公用的Student类
package com.SerializeandDeserialize; import java.io.Serializable; public class Student implements Serializable{//序列化和反序列化必须要实现这个接口 private static final long serialVersionUID = 1L; private String id; private String name; private String phone; public Student() { super(); } public Student(String id, String name, String phone) { super(); this.id = id; this.name = name; this.phone = phone; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", phone=" + phone + "]"; } }
(1)序列化:将对象进行流化写入某个文件中去:ObjectOutputStream(new FileOutputStream())
package com.SerializeandDeserialize; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; public class SerializeDemo { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); Student stu=new Student(); List<Student> list=new ArrayList<Student>(); list.add(new Student("1", "小明", "13265498270")); list.add(new Student("2", "小灰", "15365894237")); list.add(new Student("3","小花","13960279134")); OutputStream os=null; ObjectOutputStream oos=null; //写相应的流进行存储 try { //重点是进行序列化的流是:ObjectOutputStream+FileOutputStream os=new FileOutputStream(file,true); oos = new ObjectOutputStream(os); oos.writeObject(list); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally{//关闭流 try { if(oos!=null){ oos.close(); } if(os!=null){ os.close(); } } catch (Exception e2) { } } } }
(2)反序列化:将已经被流化在某个文件中的对象进行恢复(恢复成对象)
package com.SerializeandDeserialize; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.util.List; public class DeserializeDemo { public static void main(String[] args) { String path="D:\\temp\\text.txt"; File file=new File(path); InputStream is=null; ObjectInputStream ois=null; try { is=new FileInputStream(file); //真正进行反序列化的类是:ObjectInputStream ois=new ObjectInputStream(is); Object obj = ois.readObject(); if(obj!=null){ List<Student> list=(List<Student>) obj; for (Student s : list) { //该输出的是Student的toString方法,如果Student没有toString方法,则会默认调用父类的toString方法 System.out.println(s); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally{//关闭流 try { if(ois!=null){ ois.close(); } if(is!=null){ is.close(); } } catch (Exception e2) { } } } }
四、反射机制的使用
(1)Class:类
(2)Field:属性
(3)Method:方法
(4)Constractor:构造方法
类的组成:属性、构造方法、方法、块、静态块、内部类
Class类方法
1、getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
2、Object obj=cls.newInstance();//相当于Object obj=new User();前提要有构造方法才可以使用
3、Constructor cons=cls.getConstructor(new Class[]{Integer.class,String.class});//构造方法的声明
Object obj=cons.newInstance(new Object[]{1,"xgr"});//相当于Object obj=new User(1,"xgr");
五、xml文件解析以及xml文件的读取、写入
1、xml的特点:
第一:文档的申明<?xml version="1.0" encoding="utf-8">
第二:根节点一个
第三:标签成对出现:正确的嵌套
一个标准的xml文件:
<?xml version="1.0" encoding="UTF-8"?> <school> <class id="1"></class> <name>初三三班</name> <teacher>朱老师</teacher> </school>
2、dtd验证文件:(主要是为了约束xml)
两种形式:内嵌形式:
<!DOCTYPE 根节点[
..........................
]>
内嵌套形式例子:school.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE school[ <!ELEMENT school (class+)> <!ELEMENT class (name?,teacher+)> <!ATTLIST class id CDATA #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT teacher (#PCDATA)> ]> <school> <class id="1"> <name>初三二班</name> <teacher>小猪</teacher> </class> <class id="2"> <name>高一五班</name> <teacher>小凡</teacher> </class> </school>
外联形式:(单独的的dtd文件)
<!DOCTYPE 根节点 SYSTEM "xxxx.dtd">
外联形式例子:school.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE school SYSTEM "school.dtd"> <school> <class id="1"> <name>初三二班</name> <teacher>小猪</teacher> </class> <class id="2"> <name>高一五班</name> <teacher>小凡</teacher> </class> </school>
school.dtd
<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT school (class+)> <!ELEMENT class (name?,teacher+)> <!ATTLIST class id CDATA #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT teacher (#PCDATA)>
符号的使用:
?————表示相同变量名有0-1个
+————表示相同变量名可以有1-N个
*————表示相同变量名可以有0-N个
不写符号————表示变量名只有唯一一个
3、Dom解析(xml解析)
思路:a、创建一个解析器工厂
b、生成一个解析器
c、解析文件
d、进行相应功能的操作
(以下步骤是需要进行保存更新修改使用的)
f、 创建一个转换工厂
g、生成一个转换器
h、转换文件
I、写测试类,测试所写的方法功能是否可行(必须写)
例子:
目录截图:
(1)创建school.xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE school SYSTEM "school.dtd"> <school> <class id="1"> <name>初三二班</name> <teacher>小明</teacher> </class> </school>
(2)创建shcool.dtd文件
<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT school (class+)> <!ELEMENT class (name,teacher)> <!ATTLIST class id CDATA #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT school (#PCDATA)>
(3)创建实体类entity
package com.dom.demo.entity; public class Classes { private String id;//班级编号id private String className;//班级姓名 private String teacher;//班级教师的名字 //无参构造方法 public Classes() { super(); } //有参构造方法 public Classes(String id, String className, String teacher) { super(); this.id = id; this.className = className; this.teacher = teacher; } @Override public String toString() { return "Classes [id=" + id + ", className=" + className + ", teacher=" + teacher + "]"; } }
(4)创建SchoolDao接口
package com.dom.demo.dao; import java.util.List; import com.dom.demo.entity.Classes; public interface SchoolDao { //增加一条数据:添加有两种情况,成功:true,失败:false //添加一条数据就是添加一个Classes对象 public boolean add(Classes cls); //删除一条数据:根据id来删除,成功:true,失败:false public boolean delete(int id); //修改一条数据:根据id来修改,成功:true,失败:false public boolean update(int id,Classes cls); //查询所有的数据 public List<Classes> findAll(); //根据id(属性)去查询特定的数据 public Classes findById(int id); }
(5)创建SchoolDaoImpl类来实现这个接口
package com.dom.demo.Impl; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.dom.demo.dao.SchoolDao; import com.dom.demo.entity.Classes; public class SchoolDaoImpl implements SchoolDao{ String path="src/com/dom/demo/database/school.xml"; //添加信息到xml文件中 @Override public boolean add(Classes cls) { //获取一个Document Document doc=getDocument(); //获取根节点 Element root = doc.getDocumentElement(); //创建指定类型的元素,创建class节点 Element eClass = doc.createElement("class"); //将int的类型转换成String类型,因为第二个参数的类型必须是String eClass.setAttribute("id", String.valueOf(cls.getId())); Element name=doc.createElement("name"); //设计name属性里面的内容 name.setTextContent(cls.getClassName()); //将该节点加到eClass的节点上,成为eClass的子节点 //这里的name发生了自动转型,appendChild里面的参数是Node类型的,但name是Element类型的 //所以进行了向上转型,向上转型是可以自动转型的 eClass.appendChild(name); Element teacher=doc.createElement("teacher"); teacher.setTextContent(cls.getTeacher()); //将teacher节点添加到eClass节点上 eClass.appendChild(teacher); //将eClass节点添加到根节点上 root.appendChild(eClass); if(save(doc)){ return true; } return false; } //通过id来删除id这个节点里面的内容 @Override public boolean delete(int id) { //获取一个Document Document doc = getDocument(); //获取根节点 Element root = doc.getDocumentElement(); //获取根节点的子节点 NodeList rootChild = root.getChildNodes(); //遍历孩子节点 for (int i = 0; i < rootChild.getLength(); i++) { //获取孩子节点里面的内容,去到class Node son = rootChild.item(i); //排除"#text"的情况 if(!son.getNodeName().equals("#text")){ //获取class里面的id,只能通过Element里面的方法来获取 Element eson=(Element)son; String sid = eson.getAttribute("id"); //判断当前的id是否跟输入的id一致 if(sid.equals(String.valueOf(id))){ //删除对应的class的方法是:先找到自己的父节点,然后用父节点把自己给删除 son.getParentNode().removeChild(son); //由于以上的操作只保存到缓存中,所以我们应该让它保存到xml文件中 if(save(doc)){ return true; } } } } return false; } //通过id来查找到相应的用户,并将对应的信息进行更新 @Override public boolean update(int id, Classes cls) { //获取一个Document Document doc = getDocument(); //获取根节点 Element root = doc.getDocumentElement(); //获取根节点的孩子节点 NodeList rootChild = root.getChildNodes(); //遍历孩子节点 for (int i = 0; i < rootChild.getLength(); i++) { //获取孩子节点里面的内容,到class Node son = rootChild.item(i); if(!son.getNodeName().equals("#text")){ //获取class里面的id进行比较,所以要用Element里面的方法 Element eson=(Element)son; String sid = eson.getAttribute("id"); //判断当前的id是否与输入的id一致 if(sid.equals(String.valueOf(id))){ NodeList sonson = son.getChildNodes(); //遍历孙子节点 for (int j = 0; j < sonson.getLength(); j++) { //获取孙在节点里面的内容,去到name和teacher处 Node sun = sonson.item(j); if(sun.getNodeName().equals("name")){ sun.setTextContent(cls.getClassName()); } if(sun.getNodeName().equals("teacher")){ sun.setTextContent(cls.getTeacher()); } } //由于以上的操作只保存到缓存中,所以我们应该让它保存到xml文件中 if(save(doc)){ return true; } } } } return false; } //查询所有的xml文件里面的所有信息 @Override public List<Classes> findAll() { //创建List对象,由于List是一个接口,不能进行实例化,所以用它的子类进行实例化 List<Classes> list=new ArrayList<Classes>(); Document doc = getDocument(); //获取根节点 Element root = doc.getDocumentElement(); //获取根节点的子节点 NodeList rootChild = root.getChildNodes(); //遍历根节点的子节点 for (int i = 0; i < rootChild.getLength(); i++) { //获取根节点的子节点的内容 //现在去到了class节点,class节点里面有id属性,所以要获取它的id Node son = rootChild.item(i); //由于输出会存在#text的现象,所以要进行判断 if(!son.getNodeName().equals("#text")){ //由于获取属性的方法只存在于Element中,且现在的节点内容是属于Node //根据查看Element可以发现,public interface Element extends Node //所以需要将Node转换成Element 向下转型 强转 Element eson=(Element) son; //根据属性的名字获取属性的内容 String sid = eson.getAttribute("id"); Classes cls=new Classes(); //由于cls里面的属性id是整型,而sid是字符串类型,所以要进行类型的强转 cls.setId(Integer.parseInt(sid)); //获取孩子节点的下一个节点,即孙子节点 NodeList sonson = son.getChildNodes(); //遍历孙子节点 for (int j = 0; j < sonson.getLength(); j++) { //获取孙节点属性的内容,现在去到name和teacher的那一层里 Node sun = sonson.item(j); //判断是name还是teacher,并根据具体的属性来获取相应的内容 if(sun.getNodeName().equals("name")){ cls.setClassName(sun.getTextContent()); } if(sun.getNodeName().equals("teacher")){ cls.setTeacher(sun.getTextContent()); } } list.add(cls); } } return list; } //通过id来获取相应id里面的内容 @Override public Classes findById(int id) { //没有进行实例化主要是为了防止占据不必要的空间,如果真正地使用,我们才会进行实例化 Classes cls=null; //获取一个Document Document doc = getDocument(); //获取根节点 Element root = doc.getDocumentElement(); //获取根节点的孩子节点 NodeList rootChild = root.getChildNodes(); //遍历孩子节点 for (int i = 0; i < rootChild.getLength(); i++) { //获取根节点里面的内容,去到class处 Node son = rootChild.item(i); //判断除去"#text"这些节点 if(!son.getNodeName().equals("#text")){ //运用Element来获取class里面的id Element eson=(Element)son; String sid = eson.getAttribute("id"); //判断当前的id是否与输入的id一致,若一致则将信息放到Classes中 if(sid.equals(String.valueOf(id))){ cls=new Classes(); cls.setId(Integer.parseInt(sid)); //寻找孩子节点的下一个节点,即孙子节点 NodeList sonson = son.getChildNodes(); //遍历孙子节点 for (int j = 0; j < sonson.getLength(); j++) { //获取孙在里面的内容,去到了name和teacher处 Node sun = sonson.item(j); //判断是否是name和teacher,因为会存在#text,所以要进行判断 if(sun.getNodeName().equals("name")){ cls.setClassName(sun.getTextContent()); } if(sun.getNodeName().equals("teacher")){ cls.setTeacher(sun.getTextContent()); } } return cls; } } } return cls; } //创建解析器工厂——>生成解析器——>解析文件 public Document getDocument(){ //第一步:创建一个解析器工厂 DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); //第二步:生成解析器 DocumentBuilder db; Document doc = null; try { db=dbf.newDocumentBuilder(); //第三步:解析文件 File file=new File(path); doc = db.parse(file); } catch (Exception e) { e.printStackTrace(); } return doc; } //主要是进行修改,添加以及删除等功能,对数据进行了操作的话,操作完的数据状态暂时保存在缓存中,如果想同步更改xml文件里面的内容,必须用到这一步 public boolean save(Document doc){ //创建一个转换器工厂 TransformerFactory tff=TransformerFactory.newInstance(); //生产一个转换器 try { Transformer tf=tff.newTransformer(); //doc源 DOMSource dom=new DOMSource(doc); //写入具体的文件的流 StreamResult sr=new StreamResult(path); //实现转换,将DOMSource的dom对象转换为StreamResult的sr对象,dom是要转换的 XML输入,sr转换dom的 Result。 tf.transform(dom, sr); return true; } catch (Exception e) { e.printStackTrace(); } return false; } }
(6)为了测试我们的方法是否可行,我们还要写测试类SchoolDaoImplTest
package com.dom.demo.test; import java.util.List; import org.junit.Test; import com.dom.demo.Impl.SchoolDaoImpl; import com.dom.demo.entity.Classes; public class SchoolDaoImplTest { SchoolDaoImpl dao=new SchoolDaoImpl(); @Test public void testAdd() { Classes cls=new Classes(); cls.setId(5); cls.setClassName("高三二班"); cls.setTeacher("小东"); dao.add(cls); } @Test public void testDelete() { dao.delete(1); } @Test public void testUpdate() { Classes cls=new Classes(); cls.setClassName("高一二班"); cls.setTeacher("小明"); dao.update(1, cls); } @Test public void testFindAll() { List<Classes> list = dao.findAll(); for (Classes c : list) { System.out.println(c); } } @Test public void testFindById() { Classes cls = dao.findById(1); System.out.println(cls); } }
4、Dom4j解析(xml解析)
思路: