IO流

1.什么是IO流

在工作中,经常会操作磁盘上的资源,这个过程中实现了数据的输入和输出操作,磁盘上的文件和内存之间进行交互,数据的交互需要有一个媒介或者管道,把这个媒介或者管道就称为IO流,也被称为输入输出流【I:Input O:Output】
输入:从外部存储设备到内存叫输入|读取
输出:从内存到外部存储设备叫输出|写入

2.流的作用和原理

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总成或抽象。即数据在两设备键的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

3.IO流的种类

按照流的流向分:
输入流:表示将数据读取到Java程序(内存)中使用的流。
输出流:表示从Java程序(内存)向外输出的流。
根据处理数据单位分:
字节流:一次传输一个字节数据,将数据以字节的形式传输。
字符流:一次性传输一个字符(UTF-8编码1、2或3个字节)数据,将数据以字符的形式传输。
按照功能分:
节点流:可以从或向特点的地方(节点)读写字节数据。
处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。
先来一张结构图:

在这里插入图片描述

4字节输入流
InputStream类的常用方法

InputStream是所有字节输出流的父类,是抽象类,要用FileInputStream实例化对象,在这里插入图片描述

文件输入流FileInputStream

public class Demo1 {
        public static void main(String[] args) throws Exception {
            //1.创建流
            FileInputStream fis = new FileInputStream("d:gp4.txt");
            //2.读取文件
            //2.1一次读取一个字节
            /*int data = -1;
            while((data = fis.read())!=-1){
                System.out.print((char) data);
            }*/
            //2.2一次读取多个
            byte[] buf = new byte[1024*4];//4k
            /*int len = fis.read(buf);//len是读取数据的长度
            int len2 = fis.read(buf);
            int len3 = fis.read(buf);
            System.out.println("第一次读取的:" + len);
            System.out.println("第一次读取的:" + len2);
            System.out.println("第一次读取的:" + len3);*/
            int len = -1;
            while ((len = fis.read(buf))!=-1){
                for (int i = 0; i < len; i++) {
                    System.out.print((char) buf[i]);
                }
            }
            System.out.println();
            //3.关闭
            fis.close();
            //
    
        }
    }

注意:创建被操作文件:此文件必须存在,否则读取时,排除文件找不到异常。
当读到最后一个文件的时候,控制台输出-1

5 字节输出流

OutputStream是所有字节输出流的父类,是抽象类,要用FileOutputStream实例化对象,OutputStream常用方法:

在这里插入图片描述

public class Demo2 {
    public static void main(String[] args) throws IOException {
        //1.创建输出流
        FileOutputStream fos = new FileOutputStream("d:\\info.txt",true);
        //2.写入
        //fos.write(91);
        String content = "helloword\r\n";
        fos.write(content.getBytes());//将字符串的值转为byte类型的;
        fos.flush();
        //关闭
        fos.close();
        System.out.println("写入完毕");
    }
}

注意:当向文件中写入数据时,若文件不存在,程序会自动创建。
字节输入流可以不刷新直接关闭,字节输出流关闭前要刷新,把内存中的数据传入硬盘。
只能写入byte类型

6 字符输出流

Reader:是所有字符输入流的父类,为一个抽象类,不能实例化对象,使用它的子类FileReader类
Reader—>InputStreamReader—>FileReader

public class Demo3 {
    public static void main(String[] args) throws Exception {
        //1.创建流
        FileReader reader = new FileReader("d:\\info.txt");
        //2.读取
        //2.1一次读取一个字符
       /* int data = reader.read();*/
        int data = -1;
        while ((data = reader.read()) !=-1){
            System.out.print((char)data);
        }
        //3.关闭
        reader.close();
    }
}

FileReader创建的时候需要传入一个File对象。
FileReader的reader可以一次读取一个char数组。
当读到最后一个字符后再读一次返回-1;

7 字符输出流

Writer :是所有字符输出流的父类,为一个抽象类,不能实例化,使用它的子类FIleWriter

public class Demo5 {
    public static void main(String[] args) throws Exception {
        //1.创建字符输出流
        FileWriter fileWriter = new FileWriter("d:\\info.txt");
        //2.写入
        for (int i = 0; i < 10; i++) {
            fileWriter.write("好好学习,天天向上\r\n");
            fileWriter.flush();
        }
        //3.关闭
        fileWriter.close();
        System.out.println("执行完毕");
    }
}

注意:当文件不存在的时候,系统会自动创建一个文件。
写入的时候可以直接写入字符串
记得关闭前要刷新。

使用字节复制字符串
public class CopyDemo1 {
    public static void main(String[] args) throws Exception {
        //1.创建字节输入,输出流
        FileInputStream fis = new FileInputStream("copy.png");
        FileOutputStream fos = new FileOutputStream("copy2.png");
        //2.读取和写入
        byte[] buf = new byte[1024*4];
        int len = -1;
        while ((len = fis.read(buf)) !=-1){
            fos.write(buf,0,len);
        }
        fis.close();
        fos.close();
    }
}
使用字符流复制数组
public class Demo4 {
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("12.txt");
        FileWriter fw = new FileWriter("121.txt");
        char[] c = new char[1024*4];
        int l = -1;
        while ((l = fr.read(c))!=-1){
            fw.write(c);
            fw.flush();
        }
        fr.close();
        fw.close();
    }
}

如果复制的文件是文本文件,用字节流和字符流都可以。
如果复制的文件是图片、音乐、电影,用字符流辅助会出现乱码,要用字节流复制。

补充:utf-8的BOM头

在这里插入图片描述

练习:递归显示所有文件夹中的所有的文件,包括子文件夹中的内容和递归删除文件夹。
public class Demo1 {
	public static void main(String[] args) {
		File dir=new File("d:\\");
//		listDir(dir,0);
		deleteDir(dir);
	}
	// 1 递归显示文件夹中的所有的文件,包括子文件夹中内容
	public static void listDir(File dir,int level) {
		System.out.println(getSeparator(level)+dir);
		level++;
		File[] listFiles = dir.listFiles();
		if(listFiles!=null&&listFiles.length>0) {
			for (File file : listFiles) {
				if(file.isDirectory()) {//如果是文件夹,递归调用
					listDir(file,level);
				}else {
					System.out.println(getSeparator(level)+file);
				}
			}
		}
	}
	public static String getSeparator(int level) {
		StringBuilder sb=new StringBuilder();
		for(int i=0;i<level;i++) {
			sb.append("  ");
		}
		return sb.toString();
	}

	//2 递归删除文件夹
	public static void deleteDir(File dir) {
		//1先删除里面的内容
		File[] listFiles = dir.listFiles();
		if(listFiles!=null&&listFiles.length>0) {
			for (File file : listFiles) {
				if(file.isDirectory()) {
					deleteDir(file);
				}else {
					//删除文件
					System.out.println(file+"-------"+file.delete());
				}
			}
		}
		//删除文件夹
		System.out.println(dir+"-------"+dir.delete());
	}
}
8 转换流
InputStreamReader

作用:
a.实现字节流到字符流的转换
b.解决中文乱码的问题
中文编码
gb2312 (采用两个字节保存字符汉字,英文数字一个字节)
GBK (采用两个字节保存字符汉字,英文数字一个字节)
GB18030 (英文数字都是一个字节,中文是两个或四个字节)
Unicode字符集(包含每个国家的所有字符)国际通用
unicode编码 使用两个字节—65536个字符,浪费空间
为了节省空间使用转码形式
utf-8 使用 1 、2、3个字节 (EF BB BF 记事本添加的BOM(Byte Order Mark)头,编码的标记)
utf-16 使用两个字节—65536个字符 (FF FE 小端(尾) FE FF 大端(尾))
utf-32 使用4个字节
台湾 big5
ANSI:在简体中文Windows操作系统中, ANSI 编码代表 GBK 编码
只有转换流才能指定读取和写入的字符集
在这里插入图片描述

InputStreamReader:字节字符转换输入流,将字节输入流转换为字符输入流

代码实现:

public class InputStreamReaderDemo {
	public static void main(String[] args) throws IOException {
		//1.实例化File的对象
		//File file = new File("file/input1.txt");
		
		//2.实例化转换输入流的对象
		//注意:当一个流的存在的意义是为了实例化另外一个流,则这个流不需要手动进行关闭
		//InputStream input = new FileInputStream(file);
		//InputStreamReader reader = new InputStreamReader(input);
		//使用默认的字符集【GBK】进行实例化转换流
		//InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("file/input1.txt")));

		//使用指定字符集进行实例化转换流
		//字符集一般使用字符串直接传参,不区分大小写,但是,如果字符集书写有误的话,则会抛出java.io.UnsupportedEncodingException
		InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("file/input1.txt")),"UTF-8");
		
		//3.读取
		char[] arr = new char[16];
		int len = 0;
		
		while((len = reader.read(arr)) != -1) {
			String string = new String(arr, 0, len);
			System.out.println(string);
		}
		
		reader.close();
	}
}
OutputStreamWriter

OutputStreamWriter:字符转换输出流,将内存中的字符转成字节保存到硬盘中。

public class OutputStreamWriterDemo {
	public static void main(String[] args) throws IOException {
		//需求:将一段文本以utf-8的格式写入到文件中【注,文件格式为默认格式】
		//1.实例化FIle对象
		//注意:对于所有的输出流而言,文件可以不存在,在进行写入的过程中可以自动进行创建
		//但是,对于所有的输入流而言,文件必须先存在,然后才能操作,否则,会抛出FileNotFounedException
		File file = new File("file/output1.txt");
		
		//2.实例化转换输出流
		//如果不想覆盖源文件中的内容时,则在传参的时候,设置一个参数为true
		OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true), "utf-8");

		//3.写入
		writer.write("家客户放假啊刚回家");
		
		//4.刷新
		writer.flush();
		
		//5.关闭
		writer.close();
	}
}
9 缓冲流

作用:主要是为了增强基础流的功能而存在的,提高了流的工作效率【读写效率】

缓冲区可以重复使用。
默认缓冲区大小8192,8k
使用newLine可以实现跨平台换行

注意:如果使用记事本创建的文件,文件是utf-8或者unicode编码,文件的前面有一个BOM(Byte Order Mark)头,BOM作用指定文件使用的编码类型。GBK编码没有添加bom头。
utf-8:EF BB BF
unicode 小端: FF FE 66 00
unicode 大端 :FE FF 00 66

BufferedInputStream类
public class BufferedInputStreamDemo {
	public static void main(String[] args) throws IOException {
		//实例化一个File对象
		File file = new File("file/test22.txt");
		
		//实例化一个缓冲字节输入流的对象
		BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));
		
		/*
		//读取
		byte[] arr = new byte[1024];
		int len = 0;
		while((len = input.read(arr)) != -1) {
			String string = new String(arr, 0, len);
		}
		*/
		
		byte[] arr = new byte[4];
		int len = input.read(arr);
		String string = new String(arr, 0, len);
		System.out.println(string);
		
		input.mark(66);
		
		len = input.read(arr);
		string = new String(arr, 0, len);
		System.out.println(string);

		// 实现了效果:覆水可收
		input.reset();

		len = input.read(arr);
		string = new String(arr, 0, len);
		System.out.println(string);

		input.close();
	}
}
BufferedOutputStream类
public class BufferedOutputStreamDemo {
	public static void main(String[] args) throws IOException {
		//实例化FIle对象
		File file = new File("test33.txt");
		
		//实例化换种字节输出流 
		BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
		
		//写
		output.write("你好的halle".getBytes());
		
		//刷新
		output.flush();
		
		//关闭
		output.close();
	}
}
BufferedReader类
public class BufferedReaderDemo {

	public static void main(String[] args) throws IOException {
		//实例化FIle对象
		File file = new File("test33.txt");
		
		//实例化缓冲字符流的对象
		BufferedReader reader = new BufferedReader(new FileReader(file));
		
		//方式一:read循环读取
		/*
		//读取
		char[] arr = new char[8];
		int len = 0;
	
		while((len = reader.read(arr)) != -1) {
			String string = new String(arr, 0, len);
		}
		*/
		
		//方式二:readLine循环读取
		/*
		String result1 = reader.readLine();
		System.out.println(result1);
		
		String result2 = reader.readLine();
		System.out.println(result2);
		*/
		String result = "";
		while((result = reader.readLine()) != null) {
			System.out.println("第一行:" + result);
		}
		
		reader.close();
	}
}
BufferedWriter类
public class BufferedWriterDemo {
	public static void main(String[] args) throws IOException {
		// 实例化FIle对象
		File file = new File("test33.txt");
		
		//实例化缓冲字符输出流
		BufferedWriter writer = new BufferedWriter(new FileWriter(file,true));

		// 写
		writer.write("今天天气还可以");

		// 作用:主要就是为了换行
		writer.newLine();

		// 刷新
		writer.flush();
		
		//关闭
		writer.close();
	}
}
10 内存流

案例:完成一个字母大小写转换的程序

public class TextDemo02 {
	public static void main(String[] args) throws IOException {
		//定义一个字符串,全部由大写字母组成
		String string = "HELLOWORLD";
		
		//内存输入流
		//向内存中输出内容,注意:跟文件读取不一样,不设置文件路径
		ByteArrayInputStream bis  = new ByteArrayInputStream(string.getBytes());
		//内存输出流
		//准备从内存中读取内容,注意:跟文件读取不一样,不设置文件路径
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		int temp = 0;
		//read()方法每次只读取一个字符
		while((temp = bis.read()) != -1) {
			//将读取的数字转为字符
			char c = (char)temp;
			//将字符变为大写
			bos.write(Character.toLowerCase(c));
		}
		//循环结束之后,所有的数据都在ByteArrayOutputStream中
		//取出内容,将缓冲区内容转换为字符串
		String newString = bos.toString();
		
		//关闭流
		bis.close();
		bos.close();
		System.out.println(newString);
	}
}

注意:内存操作流的操作对象,一定是以内存为主准,不要以硬盘为准。

11 标准输入输出流

Java的标准输入/输出分别通过System.in和System.out实现,默认情况下分别代表是键盘和显示器

PrintStream类:PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。

PrintWriter类:向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream中的所有 print方法。它不包含用于写入原始字节的方法。

public static void main(String[] args)throws Exception {
		//1创建PrintStream
		//PrintStream ps=new PrintStream("d:\\print.txt");
		PrintWriter pw=new PrintWriter("d:\\print.txt");
		//2打印
		pw.println(true);
		pw.println(3.14);
		pw.println(100);
		pw.println("我爱北京");
		//3刷新
		pw.flush();
		//4关闭
		pw.close();
	}
public class PrintStreamDemo {
	public static void main(String[] args) throws FileNotFoundException {
		//System.out.println("hello world");
		//创建打印流的对象
		//注意:默认打印到控制台,但是,如果采用setOut方法进行重定向之后,将输出到指定的文件中
		PrintStream print = new PrintStream(new FileOutputStream(new File("test33.txt")));
		/*
		 * static void setErr(PrintStream err) 
          	重新分配“标准”错误输出流。 
		static void setIn(InputStream in) 
          	重新分配“标准”输入流。 
		static void setOut(PrintStream out) 
          	重新分配“标准”输出流。 
		 * */
		//将标准输出重定向到print的输出流
		System.setOut(print);
		
		System.out.println("hello world");
	}
}
public class InputStreamDemo {
	public static void main(String[] args) throws FileNotFoundException {
		FileInputStream inputStream = new FileInputStream(new File("test33.txt"));
		
		//setIn
		System.setIn(inputStream);
		
		//System.out.println("请输入内容:");
		
		//默认情况下是从控制台进行获取内容
		//但是如果使用setIn方法设置了重定向之后,将从指定文件中获取内容
		Scanner sc = new Scanner(System.in);
		
		String string = sc.next();
		
		System.out.println(string);
	}
}
12 对象流

流中流动的数据是对象
将一个对象写入到本地文件中,被称为对象的序列化
将一个本地文件中的对象读取出来,被称为对象的反序列化
使用对象流
ObjectInputStream: 对象输出流
ObjectOutputStream:对象输入流
注意:
序列化对象的类型必须实现Serializable接口。否则不能序列化。
系统根据系统的序列化ID判断是否是同一个类
如果向将多个对象序列化到本地,可以借助于集合,【思路:将多个对象添加到集合中,将集合的对象写入到本地文件中,再次读出来,获取到的仍然是集合对象,遍历集合】。
对象中那些字段可以不序列化:
1 transient 修饰的字段
2 静态的字段
在要序列化类中添加字段,保证序列化和反序列化是同一个类
可以定义对象的序列值,这样对象如果发生改变,还能输出该对象,不过新的值是默认值
private static final long serialVersionUID = 100L;

public class ObjectStreamDemo {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//objectOutputStreamUsage();
		objectInputStreamUsage();
	}

	// 写:将对象进行序列化
	public static void objectOutputStreamUsage() {
		//1.实例化一个Person的对象
		Person person =  new Person("张三", 10, 'B');
		
		//2.实例化一个对象输出流的对象
		ObjectOutputStream output = null;
		try {
			output = new ObjectOutputStream(new FileOutputStream(new File("file/person.txt")));
		
			//3.将对象写入到流中
			output.writeObject(person);
			
			//4.刷新
			output.flush();
		
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally {
			try {
				output.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	// 读:反序列化
	public static void objectInputStreamUsage() {
		//1.实例化对象输入流的对象
		try {
			ObjectInputStream input = new ObjectInputStream(new FileInputStream(new File("file/person.txt")));
		
			//2.读取
			Object object = input.readObject();
			
			//3.对象的向下转型
			if(object instanceof Person) {
				Person p = (Person)object;
				System.out.println(p);
			}
		
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}	

注意:在使用对象流的时候,用于初始化对象流的参数只能是字节流(将对象转换为二进制的形式,然后再把二进制写入文件)

13 RandomAccessFile类

RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。
seek设置读取指针的偏移量,每次都是从0开始
skipBytes(10)跳过10个字节。从当前位置开始跳。

public class TextDemo01 {
	public static void main(String[] args) throws Exception {
		RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
		// 以下向file文件中写数据
		file.writeInt(20);// 占4个字节
		file.writeDouble(8.236598);// 占8个字节
		//这个长度写在当前文件指针的前两个字节处,可用readShort()读取
		file.writeUTF("这是一个UTF字符串");
		file.writeBoolean(true);// 占1个字节
		file.writeShort(395);// 占2个字节
		file.writeLong(2325451l);// 占8个字节
		file.writeUTF("又是一个UTF字符串");
		file.writeFloat(35.5f);// 占4个字节
		file.writeChar('a');// 占2个字节
		//把文件指针位置设置到文件起始处
		file.seek(0);

		// 以下从file文件中读数据,要注意文件指针的位置
		System.out.println("——————从file文件指定位置读数据——————");
		System.out.println(file.readInt());
		System.out.println(file.readDouble());
		System.out.println(file.readUTF());
		
		//将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
		file.skipBytes(3);
		System.out.println(file.readLong());
		
		//跳过文件中“又是一个UTF字符串”所占字节
		//注意readShort()方法会移动文件指针,所以不用写2。
		file.skipBytes(file.readShort()); 
		System.out.println(file.readFloat());

		// 以下演示文件复制操作
		System.out.println("——————文件复制(从file到fileCopy)——————");
		file.seek(0);
		RandomAccessFile fileCopy = new RandomAccessFile("fileCopy.txt", "rw");
		int len = (int) file.length();// 取得文件长度(字节数)
		byte[] b = new byte[len];
		//全部读取
		file.readFully(b);
		fileCopy.write(b);
		System.out.println("复制完成!");
	}
}
14 Properties类

是Map接口的一个实现类,并且是Hashtable的子类

Properties集合中元素也是以键值对的形式存在的

Properties特点:
1 存储属性名和属性值
2 属性名和属性值都是字符串
3 和流有关系
4 没有泛型

public class PropertiesDemo {
	public static void main(String[] args) {
		//1.实例化一个Properties的对象
		Properties pro = new Properties();
		System.out.println(pro);
		
		//2.把文件userlist.properties中的键值对同步到集合中
		//实质:读取
		/**
		 *  void load(InputStream inStream) 
          	从输入流中读取属性列表(键和元素对)。 
		 */
		try {
			pro.load(new BufferedInputStream(new FileInputStream(new File("file/userlist.properties"))));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println(pro);
		
		//3.向集合中添加一对键值对
		/*
		 *  Object setProperty(String key, String value) 
          	调用 Hashtable 的方法 put。 
		 * */
		pro.setProperty("address", "china");
		
		System.out.println(pro);
		
		try {
			//4.store
			//实质:写入
			//comments:工作日志
			pro.store(new BufferedOutputStream(new FileOutputStream(new File("file/userlist.properties"))), "add a pair of key and value");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
总结

1 转换流
InputStreamReader 字节通向字符的桥梁—》指定编码
中文编码 gb2313–>gbk—>gb18030 1 2个字节 4个字节
国际 unicode编码表 包括了世界所有的国家的语言
utf-8 编码 1 2 3 字节
utf-16 编码 unicode 2个字节
utf-32 编码 4个字节
繁体big5

OutputStreamWriter 字符流通向字节流的桥梁---》指定编码

2 缓冲流:增强基础流的功能,缓冲区提高读写效率
BufferedInputStream
BufferedOutputStream

BufferedReader---> readLine();读取一行
BufferedWriter---> newLine();//写入行终止符    \r\n   \n

3 内存流 : 内存操作的数据就在内存
ByteArrayInputStream
ByteArrayOutputStream
4 对象流:
序列化: 把内存中的对象转换成二进制数据的过程。
反序列化: 把二进制数据转成对象的过程。
ObjectInputStream -->readObject();
ObjectOutputStream–>writeObject();

Serializable:可序列化 标记接口

不能序列化成员
	transient 修饰的成员
	静态成员

版本号:保证序列化和反序列化的类是同一个类。
serialVersionUID

5 标准输入输出
System.out PrintStream 写到控制台
System.in InputStream 从控制台读取

重定向标准输出流
System.setOut(new PrintStream("d:\\print.txt"));
System.setIn(new FiletInputStream("d:\\aaa.txt"));

6 RandomAccessFile 随机访问文件,既可以读取,也可以写入
writeInt(); //写整数
writeUTF();//写字符串
writeDouble();//写浮点数
writeBoolean();//写入boolean

readInt();
readUTF();
readDobule();
readBollean();

seek();//从头开始设置偏移量
skipBytes(20);//从当前位置,向后调20个字节

7 Properties集合
1 存储属性名,属性值
2 存储String类型
3 和流有关系
4 没有泛型

setProperty(key,value);
getProperty(key);

stringPropertyNames();//获取的属性名的集合set

//和有关的方法
list(System.out);

load(); //从硬盘加载属性文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值