目录
一.制造假数据:生成假姓名并写到文件当中
1.把网址上面爬到到一行行数据拼接成字符串的具体步骤? 2.正则表达式:需要表示字符时一定需要把字符用[]包裹吗? 3.有什么方法可以表示后面跟着逗号或者句号? 4.又有哪些方法表示只取前面的那部分? 5.如何在截取字符串中符合正则表达式的字串的时候只截取分组? 6.如何把集合中的部分数据取出删除(快速方法)? 7.把数组变成List再使用加入集合(快速方法)? 8.如何使自己创造的集合数据(如姓名)不重复?
public class Demo301 {
final static String FILE_STRING = "D:\\IDEACode\\demo1\\JAVA基础\\src\\Day30_IOPractice\\MyText\\name.txt";
final static String WEB_STRING1 = "https://hanyu.baidu.com/shici/detail?pid=0b2f26d4c0ddb3ee693fdb1137ee1b0d&from=kg0";
final static String WEB_STRING2 = "http://www.haoming8.cn/baobao/10881.html";
final static String WEB_STRING3 = "http://www.haoming8.cn/baobao/7641.html";
public static void main(String[] args) throws IOException {
//获取数据网址数据,方法一:爬取数据:把网址上面爬到到一行行数据拼接成字符串
System.out.println("1.重要步骤有:获取URL对象,连接网址");
System.out.println("读取数据,通过连接获得输入流->转换流->字符缓冲流");
String familyNameStr = webCrawler(WEB_STRING1);
String boyNameStr = webCrawler(WEB_STRING2);
String girlNameStr = webCrawler(WEB_STRING3);
System.out.println("2.字符不一定非要用[]括起来,直接写上去即可");
System.out.println("3.可以用(,|。)或者[,。]去代表后面跟的字符(虽然搜索范围变大很多)");
System.out.println(" 4.?<=忽略前面的内容,?=忽略掉后面的内容,也可以分组取出用()框起来的部分");
System.out.println("方法中传入第三个参数代表取第几组:可以去除不需要的组");
System.out.println("5.在matcher匹配到字符串之后,使用group方法获取特定组的数据");
ArrayList<String> familyNameTempList = getData(familyNameStr, "(....)[,。]", 1);
ArrayList<String> boyNameTempList = getData(boyNameStr, "(<p>)((..、)*.{2}。)(</p>)", 2);
ArrayList<String> girlNameTempList = getData(girlNameStr, "(<p>)((.. )*.{2})(</p>)", 2);
//处理数据
ArrayList<String> familyNameList = new ArrayList<>();
ArrayList<String> boyNameList = new ArrayList<>();
ArrayList<String> girlNameList = new ArrayList<>();
for (String s : familyNameTempList)
for (int i = 0; i < s.length(); i++)
familyNameList.add(s.charAt(i) + "");
System.out.println("6.IDEA提示方法:使用subList方法分离数据,然后使用clear方法清除这一部分数据");
familyNameList.subList(familyNameList.size() - 4, familyNameList.size()).clear();
for (String[] strings : boyNameTempList.stream().map(s -> s.replace("。", ""))
.map(s -> s.split("、")).collect(Collectors.toList()))
boyNameList.addAll(Arrays.asList(strings));
System.out.println("IDEA提示方法:使用Arrays工具类的asList把数组变成集合,再使用List中的addAll方法全部加入");
for (String[] strings : girlNameTempList.stream().map(s -> s.split("\\s")).collect(Collectors.toList()))
girlNameList.addAll(Arrays.asList(strings));
//生成数据
System.out.println("8.姓名不重复怎么整??使用HashSet作为姓名容器即可");
ArrayList<String> arrayList = getInfos(familyNameList, boyNameList, girlNameList, 20, 20);
Collections.shuffle(arrayList);
BufferedWriter bf = new BufferedWriter(new FileWriter(FILE_STRING));
for (String s : arrayList) {
bf.write(s);
bf.newLine();
}
bf.close();
}
//方法一:爬取数据:把网址上面爬到到一行行数据拼接成字符串
public static String webCrawler(String net) throws IOException {
StringBuilder sb = new StringBuilder();
//1.获取URL对象,连接网址
URL url = new URL(net);
URLConnection conn = url.openConnection();
//1.读取数据,通过连接获得输入流->转换流->字符缓冲流
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
br.close();
return sb.toString();
}
//方法二:初步处理爬取到的数据:得到大部分有用的数据
private static ArrayList<String> getData(String str, String regex, int index) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
//5.在matcher匹配到字符串之后,使用group方法获取特定组的数据
ArrayList<String> arrayList = new ArrayList<>();
while (matcher.find()) arrayList.add(matcher.group(index));
return arrayList;
}
//方法三:传入男生个数,女生个数,获取随机男生女生信息:随机姓名-性别-随机年龄
public static ArrayList<String> getInfos(ArrayList<String> familyNameList, ArrayList<String> boyNameList, ArrayList<String> girlNameList,
int boyCount, int girlCount) {
Random random = new Random();
ArrayList<String> arrayList = new ArrayList<>();
//使用HashSet使数据不重复
HashSet<String> boyHashSet = new HashSet<>();
HashSet<String> girlHashSet = new HashSet<>();
//这里原本是写了一个拼接姓名方法,简化了
while (boyHashSet.size() < boyCount)
boyHashSet.add(familyNameList.get(random.nextInt(familyNameList.size())) + boyNameList.get(random.nextInt(boyNameList.size())));
while (girlHashSet.size() < girlCount)
girlHashSet.add(familyNameList.get(random.nextInt(familyNameList.size())) + girlNameList.get(random.nextInt(girlNameList.size())));
//能写一行就写一行了,不用再去定义SJ一个一个加,也简化了
for (String s : boyHashSet) arrayList.add(s + "-男-" + random.nextInt(16, 28));
for (String s : girlHashSet) arrayList.add(s + "-女-" + random.nextInt(16, 28));
return arrayList;
}
}
二.使用Hutool工具一次性获取网页内容
public class Demo302 {
public static void main(String[] args) {
System.out.println("1.使用HttpUtil的get方法获取所有的网页源代码");
String str = HttpUtil.get(Demo301.WEB_STRING1);
System.out.println("2.使用ReUtil中的findAll方法传入regex,string,组号即可获取相应的字符串集合");
List<String> familyNameTempList = ReUtil.findAll("(....)[,。]",str,1);
System.out.println("3.糊涂包生成的文件会相对于class文件生成:存在out文件中,需要补全路径");
FileUtil.writeLines(familyNameTempList,Demo301.FILE_STRING,"UTF-8");
}
}
三.带权重的随机点名器
具体实现步骤使怎样的呢?
//准备数据部分:每行数据加-1
public class Demo303 {
final static String FILE_STRING2 = "D:\\IDEACode\\demo1\\JAVA基础\\src\\Day30_IOPractice\\MyText\\name2.txt";
public static void main(String[] args) throws IOException{
File file = new File(Demo301.FILE_STRING);
File file2 = new File(FILE_STRING2);
List<String> list = new ArrayList<>();
FileUtil.readUtf8Lines(file, list);
list = list.stream().map(s -> s + "-1").collect(Collectors.toList());
FileUtil.writeUtf8Lines(list, file2);
}
}
public class Demo304 {
public static void main(String[] args) {
File file = new File(Demo303.FILE_STRING2);
List<String> list = new ArrayList<>();
FileUtil.readUtf8Lines(file, list);
System.out.println("1.用学生类接收不同类型的数据");
List<Student> students = new ArrayList<>();
for (String[] strings : list.stream().map(s -> s.split("-")).collect(Collectors.toList()))
students.add(new Student(strings[0], strings[1], Integer.parseInt(strings[2]), Double.parseDouble(strings[3])));
System.out.println("2.计算权重总和");
double weight = 0;
for (Student student : students)
weight += student.getWeight();
System.out.println("3.计算每一个人的实际比重");
double[] arr = new double[list.size()];
for (int i = 0; i < students.size(); i++)
arr[i] = students.get(i).getWeight() / weight;
System.out.println("4.计算每一个人的权重范围:为了更方便的使用随机生成的数据");
for (int i = 1; i < arr.length; i++)
arr[i] = arr[i] + arr[i - 1];
System.out.println("5.随机抽取,使用二分查找搜索数据");
double num = Math.random();
int index = -Arrays.binarySearch(arr, num) - 1;
System.out.println("6.修改数据");
Student student = students.get(index);
student.setWeight(student.getWeight() / 2);
System.out.println("7.重新写文件,这里的toString方法已经转成对应的格式");
list = students.stream().map(Student::toString).collect(Collectors.toList());
FileUtil.writeUtf8Lines(list,file);
}
}
四.properties配置文件
1.properties配置文件的两个特点? 1.后缀名为properties 2.以键值对的形式存储 2.在Java中,Properties是一个什么样的类呢? 为Map的一个实现类,继承于HashTable 3.Properties类里面有什么特别的方法? 里面有特有方法store()可以把数据按照键值对的形式写到配置文件中,load()能够读取数据转换成集合 4.定义Properties时需要限定泛型吗? 5. 使用store方法与load方法时分别需要传入什么参数?
public class Demo305 {
final static String File_String = "D:\\IDEACode\\demo1\\JAVA基础\\src\\Day30_IOPractice\\MyProperties\\a.properties";
public static void main(String[] args) throws IOException {
System.out.println("4.定义Properties不需要说明泛型,可以添加任意数据类型,默认为Object,一般只添加字符串");
Properties properties = new Properties();
properties.put("aaa","111");
properties.put("bbb","222");
properties.put("ccc","333");
properties.put("ddd","444");
System.out.println("5.使用store方法时需要传入字符输出流与备注,使用load方法时需要传入字符输入流");
properties.store(new FileWriter(File_String), "myProperties");
properties.clear();
properties.load(new FileReader(File_String));
System.out.println(properties);
}
}
五.拼图小游戏完善
新增的代码(按序号展示)
14.加入存档读档功能:新增JM与JB(定义在最外层的static代码中),吧JB全部加上监听
private static JMenuItem saveItem1, saveItem2, saveItem3, loadItem1, loadItem2, loadItem3;
private static JMenu saveMenu, loadMenu;
saveMenu = new JMenu("存档");
loadMenu = new JMenu("读档");
saveItem1 = new JMenuItem("存档1(空)");
saveItem2 = new JMenuItem("存档2(空)");
saveItem3 = new JMenuItem("存档3(空)");
loadItem1 = new JMenuItem("读档1(空)");
loadItem2 = new JMenuItem("读档2(空)");
loadItem3 = new JMenuItem("读档3(空)");
functionMenu.add(saveMenu);
functionMenu.add(loadMenu);
saveMenu.add(saveItem1);
saveMenu.add(saveItem2);
saveMenu.add(saveItem3);
loadMenu.add(loadItem1);
loadMenu.add(loadItem2);
loadMenu.add(loadItem3);
saveItem1.addActionListener(this);
saveItem2.addActionListener(this);
saveItem3.addActionListener(this);
loadItem1.addActionListener(this);
loadItem2.addActionListener(this);
loadItem3.addActionListener(this);
15.存档需要存储数据:把数据序列化:需要路径,步数,空白位置,图片位置,包装成一个类:并实现Serializable接口
public class GameInfo implements Serializable {
@Serial
private static final long serialVersionUID = 7497887490544158029L;
private int[][] data;
private int x,y;
private String path;
private int step;
public GameInfo() {
}
public GameInfo(int[][] data, int x, int y, String path, int step) {
this.data = data;
this.x = x;
this.y = y;
this.path = path;
this.step = step;
}
public int[][] getData() {
return data;
}
public void setData(int[][] data) {
this.data = data;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public String toString() {
return "GameInfo{data = " + data + ", x = " + x + ", y = " + y + ", path = " + path + ", step = " + step + "}";
}
}
16.完成存档读档功能,需要注意存档文件的名字,修改界面上的存读档文字
//ActionListener
@Override
public void actionPerformed(ActionEvent e) {
Object o = e.getSource();
if (o == saveItem1 || o == saveItem2 || o == saveItem3) {
System.out.println("存档");
//要写什么数据呢?1.图片路径2.xy3.数组4.步数
//要如何根据点击的组件建立不同的文件呢?使用组件的getText方法
JMenuItem jmi = (JMenuItem) o;
String text = jmi.getText();
//下面的语句只能trycatch:父类中方法中没有抛出异常,子类也不行
try (ObjectOutputStream oos = new ObjectOutputStream
(new FileOutputStream(FILE_DATA + text.charAt(2) + ".sav"))) {
GameInfo gameInfo = new GameInfo(data, x, y, path, count);
oos.writeObject(gameInfo);
} catch (IOException ioException) {
ioException.printStackTrace();
}
jmi.setText(text.substring(0, 3) + "(" + count + "步)");
//读档信息怎么设置?通过JMenu通过下标获取组件
loadMenu.getItem(text.charAt(2) - '1').setText(text.substring(0, 3) + "(" + count + "步)");
} else if (o == loadItem1 || o == loadItem2 || o == loadItem3) {
//读档和上面的流程一样,读取数据然后initImage就可以咯,需要改一改初始化变量的时候,JItem的显示(有存档但是打开的时候 不显示)
System.out.println("读档");
JMenuItem jmi = (JMenuItem) o;
String text = jmi.getText();
try (ObjectInputStream ois = new ObjectInputStream
(new FileInputStream(FILE_DATA + text.charAt(2) + ".sav"))) {
GameInfo gameInfo = (GameInfo) ois.readObject();
data = gameInfo.getData();
path = gameInfo.getPath();
x = gameInfo.getX();
y = gameInfo.getY();
count = gameInfo.getStep();
initImage();
} catch (IOException | ClassNotFoundException ioException) {
ioException.printStackTrace();
}
17.完成根据存档初始化JMenu
//根据存档显示不同的存档与读档数据
File file = new File(FILE_DATA);
File[] files = file.listFiles();
for (File save : files) {
try (ObjectInputStream ois = new ObjectInputStream
(new FileInputStream(save))) {
GameInfo gameInfo = (GameInfo) ois.readObject();
int step = gameInfo.getStep();
saveMenu.getItem(save.getName().charAt(0) - '1').setText("存档" + save.getName().charAt(0) + "(" + step + "步)");
loadMenu.getItem(save.getName().charAt(0) - '1').setText("存档" + save.getName().charAt(0) + "(" + step + "步)");
} catch (IOException | ClassNotFoundException ioException) {
ioException.printStackTrace();
}
}
18.完成配置文件功能,可以修改properties中的文件去更换图片
//公众号
accountItem.addActionListener(e -> {
System.out.println("弹出公众号");
//创建弹框
JDialog dialog = new JDialog();
//读取配置文件来建立公众号图片
Properties properties = new Properties();
try {
properties.load(new FileReader(FILE_PROPERTIES));
} catch (IOException ioException) {
ioException.printStackTrace();
}
JLabel label = new JLabel(new ImageIcon((String) properties.get("account")));
label.setBounds(0, 0, 258, 258);
dialog.getContentPane().add(label);
dialog.setSize(344, 344);
dialog.setAlwaysOnTop(true);
dialog.setLocationRelativeTo(null);
//弹框不关闭无法设置下面的界面
dialog.setModal(true);
dialog.setVisible(true);
});