一、主要实现功能
1.用户登录
2.显示当前在线用户列表
3.群发消息
4.私聊
5.发送文件
6.服务器端信息推送
7.退出系统
二、代码实现
1.服务端代码
(1)qqframe类
package com.ckx.qqframe;
import com.ckx.qqserver.service.QQServer;
/**
* @description:
* @author: 1223
**/
public class qqframe {
public static void main(String[] args) {
new QQServer();
}
}
(2)ManageClientThreads类
package com.ckx.qqserver.service;
import java.util.HashMap;
import java.util.Iterator;
/**
* @description:
* @author: 1223
**/
public class ManageClientThreads {
//将多个线程放入HashMap集合
private static HashMap<String,ServerConnectClientThread> hm = new HashMap<>();
// 返回HashMap
public static HashMap<String, ServerConnectClientThread> getHm() {
return hm;
}
// 添加线程对象到hm 集合
public static void addClientThread(String userId,ServerConnectClientThread serverConnectClientThread){
hm.put(userId,serverConnectClientThread);
}
//通过一个方法,可以得到对应线程
public static ServerConnectClientThread getClientConnectServerThread(String userId){
return hm.get(userId);
}
//从集合移除某个线程
public static void removeServerConnectClientThread(String userId){
hm.remove(userId);
}
//编写方法返回在线用户列表
public static String getOnlineUser(){
Iterator<String> iterator = hm.keySet().iterator();
String onlineUserList = "";
while (iterator.hasNext()){
onlineUserList+= iterator.next().toString()+" ";
}
return onlineUserList;
}
}
(3)QQServer类
package com.ckx.qqserver.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import com.ckx.qqcommon.User;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
/**
* @description:在9999端口,等待客户端连接
* @author: 1223
**/
public class QQServer {
private ServerSocket ss = null;
// 创建一个集合,存放多个用户,如果是这些用户登录,就认为是合法的
private static HashMap<String ,User> validUsers = new HashMap<>();
ArrayList<Message> arrayList = new ArrayList<>();
ConcurrentHashMap<String, ArrayList> chm = new ConcurrentHashMap<String, ArrayList>();
static {//在静态代码块初始化validUsers
validUsers.put("101",new User("101","123456"));
validUsers.put("202",new User("202","123456"));
validUsers.put("时光",new User("时光","123456"));
validUsers.put("琉璃",new User("琉璃","123456"));
validUsers.put("零",new User("零","123456"));
}
//验证用户是否有效
private boolean checkUser(String userId,String passwd) {
User user = validUsers.get(userId);
if (user == null) {//说明User不存在
return false;
}
if (!user.getPasswd().equals(passwd)) {
return false;
}
return true;
}
public QQServer(){
try {
System.out.println("在9999监听。。。。");
//启动推送新闻线程
new Thread(new SendNewsToAllService()).start();
ss = new ServerSocket(9999);
while (true) {//和某个客户端建立连接后,会继续保持监听
Socket socket = ss.accept();
//得到socket关联对象输入流
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
User u = (User) objectInputStream.readObject();
Message message = new Message();
//验证
if(checkUser(u.getUserId(), u.getPasswd())){//如果登录通过
message.setMesType(MessageType.MESSAGE_LOGIN_SUCCEED);
objectOutputStream.writeObject(message);//讲message对象回复给客户端
ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());
//启动线程
serverConnectClientThread.start();
// 将线程放入集合,方便管理
ManageClientThreads.addClientThread(u.getUserId(),serverConnectClientThread);
}else {//登录失败
message.setMesType(MessageType.MESSAGE_LOGIN_FAIL);
objectOutputStream.writeObject(message);
socket.close();
}
}
}catch (Exception e) {
e.printStackTrace();
} finally {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(4)SendNewsToAllService类
package com.ckx.qqserver.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import com.ckx.utils.Utility;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
* @description:
* @author: 1223
**/
public class SendNewsToAllService implements Runnable{
@Override
public void run() {
//为了可以推送多次新闻,使用while
while (true) {
System.out.println("请输入服务器要推送的而新闻(输入exit退出新闻推送):");
String news = Utility.readString(100);
if("exit".equals(news)){
break;
}
Message message = new Message();
message.setSender("服务器");
message.setContent(news);
message.setMesType(MessageType.MESSAGE_TO_ALL_NEWS);
message.setSendTime(new Date().toString());
System.out.println("服务器推送消息给所有人:" + news);
//遍历所有的通信线程,得到socket,并发送message
HashMap<String, ServerConnectClientThread> hm = ManageClientThreads.getHm();
Iterator<String> iterator = hm.keySet().iterator();
while (iterator.hasNext()) {
String onLineUserId = iterator.next().toString();
ServerConnectClientThread serverConnectClientThread = hm.get(onLineUserId);
try {
new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream()).writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(5)ServerConnectClientThread类
package com.ckx.qqserver.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
/**
* @description:该类的一个对象和某个客户端保持通信
* @author: 1223
**/
public class ServerConnectClientThread extends Thread{
private Socket socket;
private String userId;
public ServerConnectClientThread(Socket socket, String userId) {
this.socket = socket;
this.userId = userId;
}
public Socket getSocket() {
return socket;
}
@Override
public void run() {
while (true){
try {
System.out.println("保持通讯");
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message message = (Message) objectInputStream.readObject();
//根据message类型,做相应处理
if(message.getMesType().equals(MessageType.MESSAGE_GET_ONLINE_FRIEND)){
System.out.println(message.getSender()+"在线用户列表");
String onlineUser = ManageClientThreads.getOnlineUser();
Message message1 = new Message();
message1.setMesType(MessageType.MESSAGE_RET_ONLINE_FRIEND);
message1.setContent(onlineUser);
message1.setGetter(message.getSender());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(message1);
}else if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){
ServerConnectClientThread serverConnectClientThread=ManageClientThreads.getClientConnectServerThread(message.getGetter());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
objectOutputStream.writeObject(message);
}
else if(message.getMesType().equals(MessageType.MESSAGE_CLIENT_EXIT)){
System.out.println(message.getSender()+"退出");
//然后将这个客户端对应的线程从集合中移除
Thread.sleep(1000);
ManageClientThreads.removeServerConnectClientThread(message.getSender());
socket.close();
break;
}else if(message.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES)){
//遍历所有用户的线程,然后进行转发
HashMap<String,ServerConnectClientThread> hm = ManageClientThreads.getHm();
Iterator<String> iterator = hm.keySet().iterator();
while (iterator.hasNext()){
//取出在线用户的ID
String s = iterator.next().toString();
if(!s.equals(message.getSender())){
ObjectOutputStream objectOutputStream = new ObjectOutputStream(hm.get(s).getSocket().getOutputStream());
objectOutputStream.writeObject(message);
}
}
}else if(message.getMesType().equals(MessageType.MESSAGE_FILE_MES)){
//转发文件
ServerConnectClientThread clientConnectServerThread = ManageClientThreads.getClientConnectServerThread(message.getGetter());
new ObjectOutputStream(clientConnectServerThread.getSocket().getOutputStream()).writeObject(message);
}else if(message.getMesType().equals(MessageType.MESSAGE_TO_ALL_NEWS)){
ServerConnectClientThread clientConnectServerThread = ManageClientThreads.getClientConnectServerThread(message.getGetter());
new ObjectOutputStream(clientConnectServerThread.getSocket().getOutputStream()).writeObject(message);
}
else {
System.out.println("不处理");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2.客户端代码
(1)ClientConnectServerThread类
package com.ckx.qqclient.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
/**
* @description:
* @author: 1223
**/
public class ClientConnectServerThread extends Thread{
//该线程需要持有Socket
private Socket socket;
public ClientConnectServerThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
//因为线程需要在后台和服务器通讯,做成While循环
while (true){
try {
System.out.println("客户端线程等待读取从服务器端发送的消息");
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message message = (Message) objectInputStream.readObject();
if(message.getMesType().equals(MessageType.MESSAGE_RET_ONLINE_FRIEND)){
String[] onlineUsers = message.getContent().split(" ");
System.out.println("============当前在线用户列表===========");
for (int i = 0; i < onlineUsers.length; i++) {
System.out.println("用户:"+onlineUsers[i]);
}
}else if(message.getMesType().equals(MessageType.MESSAGE_COMM_MES)){
System.out.println("\n"+message.getSender()+"对"+message.getGetter()+"说"+message.getContent());
} else if (message.getMesType().equals(MessageType.MESSAGE_TO_ALL_MES)) {
System.out.println("\n"+message.getSender()+"对大家说:"+message.getContent());
} else if(message.getMesType().equals(MessageType.MESSAGE_FILE_MES)){
System.out.println("\n"+message.getSender()+"给"+message.getGetter()+
"发文件:"+message.getSrc()+"到我的电脑的"+message.getDest());
FileOutputStream fileOutputStream = new FileOutputStream(message.getDest());
fileOutputStream.write(message.getFileBytes());
fileOutputStream.close();
System.out.println("\n 发送文件成功~");
}else if(message.getMesType().equals(MessageType.MESSAGE_TO_ALL_NEWS)){
System.out.println("服务器群发了"+message.getContent());
System.out.println("收到新闻推送");
}
else {
System.out.println("其他类型message,暂时不处理");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//为了更方便的得到Socket
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
}
(2)FileClientService类
package com.ckx.qqclient.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import java.io.*;
/**
* @description:完成文件传输服务
* @author: 1223
**/
public class FileClientService {
/**
*
* @param src 源文件
* @param dest 传输到哪里
* @param senderId 发送人ID
* @param getterId 接收人ID
*/
public void sendFileToOne(String src,String dest,String senderId,String getterId){
// 读取src文件 -- 封装到Message
Message message = new Message();
message.setMesType(MessageType.MESSAGE_FILE_MES);
message.setSender(senderId);
message.setGetter(getterId);
message.setSrc(src);
message.setDest(dest);
//将文件读取
FileInputStream fileInputStream = null;
byte[] fileBytes = new byte[(int)new File(src).length()];
try {
fileInputStream = new FileInputStream(src);
fileInputStream.read(fileBytes);//将src读入到程序的字节数组
//将字节数组设置到message对象
message.setFileBytes(fileBytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(fileInputStream !=null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("\n"+senderId+"给"+getterId+"发送了"+src+"到对方电脑的目录"+dest);
//发送
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(MangerClientServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
objectOutputStream.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)MangerClientServerThread类
package com.ckx.qqclient.service;
import java.util.HashMap;
/**
* @description:管理客户端连接到服务器端的线程的一个类
* @author: 1223
**/
public class MangerClientServerThread {
//将多个线程放入HashMap集合
private static HashMap<String,ClientConnectServerThread> hm = new HashMap<>();
public static void addClientConnectServerThread(String userId,ClientConnectServerThread clientConnectServerThread){
hm.put(userId,clientConnectServerThread);
}
//通过一个方法,可以得到对应线程
public static ClientConnectServerThread getClientConnectServerThread(String userId){
return hm.get(userId);
}
}
(4)MessageClientService类
package com.ckx.qqclient.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Date;
/**
* @description:提供和消息相关的服务
* @author: 1223
**/
public class MessageClientService {
public void SendMessageToAll(String content,String senderId){
Message message = new Message();
message.setMesType(MessageType.MESSAGE_TO_ALL_MES);
message.setSender(senderId);
message.setContent(content);
message.setSendTime(new Date().toString());
System.out.println(senderId+"对大家说"+content);
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(MangerClientServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
objectOutputStream.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessageToOne(String content,String senderId,String getterId){
Message message = new Message();
message.setMesType(MessageType.MESSAGE_COMM_MES);
message.setGetter(getterId);
message.setSender(senderId);
message.setContent(content);
message.setSendTime(new Date().toString());
System.out.println(senderId+"对你说"+content);
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(MangerClientServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
objectOutputStream.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
(5)UserClientService类
package com.ckx.qqclient.service;
import com.ckx.qqcommon.Message;
import com.ckx.qqcommon.MessageType;
import com.ckx.qqcommon.User;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
/**
* @description:完成用户登录验证和用户注册等功能
* @author: 1223
**/
public class UserClientService {
//可能要在其他地方设置User/Socket信息,因此设置成成员属性
private User u = new User();
private Socket socket;
public boolean checkUser(String userId,String pwd){
boolean b= false;
//创建User
u.setUserId(userId);
u.setPasswd(pwd);
try {
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9999);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
objectOutputStream.writeObject(u);//发送User对象
//读取从服务端回送的Message对象
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
Message ms = (Message) objectInputStream.readObject();
if(ms.getMesType().equals(MessageType.MESSAGE_LOGIN_SUCCEED)){
b = true;
ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);
clientConnectServerThread.start();
MangerClientServerThread.addClientConnectServerThread(userId,clientConnectServerThread);
}else {//如果登录失败,就不能启动线程,就关闭
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
//向服务器请求在线用户列表
public void onlineFriendList(){
Message message = new Message();
message.setMesType(MessageType.MESSAGE_GET_ONLINE_FRIEND);
message.setSender(u.getUserId());
//发送给服务器
//应该得到当前线程的Socket对应的对象
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream
(MangerClientServerThread.getClientConnectServerThread(u.getUserId()).getSocket().getOutputStream());
objectOutputStream.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
public void logout(){
Message message = new Message();
message.setMesType(MessageType.MESSAGE_CLIENT_EXIT);
message.setSender(u.getUserId());
try {
ObjectOutputStream objectOutputStream = new ObjectOutputStream
(MangerClientServerThread.getClientConnectServerThread(u.getUserId()).getSocket().getOutputStream());
objectOutputStream.writeObject(message);
System.out.println(u.getUserId()+"退出系统");
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
(6)QQView类
package com.ckx.qqclient.view;
import com.ckx.qqclient.service.FileClientService;
import com.ckx.qqclient.service.MessageClientService;
import com.ckx.qqclient.service.UserClientService;
import com.ckx.qqclient.utils.Utility;
/**
* @description:客户端菜单界面
* @author: 1223
**/
public class QQView {
private boolean loop = true;//控制是否显示菜单
private String key = "";//接收用户输入
private UserClientService userClientService = new UserClientService();
//用于消息的发送
private MessageClientService messageClientService = new MessageClientService();
private FileClientService fileClientService = new FileClientService();//用于传输文件
public static void main(String[] args) {
new QQView().mainMenu();
System.out.println("客户端退出系统");
}
//显示主菜单
private void mainMenu(){
while (loop){
System.out.println("============欢迎登录网络通信系统============");
System.out.println("\t\t 1 登录系统");
System.out.println("\t\t 9 退出系统");
System.out.println("请输入你的选择:");
key = Utility.readString(1);//限制字符长度为1
switch (key){
case "1":
System.out.println("请输入用户ID:");
String userId = Utility.readString(50);
System.out.println("请输入密码:");
String pwd = Utility.readString(50);
//接下来去服务器端验证是否合法
if(userClientService.checkUser(userId,pwd)){
System.out.println("============欢迎"+userId+"============");
while (loop){
System.out.println("\n============已进入网络通讯系统============");
System.out.println("\t\t 1 显示在线用户列表");
System.out.println("\t\t 2 群发消息");
System.out.println("\t\t 3 私聊");
System.out.println("\t\t 4 发送文件");
System.out.println("\t\t 9 退出系统");
key = Utility.readString(1);
switch (key){
case "1":
userClientService.onlineFriendList();
break;
case "2":
System.out.println("请输入想对大家说的话:");
String s = Utility.readString(100);
messageClientService.SendMessageToAll(s,userId);
break;
case "3":
System.out.println("请输入想聊天的用户号:");
String getterId = Utility.readString(50);
System.out.println("你想说什么:");
String content = Utility.readString(100);
messageClientService.sendMessageToOne(content,userId,getterId);
break;
case "4":
System.out.println("请输入你要向谁发文件:");
getterId = Utility.readString(50);
System.out.println("请输入发送文件的路径(d:\\xx.jpg):");
String src = Utility.readString(100);
System.out.println("请输入把文件发送到对方的路径(d:\\yy.jpg):");
String dest = Utility.readString(100);
fileClientService.sendFileToOne(src,dest,userId,getterId);
break;
case "9":
userClientService.logout();
loop = false;
break;
}
}
}else {//登录服务器失败
System.out.println("登录失败");
}
break;
case "9":
loop =false;
break;
}
}
}
}
3.qqcommon代码
(1)Message类
package com.ckx.qqcommon;
import java.io.Serializable;
/**
* @description:表示客户端和服务器端通信时的消息对象
* @author: 1223
**/
public class Message implements Serializable {
private static final long serialVersionUID = 1L;//保证兼容性
private String sender;//发送方
private String getter;//接收方
private String content;//消息内容
private String sendTime;//发送时间
private String mesType;//消息类型
//
private byte[] fileBytes;
private int fileLen = 0;
private String dest;//将文件传输到哪里
private String src;//源文件地址
public byte[] getFileBytes() {
return fileBytes;
}
public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
}
public int getFileLen() {
return fileLen;
}
public void setFileLen(int fileLen) {
this.fileLen = fileLen;
}
public String getDest() {
return dest;
}
public void setDest(String dest) {
this.dest = dest;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getGetter() {
return getter;
}
public void setGetter(String getter) {
this.getter = getter;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getMesType() {
return mesType;
}
public void setMesType(String mesType) {
this.mesType = mesType;
}
}
(2)MessageType类
package com.ckx.qqcommon;
/**
* @description:表示消息类型
* @author: 1223
**/
public interface MessageType {
String MESSAGE_LOGIN_SUCCEED = "1";//表示登录成功
String MESSAGE_LOGIN_FAIL = "2";//表示登录失败
String MESSAGE_COMM_MES = "3";//普通信息包
String MESSAGE_GET_ONLINE_FRIEND = "4";//要求返回在线用户列表
String MESSAGE_RET_ONLINE_FRIEND = "5";//返回在线用户列表
String MESSAGE_CLIENT_EXIT = "6";//客户端请求退出
String MESSAGE_TO_ALL_MES = "7";//普通信息包
String MESSAGE_FILE_MES = "8";//文件消息
String MESSAGE_TO_ALL_NEWS = "9";//新闻
}
(3)User类
package com.ckx.qqcommon;
import java.io.Serializable;
/**
* @description:表示一个用户信息
* @author: 1223
**/
public class User implements Serializable {
private static final long serialVersionUID = 1L;//保证兼容性
private String userId;
private String passwd;
public User(String userId, String passwd) {
this.userId = userId;//用户ID
this.passwd = passwd;//密码
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
}
4.工具类
package com.ckx.qqclient.utils;
/**
* @description:
* @author:
**/
/**
工具类的作用:
处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
*/
import java.util.*;
/**
*/
public class Utility {
//静态属性。。。
private static Scanner scanner = new Scanner(System.in);
/**
* 功能:读取键盘输入的一个菜单选项,值:1——5的范围
* @return 1——5
*/
public static char readMenuSelection() {
char c;
for (; ; ) {
String str = readKeyBoard(1, false);//包含一个字符的字符串
c = str.charAt(0);//将字符串转换成字符char类型
if (c != '1' && c != '2' &&
c != '3' && c != '4' && c != '5') {
System.out.print("选择错误,请重新输入:");
} else break;
}
return c;
}
/**
* 功能:读取键盘输入的一个字符
* @return 一个字符
*/
public static char readChar() {
String str = readKeyBoard(1, false);//就是一个字符
return str.charAt(0);
}
/**
* 功能:读取键盘输入的一个字符,如果直接按回车,则返回指定的默认值;否则返回输入的那个字符
* @param defaultValue 指定的默认值
* @return 默认值或输入的字符
*/
public static char readChar(char defaultValue) {
String str = readKeyBoard(1, true);//要么是空字符串,要么是一个字符
return (str.length() == 0) ? defaultValue : str.charAt(0);
}
/**
* 功能:读取键盘输入的整型,长度小于2位
* @return 整数
*/
public static int readInt() {
int n;
for (; ; ) {
String str = readKeyBoard(10, false);//一个整数,长度<=10位
try {
n = Integer.parseInt(str);//将字符串转换成整数
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
* 功能:读取键盘输入的 整数或默认值,如果直接回车,则返回默认值,否则返回输入的整数
* @param defaultValue 指定的默认值
* @return 整数或默认值
*/
public static int readInt(int defaultValue) {
int n;
for (; ; ) {
String str = readKeyBoard(10, true);
if (str.equals("")) {
return defaultValue;
}
//异常处理...
try {
n = Integer.parseInt(str);
break;
} catch (NumberFormatException e) {
System.out.print("数字输入错误,请重新输入:");
}
}
return n;
}
/**
* 功能:读取键盘输入的指定长度的字符串
* @param limit 限制的长度
* @return 指定长度的字符串
*/
public static String readString(int limit) {
return readKeyBoard(limit, false);
}
/**
* 功能:读取键盘输入的指定长度的字符串或默认值,如果直接回车,返回默认值,否则返回字符串
* @param limit 限制的长度
* @param defaultValue 指定的默认值
* @return 指定长度的字符串
*/
public static String readString(int limit, String defaultValue) {
String str = readKeyBoard(limit, true);
return str.equals("")? defaultValue : str;
}
/**
* 功能:读取键盘输入的确认选项,Y或N
* 将小的功能,封装到一个方法中.
* @return Y或N
*/
public static char readConfirmSelection() {
System.out.println("请输入你的选择(Y/N): 请小心选择");
char c;
for (; ; ) {//无限循环
//在这里,将接受到字符,转成了大写字母
//y => Y n=>N
String str = readKeyBoard(1, false).toUpperCase();
c = str.charAt(0);
if (c == 'Y' || c == 'N') {
break;
} else {
System.out.print("选择错误,请重新输入:");
}
}
return c;
}
/**
* 功能: 读取一个字符串
* @param limit 读取的长度
* @param blankReturn 如果为true ,表示 可以读空字符串。
* 如果为false表示 不能读空字符串。
*
* 如果输入为空,或者输入大于limit的长度,就会提示重新输入。
* @return
*/
private static String readKeyBoard(int limit, boolean blankReturn) {
//定义了字符串
String line = "";
//scanner.hasNextLine() 判断有没有下一行
while (scanner.hasNextLine()) {
line = scanner.nextLine();//读取这一行
//如果line.length=0, 即用户没有输入任何内容,直接回车
if (line.length() == 0) {
if (blankReturn) return line;//如果blankReturn=true,可以返回空串
else continue; //如果blankReturn=false,不接受空串,必须输入内容
}
//如果用户输入的内容大于了 limit,就提示重写输入
//如果用户如的内容 >0 <= limit ,我就接受
if (line.length() < 1 || line.length() > limit) {
System.out.print("输入长度(不能大于" + limit + ")错误,请重新输入:");
continue;
}
break;
}
return line;
}
}