Java之IO,网络编程实现人机聊天对话功能
首先咱们来看一下模拟环境:
某程序员大锤有一个非常喜欢的女神,为了保留和女神的各个瞬间,某程序员大锤想把他们的聊天信息(只保留文字)都保存到自己本地系统,作为以后在一起的甜蜜回忆.
经过自己分析,他和女神聊天的信息库大致如下(这是两个文件):
=某程序员大锤常用语文件(大锤.txt):=
在么
我给你发了一个红包
好的
=女神常用语文件(女神.txt):=
正要去洗澡…
正在吃饭…
正在和朋友在一起
谢谢,那我不客气了,你早点休息
真的啊,大锤,你真好
大锤你真棒
怎么了,不开心么
…你怎么回事
…是什么意思
大致内容就是这样子了,这时候我们需要考虑的就是,如果大锤说的话不在此文件中怎么办,我这里使用的是茉莉机器人来代替女神说话
首先,前去茉莉的官网http://www.itpk.cn/来注册一个账号和密码(注:茉莉为免费机器人,本人没收茉莉一分钱,本人没收茉莉一分钱,本人没收茉莉一分钱,也不为茉莉还要其他任何一个平台代言,只是单纯的来使用一下此平台,实现自己需要的功能)
注册好,登陆后显示的界面为:
这个时候我们记住自己的Api Key和Api Secret,在后面接入机器人来使用,下面咱们来查看接入的API
咱们这里只是简单的实现功能,所以机器人的其他操作设置不做任何配置,使用默认即可,下面咱们一步一步的来使用IO,网络编程,实现文件读取,存储,机器人接入功能,话不多说,来操作吧:在项目下创建一个文件夹,用来存放大锤.txt和女神.txt文件
接着来创建聊天生成文件的类:
这里碰到了异常,不知道异常是什么的,可以去看我之前写的异常:来简单的学习下,遇到不懂的,可以在下面加我微信进行交流
public class Chatlog{
//定义一个全局的键盘扫描器
static Scanner in = new Scanner(System.in);
//main方法,因为使用到了IO,肯定会有IO异常,我这里直接选择了throws抛出,代码看着整洁,干净,在开发中,推荐使用try{}catch(Exception e){}来捕获
public static void main(String[] args) throws IOException{
System.out.println("===欢迎来到珍爱网交友直播现场===");
System.out.println("===系统初始化中......");
System.out.println("请输入您要聊天的对象:");
String name = in.nextLine();
//初始化字典,返回map集合
Map<String,List<String>> map = showLog();
System.out.println(map);
System.out.println("聊天开始....");
System.out.println("聊天记录即将备份到文件,请输入文件名(记得加后缀名):");
String fileName = in.nextLine();
String me ;
while(true) {
System.out.print("我:");
me = in.nextLine();
//调用保存日志方法
saveLog("我",me,fileName);
//调用获取女神回复信息的方法
String getreply = getReply(map,me);
//女神回复的可能没有在文件中,没有
//然后调用HttpRequest的request方法,使用茉莉机器人来代替女神
if(getreply == null) {
//调用HttpRequest的request方法,返回的是String类型
String str = HttpRequest.request(me);
System.out.println(name+":"+str);
saveLog(name,str,fileName);
}else {
System.out.println(name + ":"+ getreply);
saveLog(name,getreply,fileName);
}
}
}
}
下面就要来继续实现里面实现操作的方法了:
首先初始化系统,在原来的类里面,在main方法下面直接来写这些方法:
/**
* 初始化系统
* @throws IOException
*/
private static Map showLog() throws IOException {
//初始化女神和大锤的聊天的字典
Map<String,List<String>> map = new HashMap<String,List<String>>();
//创建文件对象
File chui = new File("FileTest/大锤.txt");
File nvShen = new File("FileTest/女神.txt");
//读取大锤文件,返回的是list集合
List<String> chuiList = readLog(chui);
List<String> nvList = readLog(nvShen);
// System.out.println(chuiList);
// System.out.println(nvList);
//定义一个list集合,用来存放女神的对话
List<String> values;
//循环大锤的文件
for(int i = 0;i<chuiList.size();i++) {
// System.out.println(chuiList.get(i));
//初始化女神集合
values = new ArrayList<String>();
//循环女神的文件,3个3个循环,正好和大锤的语录匹配上
for(int j = i*3;j<i * 3 + 3;j++) {
// System.out.println(nvList.get(j));
//将女神的语录添加到集合中
values.add(nvList.get(j));
}
//将他们语录添加到字典中
map.put(chuiList.get(i), values);
}
return map;
}
定义读取文件的方法,因为这些文本是一行一行的存在,所以在这里使用字符缓冲流来读取
/**
* 读取文件的方法
* @param file
* @return
* @throws IOException
*/
private static List readLog(File file) throws IOException {
//创建list集合,将读取到的内容存入集合中
List<String> list = new ArrayList<String>();
//定义字符缓冲输入流
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String line;
//为null结束循环
while((line = br.readLine())!=null) {
//添加到集合中
list.add(line);
}
//关流
if(br != null)br.close();
return list;
}
}
然后来获取女神的回复:
/**
* 获取回复信息
* @param me
* @param map
*/
private static String getReply(Map<String, List<String>> map, String me) {
//定义一个集合,用来接收循环后的女神对话
List<String> value = null;
//将map集合转换为set集合
Set<String> set = map.keySet();
//使用for循环,进行遍历
for(Object obj : set) {
// System.out.println(obj+" "+map.get(obj));
//如果输入的内容和集合的中键包含,将保存到value集合中
if(me.contains(obj.toString())) {
value = map.get(obj);
break;
}
}
//如果输入的不在范围内,返回null,否则的话,会报空指针异常,在这里也方便上面用来判断是否有女神的回复
if(value == null) {
return null;
}
//随机数
Random r = new Random();
//随机获取女神的对话
me = value.get(r.nextInt(3));
return me;
}
最后保存聊天记录:
/**
* 保存聊天记录
* @param name
* @param getreply
* @throws IOException
*/
private static void saveLog(String name, String getreply,String fileName) throws IOException {
//创建文件对象
File file = new File(fileName);
//判断这个文件是否存在,不存在则创建
if(!file.exists()) {
file.createNewFile();
}
//格式化时间
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = sdf.format(new Date());
//调用字符缓冲输出流,后面加true代表可以追加,可以在文件下面写入
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName,true)));
//写入文件
bw.write(date+"-"+name+":"+getreply);
//换行
bw.newLine();
//关流
if(bw!=null) bw.close();
}
与女神的基本对话,就这么多,下面就来写与女神对话文件没有时候的操作,也就是接入机器人,创建http类
/*
* 向机器人发送请求和解析机器人的相应
* */
public class HttpRequest {
//设置相关常量
//api_key,我这里一部分用*来代替了,大家修改成自己的
public static final String API_KEY = "4cf4******a9f73de******26359e78e";
//API_PASSWORD
public static final String API_SECRET = "totc******uo";
//基础路径
public static final String BASE_PATH = "http://i.itpk.cn/api.php?";
//发送请求的方法
public static String request(String msg) {
//将消息字符集转码(utf-8 gbk iso-8859-1(欧洲编码 不支持中文))
try {
msg = URLEncoder.encode(msg,"utf-8");
//拼接请求路径
String path = BASE_PATH + "question=" + msg + "&api_key=" + API_KEY + "&api_secret=" + API_SECRET;
//将请求包装成一个对象
URL url = new URL(path);
//打开连接
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//设置请求方式
conn.setRequestMethod("GET");
//发送请求并获取相应参数(200:成功 404:路径 not found 500:server err)
int code = conn.getResponseCode();
// System.out.println(code);
if(code == 200) {
//请求成功,接受机器人的消息
//获取连接对象的输入流
InputStream is = conn.getInputStream();
//将字节流转换成字符流
InputStreamReader isr = new InputStreamReader(is,"utf-8");
//字符缓冲
BufferedReader br = new BufferedReader(isr);
//读取消息,声明一个字符串变量,用来保存每次读取的数据
String msg2= "";
StringBuffer string = new StringBuffer();//最终的消息
//循环读取消息
while((msg2 = br.readLine())!= null) {
string.append(msg2+"\n");
}
//返回字符串的缓冲区的内容
return string.toString().substring(1, string.length()-1);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
来看运行效果图: