java 网络编程五 (仿QQ聊天程序)

学完了socket通讯后,在老师的要求下,写了一个仿qq的聊天程序:

最终调试程序结果如下图:   有bug希望提出来,我们一起解决。


设计思路:

在服务器端 用一个HashMap<userName,socket> 维护所有用户相关的信息,从而能够保证和所有的用户进行通讯。

客户端的动作:
(1)连接(登录):发送userName    服务器的对应动作:1)界面显示,2)通知其他用户关于你登录的信息, 3)把其他在线用户的userName通知当前用户 4)开启一个线程专门为当前线程服务
(2)退出(注销):

(3)发送消息


※※发送通讯内容之后,对方如何知道是干什么,通过消息协议来实现:

客户端向服务器发的消息格式设计:

命令关键字 @# 接收方 @# 消息内容 @# 发送方
1)连接:userName      ----握手的线程serverSocket专门接收该消息,其它的由服务器新开的与客户进行通讯的socket来接收
2)退出:exit @# 全部 @# null@# userName
3)发送: on @# JList.getSelectedValue() @# tfdMsg.getText() @# tfdUserName.getText()

服务器向客户端发的消息格式设计:

命令关键字 @# 发送方 @# 消息内容
登录:
   1) msg @# server @# 用户[userName]登录了  (给客户端显示用的)
   2) cmdAdd @# server @# userName (给客户端维护在线用户列表用的)
退出:
   1) msg @# server @# 用户[userName]退出了  (给客户端显示用的)
   2) cmdRed@#server @# userName (给客户端维护在线用户列表用的)
发送:

   msg @# 消息发送者 @# 消息内容

代码实现:

客户端:

package cn.hncu.net.sina;import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;public class ClientFrom extends JFrame implements ActionListener{private static String ip="127.0.0.1";private static int port=8080;private JTextField tfdUserName=new JTextField(10);	//用户标识private JTextArea allMsg=new JTextArea();	//聊天信息显示private JTextField tfdMsg=new JTextField(10);//发送消息消息框private JButton btnSend;	//发送消息按钮private JButton btnCon;//在线用户列表private DefaultListModel<String> dataModel=new DefaultListModel<String>();private JList<String> list=new JList<String>(dataModel);public ClientFrom() {setBounds(300,300,400,300);addMenuBar();	//添加菜单上方面板/JPanel northPanel=new JPanel();northPanel.add(new JLabel("用户名称"));tfdUserName.setText("");northPanel.add(tfdUserName);btnCon=new JButton("连接");btnCon.setActionCommand("c");JButton btnExit=new JButton("退出");btnExit.setActionCommand("exit");northPanel.add(btnCon);northPanel.add(btnExit);getContentPane().add(northPanel,BorderLayout.NORTH);	//放在上方//中间面板JPanel centerPanel=new JPanel(new BorderLayout());//中allMsg=new JTextArea();allMsg.setEditable(false);allMsg.setForeground(Color.blue);allMsg.setFont(new Font("幼圆", Font.BOLD, 14));centerPanel.add(new JScrollPane(allMsg));//东dataModel.addElement("全部");list.setSelectedIndex(0);	//设置默认选择位置list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);	//设置只能单选list.setVisibleRowCount(5);		//设置显示的行数list.setFont(new Font("幼圆", Font.BOLD, 12));JScrollPane scroll=new JScrollPane(list);		//为list添加滚动条scroll.setBorder(new TitledBorder("在线"));	//Border的实现类TitileBorderscroll.setPreferredSize(new Dimension(70, allMsg.getHeight()));	//设置滚动条的首选大小centerPanel.add(scroll,BorderLayout.EAST);//南JPanel southPanel=new JPanel();southPanel.add(new JLabel("消息"));southPanel.add(tfdMsg);btnSend=new JButton("发送");btnSend.setActionCommand("send");btnSend.setEnabled(false);southPanel.add(btnSend);centerPanel.add(southPanel,BorderLayout.SOUTH);//把中间面板加到框架中getContentPane().add(centerPanel);//事件监听btnCon.addActionListener(this);btnExit.addActionListener(this);btnSend.addActionListener(this);addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {if(tfdUserName.getText()==null || tfdUserName.getText().trim().length()==0){int result = JOptionPane.showConfirmDialog(ClientFrom.this, "你还没登录,是否退出");if(result==JOptionPane.YES_OPTION){System.exit(0);}else{return;}}System.out.println(tfdUserName.getText()+"退出");sendExitMsg();System.exit(0);}});setVisible(true);}private void addMenuBar() {JMenuBar menuBar=new JMenuBar();setJMenuBar(menuBar);JMenu menu=new JMenu("选项");menuBar.add(menu);JMenuItem itemSet=new JMenuItem("设置");JMenuItem itemHelp=new JMenuItem("帮助");itemSet.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {final JDialog setDlg=new JDialog(ClientFrom.this);setDlg.setBounds(ClientFrom.this.getX(), ClientFrom.this.getY(), 250, 100);setDlg.setLayout(new FlowLayout());setDlg.add(new JLabel("服务器:"));final JTextField tfdIP=new JTextField(10);tfdIP.setText(ip);setDlg.add(tfdIP);setDlg.add(new JLabel("端口:"));final JTextField tfdPort=new JTextField(10);tfdPort.setText(port+"");setDlg.add(tfdPort);JButton btnSet=new JButton("设置");btnSet.setActionCommand("set");JButton btnCanel=new JButton("取消");btnCanel.setActionCommand("canel");setDlg.add(btnSet);setDlg.add(btnCanel);btnSet.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if("set".equals(e.getActionCommand())){if(tfdIP.getText()!=null && tfdIP.getText().trim().length()>0){ClientFrom.this.ip=tfdIP.getText();}if(tfdPort.getText()!=null && tfdPort.getText().trim().length()>0){try {ClientFrom.this.port=Integer.parseInt(tfdPort.getText());} catch (NumberFormatException e1) {JOptionPane.showMessageDialog(setDlg, "端口号格式输入错误,请输入数字");}}btnCon.setEnabled(true);tfdUserName.setEditable(true);if(client!=null){//如果前面已经登录着用户,就把用户退出String msg="exit@#全部@#null@#"+tfdUserName.getText();pw.println(msg);dataModel.removeElement(tfdUserName.getText());list.validate();tfdUserName.setText("");}setDlg.dispose();}else if("canel".equals(e.getActionCommand())){return;}}});setDlg.setVisible(true);}});itemHelp.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {JDialog helpDlg = new JDialog(ClientFrom.this);helpDlg.setBounds(ClientFrom.this.getX()+10, ClientFrom.this.getY(), 300, 100);JLabel str = new JLabel("版权所有@dragon_Dai.QQ:794530831");helpDlg.add(str);helpDlg.setVisible(true);}});menu.add(itemSet);menu.add(itemHelp);}@Overridepublic void actionPerformed(ActionEvent e) {if("c".equals(e.getActionCommand())){System.out.println(tfdUserName.getText());if(tfdUserName.getText()==null || tfdUserName.getText().trim().length()==0){JOptionPane.showMessageDialog(this, "用户名不能为空");return;}System.out.println(tfdUserName.getText()+":连接ing...");connecting();}else if("exit".equals(e.getActionCommand())){if(tfdUserName.getText()==null || tfdUserName.getText().trim().length()==0){int result = JOptionPane.showConfirmDialog(this, "你还没登录,是否退出");if(result==JOptionPane.YES_OPTION){System.exit(0);}else{return;}}System.out.println(tfdUserName.getText()+"退出");sendExitMsg();}else if("send".equals(e.getActionCommand())){if(tfdMsg.getText()==null){JOptionPane.showMessageDialog(this, "发送消息不能为空");return;}String msg="on@#"+list.getSelectedValue()+"@#"+tfdMsg.getText()+"@#"+tfdUserName.getText();pw.println(msg);}}private Socket client;private PrintWriter pw;private void connecting() {//与服务器建立连接,把userName传给服务器try {client=new Socket(ip,port);//发送用户名给服务器btnCon.setEnabled(false);	//连接成功后关掉连接按钮String userName=tfdUserName.getText().trim();pw=new PrintWriter(client.getOutputStream(),true);pw.println(userName);//连接之后,设置标题为userName在线setTitle(userName+"在线");btnSend.setEnabled(true);		//打开发送按钮tfdUserName.setEditable(false);		//用户名不能再修改//开一个线程单独用于跟服务器通信new ClientThread(client).start();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private void sendExitMsg() {//与服务器建立连接,把userName传给服务器try {client=new Socket(ip, port);String msg="exit@#全部@#null@#"+tfdUserName.getText();pw.println(msg);System.exit(0);} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}class ClientThread extends Thread{private Socket client;public ClientThread(Socket client) {this.client=client;}@Overridepublic void run() {//接收服务器返回的信息try {Scanner sc=new Scanner(client.getInputStream());while(sc.hasNext()){String msg=sc.nextLine();String msgs[]=msg.split("@#");if(msgs==null || msgs.length!=3){System.out.println("通讯异常");return;}if("msg".equals(msgs[0])){//表示该信息是用来显示用的if("server".equals(msgs[1])){//表示该信息是系统信息msg="系统信息:"+msgs[2];allMsg.append(msg+"\r\n");}else{//表示该信息聊天信息msg=msgs[1]+msgs[2];allMsg.append(msg+"\r\n");}}else if("cmdAdd".equals(msgs[0])){//表示该消息是用来更新用户在线列表的,添加用户dataModel.addElement(msgs[2]);}else if("cmdRed".equals(msgs[0])){//表示该消息是用来更新用户在线列表的,移除用户dataModel.removeElement(msgs[2]);}list.validate();	//需要刷新list,不然可能出现list更新失败的bug}} catch (IOException e) {e.printStackTrace();}}}public static void main(String[] args) {JFrame.setDefaultLookAndFeelDecorated(true);new ClientFrom();}
}
服务器:
package cn.hncu.net.sina;import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Scanner;import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
import javax.swing.border.TitledBorder;public class ServerFrom extends JFrame{private JTextArea area;//在线的用户信息显示private DefaultListModel<String> dataModel;	//在线的用户列表显示//注册的用户名不能相同//用于存储所有的用户,这里采用注册的"用户名"做key值,通信的socket做value值private Map<String, Socket> userMap=new HashMap<String, Socket>();public ServerFrom() {setTitle("聊天服务器");setDefaultCloseOperation(EXIT_ON_CLOSE);Toolkit toolkit=Toolkit.getDefaultToolkit();Dimension dim=toolkit.getScreenSize();int runWidth=500;int runHeight=400;int width=(int) dim.getWidth();int height=(int) dim.getHeight();//设置界面居中显示setBounds(width/2-runWidth/2, height/2-runHeight/2, runWidth, runHeight);area=new JTextArea();area.setEditable(false);getContentPane().add(new JScrollPane(area),BorderLayout.CENTER);//列表显示dataModel=new DefaultListModel<String>();JList<String> list=new JList<String>(dataModel);JScrollPane scroll=new JScrollPane(list);scroll.setBorder(new TitledBorder("在线"));scroll.setPreferredSize(new Dimension(100, this.getHeight()));getContentPane().add(scroll,BorderLayout.EAST);//菜单JMenuBar menuBar=new JMenuBar();setJMenuBar(menuBar);JMenu menu=new JMenu("控制(C)");menu.setMnemonic('C');		//设置快捷键为 Alt+CmenuBar.add(menu);//开启final JMenuItem itemRun=new JMenuItem("开启");//快捷键 Ctrl+RitemRun.setAccelerator(KeyStroke.getKeyStroke('R', KeyEvent.CTRL_MASK));itemRun.setActionCommand("run");menu.add(itemRun);//退出JMenuItem itemExit=new JMenuItem("退出");itemExit.setAccelerator(KeyStroke.getKeyStroke('E', KeyEvent.CTRL_MASK));itemExit.setActionCommand("exit");menu.add(itemExit);itemRun.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {if("run".equals(e.getActionCommand())){startServer();itemRun.setEnabled(false);}}});setVisible(true);}private void startServer() {try {System.out.println("服务器启动");ServerSocket server=new ServerSocket(8080);area.append("启动服务器:"+server);//单独开启一个线程用于与客户端握手new ServerThread(server).start();} catch (IOException e) {e.printStackTrace();}}class ServerThread extends Thread{private ServerSocket server;public ServerThread(ServerSocket server) {this.server=server;}@Overridepublic void run() {try {while(true){Socket s=server.accept();//读取客户端第一次向服务器请求的信息
//					BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));
//					if(br.readLine()!=null){
//						String userName=br.readLine();
//					}Scanner sc=new Scanner(s.getInputStream());if(sc.hasNext()){String userName=sc.next();area.append("\r\n"+userName+"上线了。"+s);dataModel.addElement(userName);
//						userMap.put(userName, s);	//在后面在把这个用户加入到集合中好一点,那样发送上线信息给所有用户时,就不用判断不发发给自己了。//登录成功//在专门开一个线程用于跟针对某一个客户端通讯//根据接收客户端发来的协议判断,客户端进行的是什么样的请求new ClientThread(s).start();//告诉其他用户有人上线了sendMsgToAll(userName);//把消息其他在线的用户的信息传给登录的这个客户端sendMsgToSelf(s);userMap.put(userName, s);}}} catch (IOException e) {e.printStackTrace();}}}public void sendMsgToAll(String userName) throws IOException{		//这里的异常可以抛,因为调用这个方法的位置抓了IOException//遍历map中所有除了该用户之外的客户--此时登录的用户还没有加入到容器中,所有可以直接遍历所有用户Iterator<Socket> it = userMap.values().iterator();while(it.hasNext()){Socket s=it.next();PrintWriter pw=new PrintWriter(s.getOutputStream(),true);//服务器向客户端发的消息格式设计://命令关键字@#发送方@#消息内容String msg="msg@#server@#"+userName+"登录了";	//用于显示用的.pw.println(msg);msg="cmdAdd@#server@#"+userName;	//用于给客户端维护在线用户列表用的pw.println(msg);//			pw.close();
//			s.close();}}public void sendMsgToSelf(Socket s) throws IOException{PrintWriter pw = new PrintWriter(s.getOutputStream(),true);Iterator<String> it = userMap.keySet().iterator();while(it.hasNext()){String userName=it.next();System.out.println("map:"+userMap);//告诉用户当前在线用户信息,不需要发送显示信息,只需要发送给客户端更新在线列表的信息String msg="cmdAdd@#server@#"+userName;pw.println(msg);}//		pw.close();}//专门用于跟某一个用户通讯的线程class ClientThread extends Thread{private Socket s;public ClientThread(Socket s) {this.s=s;}@Overridepublic void run() {try {//根据接收客户端发来的协议判断,客户端进行的是什么样的请求Scanner sc=new Scanner(s.getInputStream());while(sc.hasNextLine()){String msg=sc.nextLine();String msgs[]=msg.split("@#");//简单防黑。if(msgs==null || msgs.length!=4){System.out.println("通讯异常:"+msg);return;}if("on".equals(msgs[0])){//表示客户端的请求是:向别人发送信息sendMsgToSb(msgs);}else if("exit".equals(msgs[0])){//表示客户端发送的请求是:退出(下线)area.append("\r\n"+msgs[3]+"下线了"+s);dataModel.removeElement(msgs[3]);userMap.remove(msgs[3]);//通知其他所有在线的用户,***退出了sendSbExitMsgToAll(msgs);}}} catch (IOException e) {e.printStackTrace();}}}//命令关键字@#接收方@#消息内容@#发送方public void sendMsgToSb(String[] msgs) throws IOException {//可能是发给所有人,也可能是发给某一个人if("全部".equals(msgs[1])){//发给所有人(群聊)Iterator<String> it = userMap.keySet().iterator();while(it.hasNext()){String userName=it.next();String msg=null;if(userName.equals(msgs[3])){msg="msg@#"+"我"+"@#说:"+msgs[2];}else{msg="msg@#"+msgs[3]+"@#说:"+msgs[2];}Socket s=userMap.get(userName);//msg@#消息发送者@#消息内容PrintWriter pw=new PrintWriter(s.getOutputStream(), true);pw.println(msg);}}else{//发送给某一个人String userName=msgs[1];Socket s=userMap.get(userName);//msg@#消息发送者@#消息内容String msg="msg@#"+msgs[3]+"@#悄悄对你说:"+msgs[2];PrintWriter pw=new PrintWriter(s.getOutputStream(), true);pw.println(msg);//在发给自己Socket s2 = userMap.get(msgs[3]);PrintWriter pw2 = new PrintWriter(s2.getOutputStream(), true);String str2 = "msg@#"+"我"+"@#对 "+userName+"说:"+msgs[2];pw2.println(str2);}}//通知其他所有在线的用户,***退出了//1) msg @# server @# 用户[userName]退出了  (给客户端显示用的)//2) cmdRed@#server @# userName (给客户端维护在线用户列表用的)public void sendSbExitMsgToAll(String[] msgs) throws IOException {Iterator<String> it=userMap.keySet().iterator();while(it.hasNext()){String userName=it.next();Socket s=userMap.get(userName);PrintWriter pw=new PrintWriter(s.getOutputStream(), true);String msg="msg@#server@#用户["+msgs[3]+"]退出了";pw.println(msg);msg="cmdRed@#server@#"+msgs[3];pw.println(msg);}}public static void main(String[] args) {JFrame.setDefaultLookAndFeelDecorated(true);new ServerFrom();}}



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21598.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Chatgpt论文笔记——GPT1详细解读与可运行的代码

前言 论文&#xff1a;https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdf 时间&#xff1a;2018年6月 贡献&#xff1a; 提出了大规模数据上无监督预训练然后在目标任务上有监督finetune的范式。 具体实现 当时由于NLP领域不存…

生成式AI管理规则落地 大模型后时代到来

国家网信办等七部门联合颁布的《生成式人工智能服务管理暂行办法》&#xff0c;给中国生成式AI产业树立了发展规范。 这份监管文件的用意并不止于管控&#xff0c;还用大量的笔墨传递出推动产业发展的原则&#xff0c;尤其强调“鼓励生成式人工智能技术在各行业、各领域的创新…

摄影师没了?!生成式人工智能即将降维打击摄影行业

本文是Mixlab无界社区成员的投稿&#xff1a; 滚石 deepfacelab和deepfacelive项目组成员 摄影师失业了&#xff1f;&#xff1f;怎么说&#xff1f; # # 你还以为AI绘画影响的只是插画师行业吗&#xff1f;错了&#xff0c;摄影行业也即将面临技术洗牌。话不多说&#xff0c;先…

AIGC绘就无限可能的元宇宙

随着科技的飞速发展&#xff0c;我们正逐渐步入一个由虚拟和现实交织构成的全新时代。元宇宙&#xff08;Metaverse&#xff09;作为这个新时代的象征&#xff0c;正在成为一个重要的热点。而人工智能生成内容&#xff08;AIGC&#xff09;技术的结合&#xff0c;将无疑会推动元…

开发者出海合规手册;@levelsio独立开发月入20万解析;MJ+AR设计珠宝;SD算法原理-通俗版 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; 独立开发者必看&#xff0c;出海应用开发者合规手册 这是 JourneymanChina 多年出海经验教训的总结&#xff0c;适用于Google Play 以…

ChatGPT唤醒AI游戏?

配图来自Canva可画 “七天制作新游戏”、“AI全自动完成所有游戏&#xff01;”......继各种AI绘画、AI合成照片、视频之后&#xff0c;AI在游戏领域开启了新一场狂欢。 长久以来&#xff0c;游戏和AI一直有着“相互扶持”的亲密关系——一边是游戏充当AI科研基地&#xff0c…

网易的“草长莺飞二月天”:增长稳健,加码研发,逐浪AI

2月23日&#xff0c;网易发布了2022年第四季度财报。 这是网易与暴雪分道扬镳后的首份财报&#xff0c;加上近期AIGC热度扩散至游戏、教育等各个领域&#xff0c;网易第四季度业绩及其对于GPT等热门技术的探索受到市场关注。 根据财报&#xff0c;第四季度&#xff0c;网易营…

「经济理财」32堂你能听懂的理财课

之前学了一下基金投资课程&#xff0c;作为以后财富管理的积累&#xff0c;可以出门右转看「银行螺丝钉的基金投资课」。但还是觉得应该系统了解一下理财&#xff0c;从小白到理财达人&#xff0c;我需要半年来学习和实践&#xff0c;比较好的是接触到简七理财&#xff0c;结合…

[AI医学] 医学领域几个微调预训练大模型的项目

关键词&#xff1a;AI医学&#xff0c;医学大模型&#xff0c;指令微调&#xff0c;PubMed 文章目录 医学微调大模型1. MedicalGPT-zh2. DoctorGLM3. Huatuo-Llama-Med-Chinese & ChatGLM-Med 医学预训练语言模型1. BioMedLM (2.7B)2. PMC-LLaMA (7B)3. BioMedGPT (1.6B) 总…

程序员专属对联

请欣赏“程序猿春节对联集锦”&#xff1a; 对联一 上联&#xff1a;上拜图灵只佑服务可用 下联&#xff1a; 下跪关公但求永不宕机 横批&#xff1a;风调码顺 风调雨顺 上拜图灵只佑服务可用 下跪关公但求永不宕机 对联二 上联&#xff1a;屏中创造繁华世 下联&#xff1a;指尖…

Node接入ChatGPT 的最强对手Claude

由于个人的chatGPT免费版本即将到期, Claude 很火&#xff0c;在网上被说成是 ChatGPT 的最强对手&#xff0c;是 ChatGPT 的替代品。本文我将介绍下 Claude 是什么&#xff0c;以及如何免费使用 Claude. 什么是Claude 看一下它是如何自我介绍的 Slack Slack 是一款流行的团…

读《EMOQ-TTS: EMOTION INTENSITY QUANTIZATION FOR FINE-GRAINED CONTROLLABLE EMOTIONAL TEXT-TO-SPEECH》

0 Abstract 虽然近年来文本到语音(TTS)的研究取得了显著进展&#xff0c;但仍局限于情感语音合成。为了产生情感话语&#xff0c;大多数作品都利用了从情感标签或参考音频中提取的情感信息。然而&#xff0c;由于话语层面的情绪条件&#xff0c;它们导致了单调的情绪表达。在本…

专家担心 ChatGPT 很快会被用于毁灭性的网络攻击

听到这个新闻&#xff0c;我是挺震惊的&#xff0c;​ChatGPT 近几个月来风靡全球&#xff0c;但就在它以其技术能力让人们惊叹的同时&#xff0c;也有人对其潜在的滥用提出了担忧。 现在&#xff0c;似乎一些 IT 领导者担心它将很快被用于重大网络攻击&#xff0c;并有可能在未…

英文润色网站-英文质量改写改进软件

英文改写软件 英文改写软件是一种全新的工具&#xff0c;它可以方便快捷地对不同语种的图文内容进行批量改写和转换&#xff0c;包括但不限于英语、法语、德语、中文等。无论用户需要将哪种语言的文章进行改写和转换&#xff0c;都可以轻松实现。该软件支持任何文档格式和文本…

OpenAI Translator Bob Plugin Bob上一款翻译、润色、语法修改插件

OpenAI Translator Bob Plugin 一款可以在Bob进行即时翻译的插件。它基于 OpenAI 的 GPT 系列模型&#xff0c;能够提供高质量、准确的翻译服务。该插件支持多种语言的翻译&#xff0c;包括中文、英文、法语、德语、日语等。用户只需在页面中选中需要翻译的文本&#xff0c;然…

pg数据库数据导出

首先得在postgresql的安装包下找到bin目录&#xff0c;找到路径。其次在cmd下面&#xff0c;输入导出路径&#xff1a; 导出数据库的命令&#xff1a; > pg_dump -U postgres -h ip地址 数据库名> f:\data\数据库名.dump >口令&#xff1a;密码

如何进行数据的导出?

如何进行数据的导出&#xff1f; 以前有进行过填写资料并且把资料导出Excel表格&#xff0c;当时就觉得好神奇&#xff0c;又想知道这样的功能是怎么实现的&#xff0c;可是那时的头脑简单&#xff0c;没有知道答案&#xff0c;可是现在我终于知道为什么可以直接导出数据了&am…

图像搜索:以图搜图

以图搜图 随着数字时代的到来&#xff0c;单单的文字搜素已经无法满足人们的搜索了&#xff0c;图像搜索&#xff0c;甚至是视频搜索都已经比较成熟。本文大致讲解下图像搜索&#xff1a; 发展历程 原理 搜索项目&#xff1a;主要分为三个部分——图像特征抽取&#xff0c;构…

图片搜索引擎网站大全,以图搜图网站

当我们需要搜索一些图片的时候使用图片搜索引擎网站可以帮我们更快地找到自己需要的图片&#xff0c;那么有哪些图片搜索引擎网站可以搜索图片呢&#xff1f;下面小编就来和大家分享几个以图搜图的网站。 1.百度图片搜索引擎网站 百度是最大的中文搜索引擎&#xff0c;百度的图…

查找照片的来源

想要知道照片的来源&#xff0c;可以使用百度识图或其他识图工具&#xff0c;但得到的信息可能不多&#xff0c;不过还可以通过多种手段获取更多信息。 以以下照片为例&#xff0c;查找是哪家麦当劳。 &#xff08;1&#xff09;.进入电脑pc端&#xff0c;右键单击照片&#xf…