java各种文件(xml、properties、txt)处理操作的一道题目

2 篇文章 0 订阅
1 篇文章 0 订阅

一、             概述:存储员工的xml文件过多且内容无规律,为了方便简单的查看,要将xml中的内容按要求分开写入txt文件中,并打包归档。

 

二、             目标概述:分析staff_.zipxml,将符合要求(见三)的员工数据按规定(见四)写入txt文件,将多个输出文件打包为staff_select.zipDB记录生成zip的路径和时间YYYY:mm:dd HH:mm:ss

 

staff_.zip中employees.xml的样例:

<employees>
	<!--Employee Xml Catalog-->
	<employee name="FHK ZY#E" number="65253008">
		<public>
			<department>PRM</department>
			<group>PRM 7</group>
		</public>
		<individual>
			<name>FHK ZY#E</name>
			<number>65253008</number>
			<gender>Male</gender>
			<age>91</age>
			<phoneno>160296718242</phoneno>
			<workexperience>7</workexperience>
		</individual>
	</employee>
	<employee name="RHUZJJAE" number="25904879">
		<public>
			<department>OCS</department>
			<group>OCS 1</group>
		</public>
		<individual>
			<name>RHUZJJAE</name>
			<number>25904879</number>
			<gender>Male</gender>
			<age>81</age>
			<phoneno>697165507224</phoneno>
			<workexperience>4</workexperience>
		</individual>
	</employee>
	<employee name="JVPS#M X" number="88536762">
		<public>
			<department>Human Resources</department>
			<group>Human Resources 6</group>
		</public>
		<individual>
			<name>JVPS#M X</name>
			<number>88536762</number>
			<gender>Male</gender>
			<age>81</age>
			<phoneno>682619863271</phoneno>
			<workexperience>3</workexperience>
		</individual>
	</employee>
</employees>


 

jdbc.properties:

driverClassName=oracle.jdbc.xa.client.OracleXADataSource
url=jdbc:oracle:thin:@127.0.0.1:1521:ibss
userName=ibss
password=ibss
maxSize=10
minSize=8
idleTimeout=10
checkOutTimeout=10000
testsql=select count(*) from dual
checkAfterUsed=true
isSameRM=false


invalidCondition.properties:

#name validation
origName=$,#,&
targName=*
#age validation
minAge=18
maxAge=38
#gender validation
gender=Other

 

三、             Xml解析要求xml中数据有些不符合要求,

1、要根据invalidCondition.properties文件中的条件过滤筛选符合要求(有效)的员工,不符合要求的员工信息不写入txt文件中。

#name validation(员工姓名中含有 #$&的要将其转换为*)

origName=$,#,&

targName=*

#age validation(年龄小于18大于48的员工不合法)

minAge=18

maxAge=48

#gender validation(性别为Other的员工不合法)

gender=Other

 

2、员工工号相同情况不考虑

 

3、员工姓名去前后空格

 

四、            txt格式要求:

1、     txt文件名:“部门名”(该txt内员工数据均为文件名所示部门的员工)。

2、     txt文件格式:员工按部门组(从小到大)顺序排列

#Department:CRM(部门总人数:部门有效人数)

 

deptGroup=0

staffNo=*****

staffName=*****

staffGender=*****

staffAge=*****

phoneNumber=*****

workExp=***** Year(Years)

#-------------------------

 

五、            归档要求(可选功能)

读取jdbc中的参数,连接数据库,记录文件生成时间和路径,表(EMPLOYEE_ZIP)结构:

CreateTime VarChar2(1024)

ZipPath     Varchar2(1024)

 

 

六、            提交要求:

自己创建工程,工程目录结构自定义,完成试题后将整个工程目录压缩为:

“姓名_.zip”发给xxx 

 

七、            java代码实现:

 

1、元数据bean类:

package nju.syy.vo;

import java.util.ArrayList;

public class EmployeeBean {

	private String name;
	private String number;
	private String department;
	private String group;
	private String gender;
	private String age;
	private String phoneno;
	private String workExperience;
	private static ArrayList<EmployeeBean> employeeList = new ArrayList<EmployeeBean>();
	
	public EmployeeBean employeeBean;

	public EmployeeBean(EmployeeBean eb) {
		this.employeeBean = eb;
	}

	public EmployeeBean() {
		// TODO Auto-generated constructor stub
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}

	public String getGroup() {
		return group;
	}

	public void setGroup(String group) {
		this.group = group;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getPhoneno() {
		return phoneno;
	}

	public void setPhoneno(String phoneno) {
		this.phoneno = phoneno;
	}

	public String getWorkExperience() {
		return workExperience;
	}

	public void setWorkExperience(String workExperience) {
		this.workExperience = workExperience;
	}

	public EmployeeBean getEmployeeBean() {
		return employeeBean;
	}

	public void setEmployeeBean(EmployeeBean employeeBean) {
		this.employeeBean = employeeBean;
	}

	public ArrayList<EmployeeBean> getEmployeeList() {
		return employeeList;
	}

	@SuppressWarnings("static-access")
	public void setEmployeeList(ArrayList<EmployeeBean> employeeList) {
		this.employeeList = employeeList;
	}

}


 2、控制service类:

package nju.syy.service;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;

import nju.syy.util.OralceConnect;
import nju.syy.util.PropertiesUtil;
import nju.syy.util.TxtUtil;
import nju.syy.util.ZipUtil;
import nju.syy.vo.EmployeeBean;


public class EmloyeeHandle {

	ArrayList<EmployeeBean> employeeList = new ArrayList<EmployeeBean>();
	Map<String, Integer> countMap = new HashMap<String, Integer>();
	PropertiesUtil pu = new PropertiesUtil();
	Map<String, String> propertiesMap = pu
			.readTxtFormatProperties("invalidCondition.properties");

	public Map<String, Integer> getCountMap(){
		return countMap;
	}
	
	private void readXMLFile(String zipFile) {

		ZipUtil zipUtil = new ZipUtil();
		employeeList = zipUtil.unZipFile(zipFile);
	}

	public void writeToTxtFile() {
		TxtUtil tu = new TxtUtil();
		tu.writeToTxtFile(employeeList);
	}

	public boolean isValidEmployee(EmployeeBean eb) {

		int age = Integer.parseInt(eb.getAge());
		int minAge = Integer.parseInt(propertiesMap.get("minAge"));
		int maxAge = Integer.parseInt(propertiesMap.get("maxAge"));
		if ((eb.getGender() .equals(propertiesMap.get("gender")) ) || (age < minAge)
				|| (age > maxAge))
			return false;
		else
			return true;
	}

	public void transfer(EmployeeBean eb) {

		String origName = propertiesMap.get("origName");
		String targName = propertiesMap.get("targName");
		String[] origNames = origName.split(",");
		String pattern = new String();
		for (String str : origNames) {
			pattern += (str + "|");
		}

		eb.setName(eb.getName().replaceAll("[" + pattern + "]", targName));
	}

	/**
	 * 分組
	 * 
	 * @param employeeList
	 */
	public Map<String, LinkedList<EmployeeBean>> grouped(
			ArrayList<EmployeeBean> employeeList) {
		
		Map<String, LinkedList<EmployeeBean>> employeeGroupMap = new HashMap<String, LinkedList<EmployeeBean>>();
		EmloyeeHandle eh = new EmloyeeHandle();
		
		for (EmployeeBean eb : employeeList) {
			
			LinkedList<EmployeeBean> ebList;
			String department = eb.getDepartment();

			if (employeeGroupMap.containsKey(department)) {
				countMap.put(department, countMap.get(department) + 1);

				if (eh.isValidEmployee(eb)) {
					eh.transfer(eb);
					ebList = employeeGroupMap.get(department);
					addUpSort(eb, ebList);
					employeeGroupMap.put(department, ebList);
				}
				
			} else {
				countMap.put(department, 1);
				ebList = new LinkedList<EmployeeBean>();
				employeeGroupMap.put(department, ebList);
				if (eh.isValidEmployee(eb)) {
					eh.transfer(eb);
					addUpSort(eb, ebList);
				}
				
			}
		}
		
		for(java.util.Iterator<Entry<String, Integer>> iterator = countMap.entrySet().iterator(); iterator.hasNext();){
			Entry<String, Integer> entry = iterator.next();
			String key = entry.getKey();
			Integer count = entry.getValue();
			
			System.out.println("Department: " + key + ", count: " + count);
		}
		return employeeGroupMap;
	}

	/**
	 * 升序算法含义: 1、首先判断新增元素和元素集合不能为null; 2、判断元素集合是否为空,如果为空则将当前新增元素插入到链表的表头
	 * 3、如果不是第二种情况则需要遍历整个链表,查看是否有已存在元素比当前新增元素大, 如果有则将当前元素插入到已存在元素的位置
	 * 4、如果遍历到最后一个位置没有比当前新增元素大,那么就将新增元素插入到链表的最后一个位置
	 * 
	 */

	@SuppressWarnings("unused")
	public void addUpSort(EmployeeBean eb, LinkedList<EmployeeBean> ebList) {

		String curGroup = eb.getGroup();
		String[] str = curGroup.split(" ");
		int curGroupNo = Integer.parseInt(str[str.length - 1]);

		if (eb == null) {
			try {
				throw new Exception("插入元素为null");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (ebList == null) {
			try {
				throw new Exception("元素集合为null");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (ebList.size() == 0) {
			ebList.add(eb);
		} else {
			String firstGroup = ebList.getFirst().getGroup();
			String[] str1 = firstGroup.split(" ");
			int firstGroupNo = Integer.parseInt(str1[str1.length - 1]);
			if (curGroupNo < firstGroupNo) {
				ebList.addFirst(eb);
			} else {
				boolean insertFlag = false;
				for (EmployeeBean e : ebList) {
					String group = e.getGroup();
					String[] str2 = group.split(" ");
					int groupNo = Integer.parseInt(str2[str2.length - 1]);
					if (curGroupNo < groupNo) {
						int index = ebList.indexOf(e);
						ebList.add(index, eb);
						insertFlag = true;
						break;
					}
				}
				if (!insertFlag) {
					ebList.addLast(eb);
				}
			}
		}
	}

	/**
	 * 保存生成zip的路径和时间到DB
	 */
	public void save(){
		
		OralceConnect oralceConnect = new OralceConnect();
		Connection conn = oralceConnect.connectToOracle();
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		String directory = System.getProperty("user.dir");
		File file =new File(directory + "\\staff_select.zip");
		
        Long time =file.lastModified();
        Calendar cd = Calendar.getInstance();
        cd.setTimeInMillis(time);
        System.out.println(cd.getTime());
        try
		{
			pstmt = conn.prepareStatement("INSERT INTO EMPLOYEE_ZIP (CreateTime, ZipPath) VALUES ('" + cd.getTime() + "', '"+file.getAbsolutePath() + "')");
			
			rs = pstmt.executeQuery();
			
			System.out.println("数据库操作成功!");
			
		}catch(SQLException e){
			System.out.println("数据库操作异常!" + e.getMessage());
		}
		finally{
			try{
				if(rs!= null){rs.close();}
				if(pstmt!= null){pstmt.close();}
				if(conn != null && !conn.isClosed()){conn.close();}
			}catch(SQLException e){
				e.printStackTrace();
			}
			
		}
	}
	
	public static void main(String[] args) {
		EmloyeeHandle emloyeeHandle = new EmloyeeHandle();

		ZipUtil zu = new ZipUtil();
		emloyeeHandle.readXMLFile("staff_.zip");
		emloyeeHandle.writeToTxtFile();

		String directory = System.getProperty("user.dir");
		try {
			zu.zip(directory + "\\staff_select");// 要压缩的文件夹
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		emloyeeHandle.save();
	}
}



 3、工具util类:

package nju.syy.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Map;

public class OralceConnect {

	/**
	 * @param args
	 */
	public Connection connectToOracle() {
		
		PropertiesUtil pu = new PropertiesUtil();
		Map<String, String> propertiesMap = pu
				.readJdbcProperties("jdbc.properties");
		
		Connection conn = null;  //Connection数据库连接对象
		
		try {
			// 注册驱动
//			Class.forName(propertiesMap.get("driverClassName"));
			Class.forName("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection(propertiesMap.get("url"), propertiesMap.get("userName"), propertiesMap.get("password"));
			
			return conn;

		} catch (ClassNotFoundException e) {
			System.out.println("驱动类没有找到!");
		} catch(SQLException e){
			System.out.println("获得Connection数据库连接对象出错!!");
		 e.printStackTrace(); 
		}
		
		return conn;
	}
}


 

package nju.syy.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class PropertiesUtil {

	public Properties parserProperties(String propertiesFileName) {

		FileInputStream filein;
		Properties p = new Properties();
		try {
			filein = new FileInputStream(propertiesFileName);
			try {
				p.load(filein);
				return p;
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
		return p;
	}
	/**
	 * 读提txt文件的配置文档
	 * @param propertiesFileName
	 * @return
	 */
	public Map<String, String> readTxtFormatProperties(String propertiesFileName) {

		Map<String, String> propertiesMap = new HashMap<String, String>();

		Properties p = parserProperties(propertiesFileName);
		
		propertiesMap.put("origName", p.getProperty("origName"));
		propertiesMap.put("targName", p.getProperty("targName"));
		propertiesMap.put("minAge", p.getProperty("minAge"));
		propertiesMap.put("maxAge", p.getProperty("maxAge"));
		propertiesMap.put("gender", p.getProperty("gender"));

		return propertiesMap;
	}
	
	/**
	 * 读jdbc的配置文档
	 * @param propertiesFileName
	 * @return
	 */
	public Map<String, String> readJdbcProperties(String propertiesFileName) {

		Map<String, String> propertiesMap = new HashMap<String, String>();

		Properties p = parserProperties(propertiesFileName);
		
		propertiesMap.put("driverClassName", p.getProperty("driverClassName"));
		propertiesMap.put("url", p.getProperty("url"));
		propertiesMap.put("userName", p.getProperty("userName"));
		propertiesMap.put("password", p.getProperty("password"));
		propertiesMap.put("maxSize", p.getProperty("maxSize"));
		propertiesMap.put("minSize", p.getProperty("minSize"));
		propertiesMap.put("idleTimeout", p.getProperty("idleTimeout"));
		propertiesMap.put("checkOutTimeout", p.getProperty("checkOutTimeout"));
		propertiesMap.put("testsql", p.getProperty("testsql"));
		propertiesMap.put("checkAfterUsed", p.getProperty("checkAfterUsed"));
		propertiesMap.put("isSameRM", p.getProperty("isSameRM"));
		
		return propertiesMap;
	}
	
	public static void main(String[] arg){
		PropertiesUtil pu = new PropertiesUtil();
		Map<String, String> propertiesMap = pu
				.readJdbcProperties("jdbc.properties");
		System.out.println(propertiesMap.get("driverClassName"));
	}
}


 

package nju.syy.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import nju.syy.service.EmloyeeHandle;
import nju.syy.vo.EmployeeBean;


public class TxtUtil {

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void writeToTxtFile(ArrayList<EmployeeBean> employeeList) {
		try {

			EmloyeeHandle eh = new EmloyeeHandle();
			Map<String, LinkedList<EmployeeBean>> employeeGroupMap = eh
					.grouped(employeeList);
			
			Map<String, Integer> countMap = eh.getCountMap();
			
			for (Iterator iterator = employeeGroupMap.entrySet().iterator(); iterator
					.hasNext();) {

				Map.Entry entry = (Map.Entry) iterator.next();
				String key = (String) entry.getKey();
				LinkedList<EmployeeBean> ebList = (LinkedList<EmployeeBean>) entry
						.getValue();

				String directory = System.getProperty("user.dir");
				File staff_select_File = new File(directory + "\\staff_select");
				staff_select_File.mkdir();
				
				BufferedWriter bw = new BufferedWriter(new FileWriter(new File(
						staff_select_File.getCanonicalPath() + "\\" + key + ".txt")));
				StringBuffer bf = new StringBuffer();

				bf.append("#Department:" + key + "(" + countMap.get(key) + " : " + ebList.size() + ")" + "\r\n" + "\r\n");

				for (Iterator i = ebList.iterator(); i.hasNext();) {

					EmployeeBean eb = (EmployeeBean) i.next();
					String gourp = eb.getGroup();
					String[] strs = gourp.split(" ");
					String groupNo = strs[strs.length - 1];
					
					bf.append("deptGroup=" + groupNo + "\r\n");
					bf.append("staffNo=" + eb.getNumber() + "\r\n");
					bf.append("staffName=" + eb.getName() + "\r\n");
					bf.append("staffGender=" + eb.getGender() + "\r\n");
					bf.append("staffAge=" + eb.getAge() + "\r\n");
					bf.append("phoneNumber=" + eb.getPhoneno() + "\r\n");
					bf.append("workExp=" + eb.getWorkExperience()
							+ " Year(Years)" + "\r\n"
							+ "#-------------------------" + "\r\n");
				}
				bw.append(bf);
				bw.flush();
				bw.close();
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

	}

	public void zipFile(String zipFileName) throws IOException {

		// 1. 创建zip输出流
		ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(
				zipFileName));

		// 2. 创建并设置条目信息
		File f = new File("javaio.bmp");
		ZipEntry ze = new ZipEntry(f.getName());
		ze.setComment("Hello, Zip");
		ze.setSize(f.length());
		ze.setTime(f.lastModified());
		
		// 3. 添加条目到输出流
		zos.putNextEntry(ze);

		// 4. 输出
		FileInputStream fin = new FileInputStream(f);
		byte[] buffer = new byte[4096];
		int len;
		while ((len = fin.read(buffer)) != -1) {
			zos.write(buffer, 0, len);
		}
		fin.close();

		// 5. 关闭流
		zos.close();
	}

}


 

package nju.syy.util;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;

import nju.syy.vo.EmployeeBean;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;


/**
 * 
 * @author hongliang.dinghl Dom4j 生成XML文档与解析XML文档
 */
public class XMLUtil {

	public ArrayList<EmployeeBean> parserXml(InputStream inputStream) {
		
		EmployeeBean employeeBean = new EmployeeBean();

		SAXReader saxReader = new SAXReader();
		try {
			
			Document document = saxReader.read(inputStream);
			Element employees = document.getRootElement();
			
			for (Iterator<?> i = employees.elementIterator(); i.hasNext();) {
				EmployeeBean eb = new EmployeeBean();
				Element employee = (Element) i.next();

				// 取employee的姓名属性
				eb.setName(employee.attributeValue("name"));
				
				// 取employee的编号属性
				eb.setNumber(employee.attributeValue("number"));
				
				Iterator<?> j = employee.elementIterator();

				Element publics = (Element) j.next();

				// 取"部门"元素
				Iterator<?> i_publics = publics.elementIterator();
				Element department = (Element) i_publics.next();
				eb.setDepartment(department.getTextTrim());
				
				// 取"小组"元素
				Element group = (Element) i_publics.next();
				eb.setGroup(group.getTextTrim());
				
				// -----------------------------------------------------------------
				// 取"个人信息"元素
				Element individuals = (Element) j.next();

				// 取"性别"元素
				Iterator<?> i_individuals = individuals.elementIterator();
				i_individuals.next();
				i_individuals.next();
				Element gender = (Element) i_individuals.next();
				eb.setGender(gender.getTextTrim());
				
				// 取"年龄"元素
				Element age = (Element) i_individuals.next();
				eb.setAge(age.getTextTrim());

				// 取"电话号码"元素
				Element phoneno = (Element) i_individuals.next();
				eb.setPhoneno(phoneno.getTextTrim());

				// 取"工作经验"元素
				Element workexperience = (Element) i_individuals.next();
				eb.setWorkExperience(workexperience.getTextTrim());

				employeeBean.getEmployeeList().add(eb);
			}

		} catch (DocumentException e) {
			System.out.println(e.getMessage());
		}
//		System.out.println(employeeBean.getEmployeeList().size());
		return employeeBean.getEmployeeList();
	}

}


 

package nju.syy.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import nju.syy.vo.EmployeeBean;


public class ZipUtil {

	ArrayList<EmployeeBean> employeeList = new ArrayList<EmployeeBean>();
	XMLUtil xu = new XMLUtil();

	/**
	 * 依次读取压缩包中各文件内容
	 * 
	 * @param file
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<EmployeeBean> unZipFile(String zipFileName) {

		try {
			// 由指定的File对象打开供阅读的ZIP文件
			ZipFile zip = new ZipFile(new File(zipFileName));

			// 获取zip文件中的各条目(子文件)
			Enumeration<ZipEntry> entries = (Enumeration<ZipEntry>) zip
					.entries();

			// 依次访问各条目
			while (entries.hasMoreElements()) {
				
				ZipEntry ze = (ZipEntry) entries.nextElement();

				employeeList = xu.parserXml(zip.getInputStream(ze));
			}
		} catch (ZipException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return employeeList;
	}

	/**
	 * 依次将txt文件压缩到staff_select.zip文件中
	 * 
	 * @param file
	 */
	public void zip(String inputFileName) throws Exception {
		String directory = System.getProperty("user.dir");
		String zipFileName = directory + "\\staff_select.zip"; // 打包后文件名字
//		System.out.println(zipFileName);
		zip(zipFileName, new File(inputFileName));
	}

	private void zip(String zipFileName, File inputFile) throws Exception {
		ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
				zipFileName));
		zip(out, inputFile, "");
		out.close();
	}

	private void zip(ZipOutputStream out, File f, String base) throws Exception {
		
		if (f.isDirectory()) {
			File[] fl = f.listFiles();
			out.putNextEntry(new ZipEntry(base + "/"));
			base = base.length() == 0 ? "" : base + "/";
			for (int i = 0; i < fl.length; i++) {
				zip(out, fl[i], base + fl[i].getName());
			}
		} else {
			out.putNextEntry(new ZipEntry(base));
			FileInputStream in = new FileInputStream(f);
			int b;
			while ((b = in.read()) != -1) {
				out.write(b);
			}
			in.close();
		}
	}
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值