说明:本文为我在做课设时遇到的问题汇总,解决方法多数来自网络,因深感到处搜索解决方法不易,所以做成汇总。因搜索时没有记录每个答案来源网站,如有侵权,请联系我。感谢无私分享的每一个人。

题目:设计散列表实现电话号码查找系统

基本要求:

(1)设每个记录有下列数据项:电话号码、用户名、地址;

(2)从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表;

(3)查找并显示给定电话号码的记录;

(4)查找并显示给定用户名的记录。

(5)尝试不同类型处理冲突的方法,考察平均查找长度的变化。

目录

界面设计:

Q1: 如何为界面添加背景?将左上角Java图标改为自定义logo?

Q2:如何根据xy坐标像素位置自定义组件布局?

Q3:如何让窗口在电脑屏幕居中?

Q4:将鼠标变成小手的代码?

Q5:如何添加背景音乐?

Q6:如何构建表格并使表格能够实时获取散列表更新内容并刷新?

Q7:如何右击表格某行删除?

Q8:切换界面时,如何对上一个界面中的散列表进行操作?

Q9:为什么文本框输入值比较会出现问题?

Q10:如何在删除或查找成功后显示自动关闭的提示弹窗?

算法设计

Q1:除留取余法和除数的获取?

Q2:扩容条件?如何扩容?

Q3:解决冲突的方法有哪些?

Q4:如何知道删除成功还是失败?

Q5:其他问题?


界面设计:

Q1: 如何为界面添加背景?将左上角Java图标改为自定义logo?

A1:在网络搜索到以下代码,可建立如下bpic框架类,框架中参数可按需修改。

public class bpic extends JFrame {int width,height;String p1,p2;JPanel  contentPane;Image im;public bpic(String title,String p1,String p2) {super(title);setResizable(false);//设置窗口为不可缩放setVisible(true);//设置为窗口可见setDefaultCloseOperation(3);//设置用户在此窗体上发起 "close" 时默认执行的操作。contentPane = new JPanel(); //指定容器setContentPane(contentPane);//设置 contentPane 属性contentPane.setOpaque(false);//设置面板背景为透明(这一步很重要)init(p1,p2);}public void init(String p1,String p2) {/** 设置窗口图标*/ImageIcon ig = new ImageIcon(p1);//这里放上你要设置图标图片im = ig.getImage();setIconImage(im);/** 设置窗口背景图片*/ImageIcon img = new ImageIcon(p2);//要设置的背景图片JLabel imgLabel = new JLabel(img);//将背景图放在标签里。this.getLayeredPane().add(imgLabel, new Integer(Integer.MIN_VALUE));//将背景标签添加到jframe的LayeredPane面板里。imgLabel.setBounds(0, 0, img.getIconWidth(), img.getIconHeight());}}

调用代码:

bpic frame = new bpic("电话号码查询系统", //窗口标题
"D:\\Projects\\teleSearch\\图片\\logo.png", //logo图片地址
"D:\\Projects\\teleSearch\\图片\\首页.jpg"); //背景图片地址

效果展示:

Q2:如何根据xy坐标像素位置自定义组件布局?

A2:需要先将窗口frame布局设置为空

frame.setLayout(null); //布局方式设为空,可以根据像素坐标自由确定组件布局

组件再调用setBounds即可

picStart.setBounds(380, 50, 330, 330);
frame.add(picStart);//对picStart进行了一系列其他设置代码之后
//一定要repaint(),不然不显示组件
picStart.repaint();

Q3:如何让窗口在电脑屏幕居中?

A3:

//设置居中Toolkit tk = frame.getToolkit();Dimension screenSize = tk.getScreenSize();frame.setBounds((screenSize.width - 1100) / 2, (screenSize.height - 800) / 2,1100, 800);

Q4:将鼠标变成小手的代码?

A4:

picStart.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

Q5:如何添加背景音乐?

A5:在网络搜索到如下代码

/*** Description: 简易音频播放器(只支持AU,RA,WAV)*                在不使用JMF的情况下快速实现音频播放*/
import javax.sound.sampled.*;
import java.io.*;
import java.util.concurrent.TimeUnit;public class Sound {private String musicPath; //音频文件private volatile boolean run = true;  //记录音频是否播放private Thread mainThread;   //播放音频的任务线程private AudioInputStream audioStream;private AudioFormat audioFormat;private SourceDataLine sourceDataLine;public Sound(String musicPath) {this.musicPath = musicPath;prefetch();}//数据准备private void prefetch(){try{//获取音频输入流audioStream = AudioSystem.getAudioInputStream(new File(musicPath));//获取音频的编码对象audioFormat = audioStream.getFormat();//包装音频信息DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,audioFormat,AudioSystem.NOT_SPECIFIED);//使用包装音频信息后的Info类创建源数据行,充当混频器的源sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);sourceDataLine.open(audioFormat);sourceDataLine.start();}catch(UnsupportedAudioFileException ex){ex.printStackTrace();}catch(LineUnavailableException ex){ex.printStackTrace();}catch(IOException ex){ex.printStackTrace();}}//析构函数:关闭音频读取流和数据行protected void finalize() throws Throwable{super.finalize();sourceDataLine.drain();sourceDataLine.close();audioStream.close();}//播放音频:通过loop参数设置是否循环播放private void playMusic(boolean loop)throws InterruptedException {try{if(loop){while(true){playMusic();}}else{playMusic();//清空数据行并关闭sourceDataLine.drain();sourceDataLine.close();audioStream.close();}}catch(IOException ex){ex.printStackTrace();}}private void playMusic(){try{synchronized(this){run = true;}//通过数据行读取音频数据流,发送到混音器;//数据流传输过程:AudioInputStream -> SourceDataLine;audioStream = AudioSystem.getAudioInputStream(new File(musicPath));int count;byte tempBuff[] = new byte[1024];while((count = audioStream.read(tempBuff,0,tempBuff.length)) != -1){synchronized(this){while(!run)wait();}sourceDataLine.write(tempBuff,0,count);}}catch(UnsupportedAudioFileException ex){ex.printStackTrace();}catch(IOException ex){ex.printStackTrace();}catch(InterruptedException ex){ex.printStackTrace();}}//暂停播放音频private void stopMusic(){synchronized(this){run = false;notifyAll();}}//继续播放音乐private void continueMusic(){synchronized(this){run = true;notifyAll();}}//外部调用控制方法:生成音频主线程;public void start(boolean loop){mainThread = new Thread(new Runnable(){public void run(){try {playMusic(loop);} catch (InterruptedException e) {e.printStackTrace();}}});mainThread.start();}//外部调用控制方法:暂停音频线程public void stop(){new Thread(new Runnable(){public void run(){stopMusic();}}).start();}//外部调用控制方法:继续音频线程public void continues(){new Thread(new Runnable(){public void run(){continueMusic();}}).start();}
}

调用代码:

Sound player = new Sound("D:/Projects/teleSearch/Canon.wav"); //音频地址
player.start(true); //调用start方法,开始线程
//因为我的背景音乐是开机bgm,切换界面后将不再进行
//故在鼠标监听器点击strat图标的代码段中,要终止运行
//终止代码
player.stop();

Q6:如何构建表格并使表格能够实时获取散列表更新内容并刷新?

A6:在网络学习后,建立如下适合本系统的表格

//定义全局变量,便于在鼠标监听器中进行刷新修改
private DefaultTableModel model1,model2;//全局变量table,并且设置table为不可修改(但可以选中)private JTable table = new JTable(){public boolean isCellEditable(int rowIndex, int ColIndex){return false;}};
//全局变量,线程计时时间
//用于线程计时final long timeInterval = 2000;//表格初步建立//设置表格标题String[] header1 = {"序号","用户名", "电话号码","地址"};String[] header2 = {"序号","电话号码", "用户名","地址"};//这里data为空,因为主要内容的获取在鼠标监听获取事件后进行Object[][] data = {};// create a table modelmodel1 = new DefaultTableModel(data, header1);model2 = new DefaultTableModel(data, header2);// create a JTable objecttable.setModel(model1);table.getTableHeader().setReorderingAllowed(false);   //不可整列移动table.getTableHeader().setResizingAllowed(false);   //不可拉动表格//内容设置居中DefaultTableCellRenderer r = new DefaultTableCellRenderer();r.setHorizontalAlignment(JLabel.CENTER);table.setDefaultRenderer(Object.class,r);//设置表格风格table.setGridColor(Color.BLACK);table.getTableHeader().setFont(font2);table.setFont(font1);//设置行高table.setRowHeight(40);//设置列宽table.getColumnModel().getColumn(0).setPreferredWidth(70);table.getColumnModel().getColumn(1).setPreferredWidth(160);table.getColumnModel().getColumn(2).setPreferredWidth(160);table.getColumnModel().getColumn(3).setPreferredWidth(600);// must do: bind a JTable object to a JScrollPane object, otherwise the header of the table will not be displayed in the JPanel.JScrollPane jScrollPane = new JScrollPane();// key, crucial!jScrollPane.setViewportView(table);jScrollPane.setBounds(60, 85, 950, 600);jScrollPane.repaint();frame.add(jScrollPane);//获取hash表内容并更新至表格
//以下内容在鼠标监听中
//加入多线程计时器
Runnable runnable1 = new Runnable() {public void run() {while (isName) { //一般的线程这里是true,因为本系统有用户名和电话号码两种操作选        项,所以需要进行判断,否则两套线程一起运行会出错,具体情况具体分析// 要运行的任务代码//建立一个数组,接收hash表中内容//可以在hash表中建立一个返回值为数组的方法,在此不多做解释//例如这个数组String[][] dataName1 = new String[lenName1][4];//设置给model1(model2同理)model1 = new DefaultTableModel(dataName1,header1);//改变表格内容table.setModel(model1);//设置行高table.setRowHeight(40);//设置列宽table.getColumnModel().getColumn(0).setPreferredWidth(70);table.getColumnModel().getColumn(1).setPreferredWidth(160);                               table.getColumnModel().getColumn(2).setPreferredWidth(160);table.getColumnModel().getColumn(3).setPreferredWidth(600);table.repaint();// ------- ends heretry {// sleep():同步延迟数据,并且会阻塞线程Thread.sleep(timeInterval);} catch (InterruptedException e) {e.printStackTrace();}}}};//创建定时器Thread thread = new Thread(runnable1);//开始执行thread.start();

效果:

Q7:如何右击表格某行删除?

A7:构建如下方法并调用

由于表格每一秒刷新一次,刷新时若尝试获取表格内容会报错,此错误未解决,但不影响使用,只要在一秒内点击删除就可以啦

//创建一个JPopupMenuprivate void createPopupMenu() {m_popupMenu = new JPopupMenu();JMenuItem delMenItem = new JMenuItem();delMenItem.setText("  删除  ");delMenItem.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(java.awt.event.ActionEvent evt) {//该操作需要做的事int row = table.getSelectedRow();//获取所选中行的数值//获取某行列元素值的方法为//table.getValueAt(row,1).toString();//row为所选中行,1为第二列(从0开始计算)//获取值之后,作为参数传入,调用删除方法即可             }});m_popupMenu.add(delMenItem);}private void tableMouseClicked(java.awt.event.MouseEvent evt) {mouseRightButtonClick(evt);}//鼠标右键点击事件private void mouseRightButtonClick(java.awt.event.MouseEvent evt) {//判断是否为鼠标的BUTTON3按钮,BUTTON3为鼠标右键if (evt.getButton() == java.awt.event.MouseEvent.BUTTON3) {//通过点击位置找到点击为表格中的行int focusedRowIndex = table.rowAtPoint(evt.getPoint());if (focusedRowIndex == -1) {return;}//将表格所选项设为当前右键点击的行table.setRowSelectionInterval(focusedRowIndex, focusedRowIndex);//弹出菜单m_popupMenu.show(table, evt.getX(), evt.getY());}}
//调用方法,加入在建立界面的方法中
//右键删除createPopupMenu();table.addMouseListener(new java.awt.event.MouseAdapter() {public void mouseClicked(java.awt.event.MouseEvent evt) {tableMouseClicked(evt);}});

Q8:切换界面时,如何对上一个界面中的散列表进行操作?

A8:将散列表作为全局变量,并作为参数传入

Q9:为什么文本框输入值比较会出现问题?

A9:textSearch.getText() == "aaa"是无法比较的,字符串的比较需要用textSearch.getText() .equals("aaa")

Q10:如何在删除或查找成功后显示自动关闭的提示弹窗?

A10:

先写一个悬浮窗口

//一个悬浮窗口class Fail extends JDialog{public Fail (){Font font2 = new Font("宋体",Font.BOLD,25);setUndecorated (true);setBackground(Color.white);setSize (200, 70);setLocationRelativeTo (null);setLayout (new BorderLayout ());JLabel label =new JLabel ("用户不存在:(");label.setFont(font2);label.setHorizontalAlignment (JLabel.CENTER);add (label,BorderLayout.CENTER);}}

在删除失败的条件下调用显示

//显示删除失败弹窗final Fail ff = new Fail();ff.setVisible (true);// 在swing中调用线程,必须如下:SwingUtilities.invokeLater (new Runnable(){@Overridepublic void run (){try{Thread.sleep (1000);}catch (InterruptedException e1){e1.printStackTrace();}ff.dispose ();}});}//自动关闭窗口windowClear.dispose();

算法设计

Q1:除留取余法和除数的获取?

A1:

//除留取余法,获取哈希码public int getHashCode(String name){int sum = 0;for(int i = 0; i < name.length(); i++){char ch = name.charAt(i);sum += Integer.valueOf(ch);}//将字符串转化为int类型,计算关键字name的值sum = sum % m; //除留取余,找到key值在散列表中对应的位置return sum;}//判断素数public static boolean isprime(int n) {if (n < 2)return false;if(n == 2)return true;if(n % 2 == 0)return false;for (int i = 3; i < n; i += 2)if (n % i == 0)return false;return true;}//确定除留取余法的除数:小于size的最大素数public static int confirm(int m){while(!isprime(m)){//如果函数返回值是false,说明m不是素数,就把m----m;}return m;}

Q2:扩容条件?如何扩容?

A2:定义装载因子,大小为散列表已有元素个数/散列表大小(记得转成double),当装载因子>=0.7时,进行扩容,扩容代码如下(自己写的,比较麻烦,如有更好的扩容方法欢迎指教)

  public void expandName(){aslCount1 = 0;int n = dataNum;DataItem[] preArray = new DataItem[dataNum];preArray = getNameArray();arraySize *= 2;m = confirm(arraySize);dataNum = 0;dataArray = new DataItem[m];for(int i = 0;i < n;i++){insertNameData(preArray[i].getName(),preArray[i].getNum(),preArray[i].getAddress());}//System.out.println("扩容成功");}

Q3:解决冲突的方法有哪些?

A3:我采用了线性探测、二次探测、再哈希法、链表法四种方法,给出四种方法的插入操作,其他操作同理。

线性探测

若当前位置产生冲突,则当前位置+1,重复操作,直到不产生冲突为止。

//插入hash表 #用户名public void insertNameData(String name, String num, String address){int count = 0;//记录冲突次数DataItem data = new DataItem(name,num,address);int hashCode = getHashCode(name);aslCount1++;
//用于计算查找成功平均查找长度,将每个元素插入时的探测次数记录并累加,若删除则减去while (dataArray[hashCode] != null){//向后探测if(hashCode < m - 1)hashCode++;elsehashCode = 0;count++;aslCount1++;if(car >= 0.7){//给散列表扩容expandName();insertNameData(name, num, address);return;}}if(count != m){dataArray[hashCode] = data;dataNum++;car = (double)dataNum / (double)m;// System.out.println(car);
//            System.out.println("添加成功 "+data.getName()+data.getNum()+data.getAddress());
//            System.out.println("冲突次数" + count);
//            System.out.println("当前数据个数" + dataNum);}}

二次探测

若当前位置产生冲突,则hashCode为当前位置的+ - 1,2,3,….的平方处,逐个判断直到没有冲突为止。

 //插入hash表 #用户名public void insertNameData(String name, String num, String address){int stepSize, i = 1;DataItem data = new DataItem(name,num,address);int hashCode = getHashCode(name);if(dataArray[hashCode] == null){dataArray[hashCode] = data;dataNum++;aslCount1++;car = (double)dataNum / (double)m;//System.out.println("添加成功 "+data.getName()+data.getNum()+data.getAddress());//System.out.println("当前数据个数" + dataNum);return;}while (i <= m/2){aslCount1++;stepSize = i * i;hashCode += stepSize;hashCode %= m;if(dataArray[hashCode] == null)break;hashCode -= stepSize;if(hashCode < 0){hashCode = 0 - hashCode;//变为正号hashCode %= m;hashCode = m - hashCode;}if(dataArray[hashCode] == null)break;i++;hashCode = getHashCode(name);}if(dataArray[hashCode] == null){dataArray[hashCode] = data;dataNum++;//System.out.println("添加成功 "+data.getName()+data.getNum()+data.getAddress());//System.out.println("当前数据个数" + dataNum);}else {//进行扩容再次递归添加//System.out.println("进行扩容");expandName();insertNameData(name,num,address);}}

再哈希法

构造一个二次哈希函数,当产生冲突时,当前哈希值加上步长stepSize利用除留取余法得到新的哈希值进行判断,直到不产生冲突为止。

//插入hash表 #用户名public void insertNameData(String name, String num, String address){DataItem data = new DataItem(name,num,address);int hashCode = getHashCode(name);int stepSize = getHashCode2(name);aslCount1++;while (dataArray[hashCode] != null){aslCount1++;hashCode += stepSize;hashCode %= m;if(car >= 0.7){//给散列表扩容expandName();insertNameData(name, num, address);return;}}dataArray[hashCode] = data;dataNum++;car = (double)dataNum / (double)m;//System.out.println("添加成功 "+data.getName()+data.getNum()+data.getAddress());//System.out.println("负载因子" + car);//System.out.println("当前数据个数" + dataNum);}
//二次哈希函数,不能输出0,不能与第一次哈希函数相同public int getHashCode2(String name){int sum = 0,constant; //constant是常数,是质数且小于数组容量constant = confirm(m - 1);//令constant为小于m(hash表大小)的最大质数for(int i = 0; i < name.length(); i++){char ch = name.charAt(i);sum += Integer.valueOf(ch);}//将字符串转化为int类型,计算关键字name的值sum = constant-(sum % constant);//公式return sum;}

链表法

计算出哈希码,相同哈希码的元素以链表的形式逐个向后添加,便于插入,但查找和删除时需要在对应哈希码的链表中逐一查找。

hashtable类中方法

//插入 #用户名public void insertName(String name,String num,String address){//获取name的哈希码int hashCode = getHashCode(name);//System.out.println("哈希码为" + hashCode);Node newNode = new Node(name,num,address);//System.out.println("要插入的信息为" + newNode.name + newNode.num + newNode.address);dataArray[hashCode].insertName(newNode);dataNum++;aslCount1 += dataArray[hashCode].getCount();//System.out.println("插入成功第"+ hashCode+"hash表的长度为"+dataArray[hashCode].getLength() + "当前共有数据" + dataNum);}

linklist类中方法,需自定义node类

//插入用户 #用户名public void insertName(Node node){count = 1;//二种情况:1.链表为空;2.链表有节点//1.链表为空if(head == null){head = node;length++;return;}//2.链表存在节点//定义一个辅助指针,找到链表的最后位置,再进行插入Node temp = head;//通过while循环,找到最后while (temp.next != null){count++;temp = temp.next;}//循环退出时temp即为最后的节点//将新添的节点赋值于最后节点的下一个temp.next=node;length++;//System.out.println("插入成功,该链表长度为" + length);}

Q4:如何知道删除成功还是失败?

A4:将删除的方法返回值设置为布尔类型

Q5:其他问题?

A5:可以私信我要整个程序代码,仅供学习使用~也可以有问题与我交流,如果我会的话一定会解答。内容比较简单,方法也非最优,如有问题欢迎指教,一起学习交流,希望对你有帮助!

其他效果:

【Java Swing/散列表】散列表实现电话号码查找系统——问题汇总分享相关推荐

  1. 数据结构课设(散列表的设计与实现---电话号码查找系统)

    一.要求: [问题描述] 设计散列表实现电话号码查找系统. [基本要求] 1) 设每个记录有下列数据项:电话号码.用户名.地址:2) 从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表:3)  ...

  2. Java swing实现的一款餐厅点餐系统

    一.项目简介 本项目是一套Java swing实现的一款餐厅点餐系统,主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者. 包含:项目源码.数据库脚本等,该项目可以直接作 ...

  3. 数据结构课程设计-利用散列表做一个电话号码查找系统

    [基本要求] (1)设每个记录有下列数据项:电话号码.用户名.地址: (2)从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表: (3)采用一定的方法解决冲突: (4)查找并显示给定电话号码的 ...

  4. Java+Swing聊天室

    Java+Swing聊天室 一.系统介绍 二.系统展示 1.发送消息 2.清屏 三.系统实现 四.其他 1.其它系统 2.获取源码 一.系统介绍 本系统实现了简单的聊天室功能:发送消息.清屏.退出系统 ...

  5. java 抽奖系统_【小型系统】抽奖系统-使用Java Swing完成

    一.需求分析 1. 显示候选人照片和姓名. 2. 可以使用多种模式进行抽奖,包括一人单独抽奖.两人同时抽奖.三人同时抽奖. 3. 一个人可以在不同的批次的抽奖中获取一.二.三等奖,但是不能在同一批次抽 ...

  6. 【java毕业设计】基于java+swing的模拟写字板设计与实现(毕业论文+程序源码)——模拟写字板

    基于java+swing的模拟写字板设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+swing的模拟写字板设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦.需要下载开题报 ...

  7. 设计散列表实现通讯录查找系统_[源码和文档分享]利用哈希表实现电话号码查询系统...

    第一章 需求分析 1.1 问题描述 设计一个电话号码查询系统,为来访的客⼈提供各种信息查询服务. 1.2 基本要求 设计每个记录有下列数据项:电话号码.用户名.地址 从键盘输入个记录,分别以电话号码和 ...

  8. 散列表应用---电话号码查询系统

    问题介绍 设计电话号码查询系统 基本要求 1.设每个记录有下列数据项: 电话号码.用户名.地址: 2.从键盘输入各记录,分别以电话号码和用户名为关键字建立散列表: 3.采用合适的方法解决冲突: 4.查 ...

  9. 32. 尚融宝散标投资列表

    需求 一.后端实现 controller LendController.java package com.indi.srb.core.controller.api;@Api(tags = " ...

最新文章

  1. Leangoo项目管理软件阶段式(瀑布式)游戏产品研发流程
  2. redis 未授权访问利用 两种方式
  3. 使用swipemenulistview实现列表的左右滑动
  4. 301转向和网址规范化
  5. 六,搭建elasticsearch集群搭建
  6. 用Windows Live Writer 2012发博客
  7. python snmp采集交换机信息_Python采集12星座信息,分析出12星座的各个特点
  8. 01-hibernate注解:类级别注解,@Entity,@Table,@Embeddable
  9. Qt文档阅读笔记-QWebPage官方解析与实例
  10. 安装eclipse插件sts
  11. 多路复用实现单服百万级别RPS吞吐
  12. android 获取微信二维码 DiffDevOAuth.auth
  13. LAMP架构超详细搭建步骤
  14. 【C语言】百度搜歌(只用歌曲或者歌手名字去搜索实现)
  15. 接口收到CRC错包怎么处理
  16. Docker 中 latest 标签引发的困惑
  17. 一网通支付ios开发
  18. 卡尔曼滤波器(2) -- α−β−γ滤波器(例1)
  19. 购物时,商品加入购物车的飞入效果
  20. 基于C语言的网络电子词典

热门文章

  1. 【python matplotlib 】fig, ax = plt.subplots()画多表图
  2. [re入门]ce对植物大战僵尸的修改
  3. 【接入指南】一文带你了解华为帐号服务
  4. js中promise原理及手动基本实现_V2
  5. 电信运营商大量投入,网速激增
  6. 从win10家庭版/中文版升级到win10专业版
  7. FaceTime 在苹果电脑macOS与iPhone iOS上视频聊天配置步骤
  8. 小程序锚点定位(通讯录)
  9. linux最新分区方案,中移互联网java开发面经
  10. python将结果写入txt文件_python(如何将数据写入本地txt文本文件)