Java学习笔记(六)



第十一章 算法

一、排序算法

1.1 冒泡排序

1、定义:每次从数组中找出最大值放在数组的后面去
2、实现冒泡排序的关键步骤
(1)确定总共需要做几轮: 数组的长度-1.
(2)每轮比较几次
(3)当前位置大于后一个位置则交换数据
3、示例

 public static void main(String[] args) {
 	int[] arr = {5, 2, 3, 1};
    for (int i = 0; i < arr.length - 1; i++) {
    	// 定义一个循环控制每轮比较几次。
        for (int j = 0; j < arr.length - i - 1; j++) {
        // 判断当前位置的元素值,是否大于后一个位置处的元素值
        	if(arr[j] > arr[j+1]){
            	int temp = arr[j + 1];
                arr[j + 1] = arr[j];
                arr[j] = temp;
            }
        }
    }
    //返回数组的字符串表现形式
    System.out.println(Arrays.toString(arr));
}

1.2 选择排序

1、定义:每轮选择当前位置,与后面的值比较,若后面的值小于该值,交换位置。
2、示例

public static void main(String[] args) {
	int[] arr = {5, 1, 3, 2};
	//控制选择几轮
    for (int i = 0; i < arr.length - 1; i++) {
    	//控制每轮选择几次。
        for (int j = i + 1; j < arr.length; j++) {
        // 判断当前位置是否大于后面位置处的元素值,若大于则交换。
        	if(arr[i] > arr[j]){
            	int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
    System.out.println(Arrays.toString(arr));
}

二、查找算法

2.1 二分查找 (折半查找)

1、定义:数组中的数据必须是有序的。每次排除一半的数据,能够提高查询数据的性能。
2、关键步骤
(1)定义两个变量,分别记录开始索引(left)和结束索引(right)
(2)计算中间位置的索引,mid = (left+right)/2;
(3)每次查找中间mid位置的元素,和目标元素key进行比较。如果中间位置元素比目标元素小,left = mid+1。如果中间位置元素比目标元素大,right = mid-1。如果中间位置元素和目标元素相等,把mid返回。
3、示例

public class Test {
    public static void main(String[] args) {
        int[] arr = {7, 23, 79, 81, 103, 127, 131, 147};
        System.out.println(binarySearch(arr, 150));
        System.out.println(Arrays.binarySearch(arr, 81));
    }
    public static int binarySearch(int[] arr, int data){
        // 定义两个变量,一个站在左边位置,一个站在右边位置
        int left = 0;
        int right = arr.length - 1;
        // 定义一个循环控制折半。折半条件:left <= right
        while (left <= right){
            // 每次折半,都算出中间位置处的索引
            int middle = (left + right) / 2;
            // 判断当前要找的元素值,与中间位置处的元素值的大小情况。
            if(data < arr[middle]){
                // 往左边找,截止位置(右边位置) = 中间位置 - 1
                right = middle - 1;
            }else if(data > arr[middle]){
                // 往右边找,起始位置(左边位置) = 中间位置 + 1
                left = middle + 1;
            }else {
                // 中间位置处的元素值,正好等于我们要找的元素值
                return middle;
            }
        }
        return -1; // -1特殊结果,就代表没有找到数据
    }
}

三、正则表达式

1、定义:就是由一些特定的字符组成,代表的是一个规则。
2、作用
(1)用来校验数据格式是否合法。
(2)在一段文本中查找满足要求的内容。
3、书写规则
在这里插入图片描述
4、应用
(1)正则表达式用于校验规则

//qq校验规则:qq不可为空,不是以0开头的,满足6-20之间的长度。
public static boolean checkQQ1(String qq){
	//以数字1-9开头,//d是指后面的字符为数字0-9,还有5-19个数字
    return qq != null && qq.matches("[1-9]\\d{5,19}");
}
//电话校验规则:校验用户输入的手机或座机,
public static boolean checkPhone(){
	//手机号以1开头,第二位数字为3-9,\\d是指后面的字符为数字0-9,还有9个数字
	//座机以0开头,\\d是指后面的字符为数字0-9,还有2-7个数字,接下来是“-”字符,?表示可有可无。
	phone.matches("(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})")
}

(2)正则表达式用于查找信息

//从以下内容中爬取出,手机,邮箱,座机、400电话等信息。
public static void method1(){
	String data = " 来黑马程序员学习Java,\n" +
    	"        电话:1866668888,18699997777\n" +
        "        或者联系邮箱:boniu@itcast.cn,\n" +
        "        座机电话:01036517895,010-98951256\n" +
        "        邮箱:bozai@itcast.cn,\n" +
        "        邮箱:dlei0009@163.com,\n" +
        "        热线电话:400-618-9090 ,400-618-4000,4006184000,4006189090";
        // 1、定义爬取规则
        String regex = "(1[3-9]\\d{9})|(0\\d{2,7}-?[1-9]\\d{4,19})|(\\w{2,}@\\w{2,20}		 	 
                        (\\.\\w{2,10}){1,2})" + "|(400-?\\d{3,7}-?\\d{3,7})";
        // 2、把正则表达式封装成一个Pattern对象
        Pattern pattern = Pattern.compile(regex);
        // 3、通过pattern对象去获取查找内容的匹配器对象。
        Matcher matcher = pattern.matcher(data);
        // 4、定义一个循环开始爬取信息
        while (matcher.find()){
            String rs = matcher.group(); // 获取到了找到的内容了。
            System.out.println(rs);
        }
    }

(3)正则表达式用于搜索替换和分割内容
在这里插入图片描述

public class Test {
    public static void main(String[] args) {
        // 1、public String replaceAll(String regex , String newStr):搜索替换
        // 需求1:请把下面字符串中的不是汉字的部分替换为 “-”
        String s1 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
        System.out.println(s1.replaceAll("\\w+", "-"));
        // 需求2:“我我我喜欢编编编编编编编编编编编编程程程”,需要优化成“我喜欢编程”。
        String s2 = "我我我喜欢编编编编编编编编编编编编程程程";
        //(.)是一组.匹配任意字符,\\1是分组引用,+是重复的字
        //$1代表组内重复的字
        System.out.println(s2.replaceAll("(.)\\1+", "$1"));
        // 2、public String[] split(String regex):分割字符串,返回一个字符串数组。
        // 需求1:请把下面字符串中的人名取出来,使用切割来做
        String s3 = "古力娜扎ai8888迪丽热巴999aa5566马尔扎哈fbbfsfs42425卡尔扎巴";
        String[] names = s3.split("\\w+");
        System.out.println(Arrays.toString(names)); //[古力娜扎,迪丽热巴,马尔扎哈,卡尔扎巴]
    }
}

四、方法递归

1、定义:方法调用自身的形式称为方法递归 (recursion)。
2、形式
(1)直接递归:方法自己调用自己。
(2)间接递归:方法调用其他方法,其他方法又回调方法自己。
3、递归算法三要素:①递归的公式;②递归的终结点;③递归的方向必须走向终结点。
4、示例

第十二章 file、IO流和特殊文件

一、file

1、定义:File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件 (可以是文件、或文件夹)。
2、常用方法
(1)创建对象
在这里插入图片描述

public static void main(String[] args) {
	// 1、创建一个File对象,指代某个具体的文件ab.txt。
    // File f1 = new File("D:/resource/ab.txt");
    // File f1 = new File("D:\\resource\\ab.txt");
    // 路径分隔符resource
    File f1 = new File("D:" + File.separator +"resource" + File.separator + "ab.txt");
    System.out.println(f1.length()); // 文件大小
    //File对象既可以代表文件、也可以代表文件夹
    File f2 = new File("D:/resource");
    System.out.println(f2.length());
    // File对象还可以指代一个不存在的文件路径
    File f3 = new File("D:/resource/aaaa.txt"); //绝对路径
    System.out.println(f3.length()); //0
    System.out.println(f3.exists()); // false
    // 相对路径,默认是直接去工程file-io-app下寻找文件的。
    File f4 = new File("file-io-app\\src\\itheima.txt");
    System.out.println(f4.length());
}

(2)判断文件类型、获取文件信息功能
在这里插入图片描述
(3)创建文件、删除文件
在这里插入图片描述在这里插入图片描述

public static void main(String[] args) throws Exception {
	// public boolean createNewFile():创建一个新文件(文件内容为空),返回布尔值。
    File f1 = new File("D:/resource/itheima2.txt");
    System.out.println(f1.createNewFile());
    // public boolean mkdir():用于创建文件夹,注意:只能创建一级文件夹
    File f2 = new File("D:/resource/aaa");
    System.out.println(f2.mkdir());
    //public boolean mkdirs():用于创建文件夹,注意:可以创建多级文件夹
    File f3 = new File("D:/resource/bbb/ccc/ddd/eee/fff/ggg");
    System.out.println(f3.mkdirs());
	// public boolean delete():删除文件,或者空文件,注意:不能删除非空文件夹。
    System.out.println(f1.delete());
}

(4)遍历文件夹
在这里插入图片描述
使用listFiles方法时的注意事项
① 当主调是文件,或者路径不存在时,返回null
② 当主调是空文件夹时,返回一个长度为0的数组
③ 当主调是一个有内容的文件夹时,将所有一级文件和文件夹的路径放在File数组中返回。
④ 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件当主调是一个文件夹,但是没有权限访问该文件夹时,返回null。

public static void main(String[] args) {
	// public String[] list():获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。
    File f1 = new File("D:\\course\\待研发内容");
    String[] names = f1.list();
    for (String name : names) {
    	System.out.println(name);
    }
    // public File[] listFiles():获取当前目录下所有"一级文件对象"到一个文件对象数组中去返回
    File[] files = f1.listFiles();
    for (File file : files) {
    	System.out.println(file.getAbsolutePath());
    }
}

3、示例-在D:\\判断下搜索QQ.exe这个文件,然后直接输出。

public class RecursionTest3 {
    public static void main(String[] args) throws Exception {
          searchFile(new File("D:/") , "QQ.exe");
    }
    //dir:目录   fileName:要搜索的文件名称
    public static void searchFile(File dir, String fileName) throws Exception {
        // 1、把非法的情况都拦截住
        if(dir == null || !dir.exists() || dir.isFile()){
            return; // 代表无法搜索
        }
        // 2、dir不是null,存在,一定是目录对象。
        // 获取当前目录下的全部一级文件对象。
        File[] files = dir.listFiles();
        // 3、判断当前目录下是否存在一级文件对象,以及是否可以拿到一级文件对象。
        if(files != null && files.length > 0){
            // 4、遍历全部一级文件对象。
            for (File f : files) {
                // 5、判断文件是否是文件,还是文件夹
                if(f.isFile()){
                    // 是文件,判断这个文件名是否是我们要找的
                    if(f.getName().contains(fileName)){
                        System.out.println("找到了:" + f.getAbsolutePath());
                        Runtime runtime = Runtime.getRuntime();
                        runtime.exec(f.getAbsolutePath());
                    }
                }else {
                    // 是文件夹,继续重复这个过程(递归)
                    searchFile(f, fileName);
                }
            }
        }
    }
}

二、IO流

2.1 定义:IO流又称输入输出流,用于读写数据的(可以读写文件,或网络中的数据…)。
在这里插入图片描述
2.2 IO流的分类和体系结构
在这里插入图片描述
1、按流中数据的最小单位,IO流分为四大类:
(1)字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流。
(2)字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流。
(3)字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
(4)字符输出流: 以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。
2、IO流的体系
在这里插入图片描述

2.3 IO流-字节流

1、FileInputStream(文件字节输入流)
(1)作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

public static void main(String[] args) throws Exception {
	//1、创建文件字节输入流管道,与源文件接通。
	//InputStream is=new FileInputStream(new File("file-io-app\\src\\itheima.txt"));
	//简化写法,参数为相对路径
    InputStream is = new FileInputStream(("file-io-app\\src\\itheima.txt"));
    //2、读取文件的字节数据。
    // public int read():每次读取一个字节返回
    int b1 = is.read();
    System.out.print((char) b1);
    //循环改造
    int b; // 用于记住读取的字节。
    while ((b = is.read()) != -1){
    	System.out.print((char) b);
    }  
    // public int read(byte[] buffer):每次读取多个字节返回int
    byte[] buffer1 = new byte[3];
    int len1 = is.read(buffer1);
    String rs1 = new String(buffer1);
    System.out.print(rs1);  //abc
    //循环改造
    byte[] buffer = new byte[3];
    int len; // 记住每次读取了多少个字节。  abc 66
    while ((len = is.read(buffer)) != -1){
    	// 转成字符串形式,从0开始到len,读取多少,倒出多少。
    	String rs = new String(buffer, 0 , len);
        System.out.print(rs); //abccc
    }
    //3、流使用完毕之后,必须关闭!释放系统资源!
    is.close();
}

(4)用文件字节输入流解决读取汉字输出乱码
① 定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节。
在这里插入图片描述

② Java官方为InputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回
在这里插入图片描述
2、FileOutputStream(文件字节输出流)
(1)作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

	public static void main(String[] args) throws Exception {
    // 1、创建一个字节输出流管道与目标文件接通。
    // 覆盖管道:覆盖之前的数据
	//OutputStream os =new FileOutputStream("file-io-app/src/itheima04out.txt");
    // 追加数据的管道
    OutputStream os=new FileOutputStream("file-io-app/src/itheima04out.txt", true);
    // 2、输出字节数据出去
    os.write(97); // 97就是一个字节,代表a
    os.write('b'); // 'b'也是一个字节
    // os.write('磊'); // 中文为三个字节[ooo],可以运行但是会乱码
   byte[] bytes = "我爱你中国abc".getBytes(); //转换为byte数组
   os.write(bytes); //我爱你中国abc
   os.write(bytes, 0, 15); //我爱你中国
   os.write("\r\n".getBytes()); // 换行符
   os.close(); // 关闭流
}

3、文件复制——复制一张图片,从磁盘D:/resource/meinv.png的一个位置,复制到C:/data/meinv.png位置。

public static void main(String[] args) throws Exception {
	// 1、创建一个字节输入流管道与源文件接通
    InputStream is = new FileInputStream("D:/resource/meinv.png");
    // 2、创建一个字节输出流管道与目标文件接通。
    OutputStream os = new FileOutputStream("C:/data/meinv.png");
    // 3、创建一个字节数组,负责转移字节数据。
    byte[] buffer = new byte[1024]; // 1KB.
    // 4、从字节输入流中读取字节数据,写出去到字节输出流中。读多少写出去多少。
    int len; // 记住每次读取了多少个字节。
    while ((len = is.read(buffer)) != -1){
    	os.write(buffer, 0, len);
    }
    os.close();
    is.close();
    System.out.println("复制完成!!");
}

4、释放资源
(1)try-catch-finally
① 格式

try{
}catch(IOException e){
	e.printStackTrace();
}finally{
}

② finaly代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止。
③ 作用:一般用于在程序执行完成后进行资源的释放操作 (专业级做法)。
(2)try-with-resource
① 格式

try(定义资源1;定义资源2){
	可能出现异常的代码;
}catch(异常类名 变量名){
	异常的处理代码;
}

2.4 IO流-字符流
1、FileReader(文件字符输入流)
(1)作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

public static void main(String[] args)  {
	//自动释放资源
	try (
		 // 创建一个文件字符输入流管道与源文件接通
          Reader fr = new FileReader("io-app2\\src\\itheima01.txt");
	){
		/* read() 每次读取一个字符,性能较差
		int c; // 记住每次读取的字符编号。
        while ((c = fr.read()) != -1){
             System.out.print((char) c);
        }
		*/
        // read(char[] buffer) 每次读取多个字符,性能较好
        char[] buffer = new char[3];
        int len; // 记住每次读取了多少个字符。
        while ((len = fr.read(buffer)) != -1){
        // 读取多少倒出多少
        	System.out.print(new String(buffer, 0, len));
      		}
       } catch (Exception e) {
            e.printStackTrace();
       }
}

2、FileWriter(文件字符输出流)
(1)作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
(2)常用方法
在这里插入图片描述
在这里插入图片描述

(3)注意事项:字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效。

fw.flush(); //刷新流
fw.close(); //关闭流

(4)示例

public static void main(String[] args) {
	try (
    	//1、创建一个文件字符输出流管道与目标文件接通,追加数据
        Writer fw = new FileWriter("io-app2/src/itheima02out.txt", true);
        ){
        // 1、public void write(int c):写一个字符
        fw.write('a'); //a
        fw.write(97); //a
        fw.write('磊'); // 磊
        // 2、public void write(String c)写一个字符串
        fw.write("我爱你中国abc");
		fw.write("\r\n"); // 换行
        // 3、public void write(String c ,int pos ,int len):写字符串的一部分出去
        fw.write("我爱你中国abc", 0, 5); //我爱你中国
        // 4、public void write(char[] buffer):写一个字符数组出去
        char[] buffer = {'黑', '马', 'a', 'b', 'c'};
        fw.write(buffer); //黑马abc
        // 5、public void write(char[] buffer ,int pos ,int len):写字符数组的一部分出去
        fw.write(buffer, 0, 2);
    } catch (Exception e) {
    	 e.printStackTrace();
    }
}

2.4 IO流-缓冲流

1、BufferedInputStream(字节缓冲输入流)和BufferedOutputStream(字节缓冲输出流)
(1)作用:提高字节流读写数据的性能。字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池。
(2)常用方法
在这里插入图片描述
(3)示例

public static void main(String[] args) {
	try (
		InputStream is = new FileInputStream("io-app2/src/itheima01.txt");
		// 1、定义一个字节缓冲输入流包装原始的字节输入流
		InputStream bis = new BufferedInputStream(is);
		OutputStream os = new FileOutputStream("io-app2/src/itheima01_bak.txt");
		// 2、定义一个字节缓冲输出流包装原始的字节输出流
		OutputStream bos = new BufferedOutputStream(os);
    ){
    byte[] buffer = new byte[1024];
    int len;
    while ((len = bis.read(buffer)) != -1){
    	bos.write(buffer, 0, len);
    }
    System.out.println("复制完成!!");
    } catch (Exception e) {
    	e.printStackTrace();
    }
}

2、BufferedReader(字符缓冲输入流)
(1)作用:自带8K (8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

public static void main(String[] args)  {
	try (
		Reader fr = new FileReader("io-app2\\src\\itheima04.txt");
		//创建字符缓冲输入流包装原始的字符输入流,不能用多态,否则不能调用BufferedReader特有方法            
        BufferedReader br = new BufferedReader(fr);
    ){
    String line; // 记住每次读取的一行数据
	while ((line = br.readLine()) != null){
    	System.out.println(line);
    }
	} catch (Exception e) {
    	e.printStackTrace();
    }
}

2、BufferedWriter(字符缓冲输出流)
(1)作用:自带8K (8192)的字符缓冲池,可以提高字符输出流读取字符数据的性能
(2)常用方法
在这里插入图片描述
在这里插入图片描述

2.5 IO流-转换流

1、不同编码读取出现乱码的问题
(1)若代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码。
(2)若代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时会出现乱码。
2、InputStreamReader(字符输入转换流)
(1)作用:解决不同编码时,字符流读取文本内容乱码的问题。
(2)解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
(3)常用方法在这里插入图片描述
3、OutputStreamWriter(字符输出转换流)
(1)作用:可以控制写出去的字符使用什么字符集编码
(2)解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。
(3)常用方法
在这里插入图片描述

2.6 IO流-打印流

1、PrintStream和PrintWriter(打印流)
2、作用: 打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
3、常用方法
① PrintStream
在这里插入图片描述
② PrintWriter
在这里插入图片描述
在这里插入图片描述
4、输出语句的重定向
(1)作用:可以把输出语句的打印位置改到某个文件中去。
(2)示例

public class PrintTest2 {
    public static void main(String[] args) {
        System.out.println("老骥伏枥");
        System.out.println("志在千里");
        try ( PrintStream ps = new PrintStream("io-app2/src/itheima09.txt"); ){
            // 把系统默认的打印流对象改成自己设置的打印流
            System.setOut(ps);
            System.out.println("烈士暮年");	
            System.out.println("壮心不已");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.7 IO流-数据流

1、DataOutputStream(数据输出流)
(1)作用:允许把数据和其类型一并写出去。
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

public static void main(String[] args) {
	try (
		 DataOutputStream dos =new DataOutputStream(new FileOutputStream("io-app2/src/itheima10out.txt"));
	){
    	dos.writeInt(97);
    	dos.writeDouble(99.5);
        dos.writeBoolean(true);
        dos.writeUTF("黑马程序员666!");
    } catch (Exception e) {
		e.printStackTrace();
	}
}

2、DataInputStream(数据输入流)
(1)作用:用于读取特定类型的数据。
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

public static void main(String[] args) {
	try (
		DataInputStream dis = new DataInputStream(new FileInputStream("io-app2/src/itheima10out.txt"));
	){
		int i = dis.readInt();
		System.out.println(i);  //97
        double d = dis.readDouble();
        System.out.println(d); //99.5
        boolean b = dis.readBoolean(); 
        System.out.println(b); //true
        String rs = dis.readUTF();
        System.out.println(rs); //黑马程序员666!
	} catch (Exception e) {
    	e.printStackTrace();
    }
}

2.8 IO流-序列化流

1、ObjectOutputStraem(对象字节输出流)
(1)作用:可以把Java对象进行序列化: 把Java对象存入到文件中去。
(2)常用方法
在这里插入图片描述在这里插入图片描述
(3)注意事项:对象如果要参与序列化,必须实现序列化接口 (java.io.Serializable)。
(4)示例

//对象如果要参与序列化,必须实现序列化接口 (java.io.Serializable)
public class User implements Serializable {
    private String loginName;
    private String userName;
    private int age;
    // transient 这个成员变量将不参与序列化。
    private transient String passWord;
    public User() {
    }
    public User(String loginName, String userName, int age, String passWord) {
        this.loginName = loginName;
        this.userName = userName;
        this.age = age;
        this.passWord = passWord;
    }
	//调用tostring,打印内容
    @Override
    public String toString() {
        return "User{" +"loginName='" + loginName + '\'' + ", userName='" + userName + '\'' +
                ", age=" + age +", passWord='" + passWord + '\'' +'}';
    }
}
public class Test1ObjectOutputStream {
    public static void main(String[] args) {
        try (
                //创建一个对象字节输出流包装原始的字节输出流。
                ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("io-app2/src/itheima11out.txt"));
                ){
            // 1、创建一个Java对象。
            User u = new User("admin", "张三", 32, "666888xyz");
            // 3、序列化对象到文件中去
            oos.writeObject(u);
            System.out.println("序列化对象成功!!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2、ObjectInputStream(对象字节输入流)
(1)作用:可以把Java对象进行反序列化: 把存储在文件中的Java对象读入到内存中来。
(2)常用方法
在这里插入图片描述
在这里插入图片描述
(3)示例

public class Test2ObjectInputStream {
    public static void main(String[] args) {
        try (
            // 1、创建一个对象字节输入流管道,包装 低级的字节输入流与源文件接通
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io-app2/src/itheima11out.txt"));
        ){
            User u = (User) ois.readObject();
            System.out.println(u); 
            //User{loginName='admin',userName='张三',age=32,passWord='null'}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(4)注意事项:如果要一次序列化多个对象,用一个ArrayList集合存储多个对象,然后直接对集合进行序列化( ArrayList集合已经实现了序列化接口)。

2.9 IO框架

1、框架
(1)定义:解决某类问题,编写的一套类、接口等,可以理解成一个半成品,大多框架都是第三方研发的。在框架的基础上开发,可以得到优秀的软件架构,并能提高开发效率。
(2)形式:一般是把类、接口等编译成class形式,再压缩成一个jar结尾的文件发行出去。
2、IO框架
(1)定义:封装了lava提供的对文件、数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等。
(2)Commons-io是apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率。
在这里插入图片描述
在这里插入图片描述
(3)导入commons-io-2.11.0.jar到项目中的步骤
① 在项目中创建一个文件夹: lib
② 将commons-io-2.6.jar文件复制到lib文件夹
③ 在jar文件上点右键,选择 Add as Library -> 点击OK
④ 在类中导包使用
(4)示例

public static void main(String[] args) throws Exception {
	//1.复制文件
	FileUtils.copyFile(new File("io-app2\\src\\itheima01.txt"), new File("io-app2/src/a.txt"));
	//2.复制文件夹
	FileUtils.copyDirectory(new File("D:\\resource\\私人珍藏"), new File("D:\\resource\\私人珍藏3"));
	//3.删除文件夹
	FileUtils.deleteDirectory(new File("D:\\resource\\私人珍藏3"));
	// Java提供的原生的一行代码搞定很多事情
	Files.copy(Path.of("io-app2\\src\\itheima01.txt"), Path.of("io-app2\\src\\b.txt"));
	System.out.println(Files.readString(Path.of("io-app2\\src\\itheima01.txt")));
    }
}

三、特殊文件

3.1 properties文件

1、定义:properties文件,称为属性文件,它可以很方便的存储一些类似于键值对的数据。经常当做软件的配置文件使用。
在这里插入图片描述
2、Properties是一个Map集合(键值对集合),但是我们一般不会当集合使用。Properties是用来代表属性文件的,通过Properties可以读写属性文件里的内容。
3、常用方法
① 使用Properties读取属性文件里的键值对数据
在这里插入图片描述在这里插入图片描述

public class PropertiesTest1 {
    public static void main(String[] args) throws Exception {
        // 1、创建一个Properties的对象出来(键值对集合,空容器)
        Properties properties = new Properties();
        // 2、开始加载属性文件中的键值对数据到properties对象中去
        properties.load(new FileReader("properties-xml-log-app\\src\\users.properties"));
        System.out.println(properties);
        // 3、根据键取值
        System.out.println(properties.getProperty("赵敏"));
        System.out.println(properties.getProperty("张无忌"));
        // 4、遍历全部的键和值。
        Set<String> keys = properties.stringPropertyNames();
        for (String key : keys) {
            //再根据键获取值
            String value = properties.getProperty(key);
            System.out.println(key + "---->" + value);
        }
        properties.forEach((k, v) -> {
            System.out.println(k + "---->" + v);
        });
    }
}

② 使用Properties把键值对数据写出到属性文件里去
在这里插入图片描述
在这里插入图片描述

public class PropertiesTest2 {
    public static void main(String[] args) throws Exception {
        // 1、创建Properties对象出来,先用它存储一些键值对数据
        Properties properties = new Properties();
        properties.setProperty("张无忌", "minmin");
        properties.setProperty("殷素素", "cuishan");
        properties.setProperty("张翠山", "susu");
        // 2、把properties对象中的键值对数据存入到属性文件中去
        properties.store(new FileWriter("properties-xml-log-app/src/users2.properties")
        , "i saved many users!");
    }
}

3.2 XML文件

1、定义:XML文件,本质是一种数据的格式,可以用来存储复杂的数据结构和数据关系。
2、语法规则
(1)XML中的 <标签名> 称为一个标签或一个元素,一般是成对出现的。XML中的标签名可以自己定义 (可扩展),但必须要正确的嵌套。XML中的标签可以有属性。
(2)XML中只能有一个根标签;文档声明必须是第一行。
(3)文件中放置的是XML格式的数据,这个文件就是XML文件,后缀一般要写成.xml。
(4)如果标签文本中有这些特殊字符,需要用一些占位符代替。

 &lt;  表示 <
 &gt;  表示 >
 &amp; 表示 &
 &apos; 表示 '
 &quot; 表示 "

(5)XML中可以写一个叫CDATA的数据区: <![CDATA[..内容... ]]>,里面的内容可以随便写。
3、应用场景:经常用来做为系统的配置文件,或者作为一种特殊的数据结构,在网络中进行传输。
4、解析XML文件——Dom4j框架
(1)思想:文本对象模型
在这里插入图片描述

(2)常用方法
① 解析XML文件——得到Document对象
在这里插入图片描述
② Document
在这里插入图片描述
③ Element提供的方法在这里插入图片描述
(3)示例

public static void main(String[] args) throws Exception {
	// 1、创建一个Dom4J框架提供的解析器对象
    SAXReader saxReader = new SAXReader();
    // 2、使用saxReader对象把需要解析的XML文件读成一个Document对象。
    Document document = saxReader.read("properties-xml-log-app\\src\\helloworld.xml");
    // 3、从文档对象中解析XML文件的全部数据了
    Element root = document.getRootElement();
    System.out.println(root.getName());
    // 4、获取根元素下的全部一级子元素。
    List<Element> elements = root.elements("user");
    for (Element element : elements) {
    	System.out.println(element.getName());
    }
    // 5、获取当前元素下的某个子元素。
    Element people = root.element("people");
    System.out.println(people.getText());
    // 如果下面有很多子元素user,默认获取第一个。
    Element user = root.element("user");
    // 6、获取元素的属性信息呢?
    Attribute id = user.attribute("id");
    System.out.println(id.getName());
    System.out.println(id.getValue());
    List<Attribute> attributes = user.attributes();
    // 7、如何获取全部的文本内容:获取当前元素下的子元素文本值
    System.out.println(user.elementText("name"));
    Element data = user.element("data");
    System.out.println(data.getText());
    System.out.println(data.getTextTrim()); // 取出文本去除前后空格
}

5、XML约束
(1)定义:就是限制XML文件只能按照某种格式进行书写。
(2)约束文档:专门用来限制xml书写格式的文档,比如: 限制标签、属性应该怎么写。
(3)约束文档的分类:DTD文档和Schema文档

3.3 日志

1、定义:可以将系统执行的信息,方便的记录到指定的位置(控制台、文件中、数据库中)。可以随时以开关的形式控制日志的启停,无需侵入到源代码中去进行修改。
2、日志框架——logback
(1)步骤
① 导入logback框架(slftj-api.jar、logback-core.jar、logback-classes.jar)到项目中去。
② 将logback.xml配置文件复制粘贴到src目录下(必须是src目录)。
③ 创建Logback框架提供的Logger对象,然后用Logger对象调用其提供的方法就可以记录系统的日志信息。
(2)示例

 public class LogBackTest {
       // 创建一个Logger日志对象
       public static final Logger LOGGER = LoggerFactory.getLogger("LogBackTest");
       public static void main(String[] args) {
           //while (true) {
               try {
                   LOGGER.info("chu法方法开始执行~~~");
                   chu(10, 0);
                   LOGGER.info("chu法方法执行成功~~~");
               } catch (Exception e) {
                   LOGGER.error("chu法方法执行失败了,出现了bug~~~");
               }
       } 
       public static void chu(int a, int b){
           LOGGER.debug("参数a:" + a);
           LOGGER.debug("参数b:" + b);
           int c = a / b;
           LOGGER.info("结果是:" + c);
       }
   }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值