We Talk -- 团队博客
WeTalk --在线群聊程序
团队博客
服务器一直在运行,使用客户端可直接登入使用。(做得很粗糙...)
0.项目介绍
现在我们网上交流离不开微信和QQ,当然在方便的同时也有风险,像在大企业内部而言,用QQ,微信等,容易造成信息泄露,进而造成巨大的损失,这个时候一个只用于企业内部交流的系统的重要性就凸显出来了。所以我们小组决定做一个在线群聊系统。
1 团队名称、团队成员介绍(需要有照片)
WT队
成员:
网络1513 王威(201521123076)
网络1512 倪兢飞(201521123061)
网络1513 秦贞一(201521123072)
2 项目git地址
项目地址(http://git.oschina.net/SlickGhostjava/wetalk/tree/master/)
3 项目git提交记录截图(要体现出每个人的提交记录、提交说明),老师将点击进去重点考核。
王威
秦贞一
倪兢飞
4 项目功能架构图与主要功能流程图
4.0项目分析及规划:
系统分为两大类,客户端和服务器,客户端就是用户使用的部分,有登录界面,注册界面,菜单界面,聊天界面。对于服务器,主要作用为维护数据库以及处理客户端的消息,有如登入验证,用户注册,消息转发等。
本次项目主要涉及到Swing,输入输出流,socket,数据库相关内容。Swing设计界面,socket和输入输出用于实现客户端和服务端之间的消息收发,数据库模块用于信息管理。
根据实际情况,每个人擅长的部分,合理分配任务。
4.1.客户端与服务端功能模块设计
4.2.通信协议设计
本次实现的是一个面向小群体的在线群聊系统,考虑到用户访问量不大,所以涉及到的连接均采用基于TCP的安全可靠通信模型。 以后若要实现用户之间的单聊,可采用UDP通信协议。
4.3.表设计:
- 用户信息表(users)
字段 | 解释 | 类型 | 字段长度 |
---|---|---|---|
number | 账号 | int | 5 |
password | 密码 | Nvarchar | 15 |
netName | 网名 | Nvarchar | 40 |
sign | 签名 | Nvarchar | 40 |
telephone | 电话 | Nvarchar | 11 |
isVIP | 是否会员 | int | 1 |
4.4.流程图
5 项目运行截图
服务端启动:
日志文件记录相关信息
客户端运行截图
首先进入登录界面
若该账号没有注册则提示错误
点击注册按钮,进入注册界面
注册成功后,登录:
登录成功,跳出聊天界面:
点击加入群聊:
此时要是再有人加入:
群成员那边有提示,
此时进行聊天:
2017-6-26,增加文件上传下载功能,使用缓冲,利用DataOutputStream和DataInputStream在套接字中传输
因为服务器放在TX云主机上,而且现在网速略慢...传到一半手动给终止了,只接受到3721KB。假如架设在局域网内,那么传输速度是很快的。在本机上测试,200+MB文件大概10s多。
下载文件
6 项目关键代码(不能太多)
客户端:
/*
*
* 初始化客户端
* 功能:
* 1.建立socket连接
* 2.返回登入验证结果
* 3.返回是否注册成功结果
*
* @author Wang
*
* 2017-6-21
*
* update:2017-6-26
*/
public class initClient {
public ClientReadThread getReadThread() {
return readThread;
}
public void setReadThread(ClientReadThread readThread) {
this.readThread = readThread;
}
public Socket getSocket() {
return socket;
}
public void setSocket(Socket socket) {
this.socket = socket;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void setObjectout(ObjectOutputStream objectout) {
this.objectout = objectout;
}
public void setObjectin(ObjectInputStream objectin) {
this.objectin = objectin;
}
ClientReadThread readThread;
Socket socket;
private ObjectOutputStream objectout;
private ObjectInputStream objectin;
private int port = 7890;
private User user;
// private String address = "127.0.0.1";
private String address = "119.29.19.94";
private String downloadFilePath = "H:\\Client\\";
//重新连接
public initClient() {
try {
this.Connection();
} catch (IOException e) {
e.printStackTrace();
}
}
public ObjectOutputStream getObjectout() {
return objectout;
}
public ObjectInputStream getObjectin() {
return objectin;
}
public void Connection() throws IOException{
try {
socket = new Socket(address, port);
} catch (IOException e) {
e.printStackTrace();
}
objectin = new ObjectInputStream(socket.getInputStream());
objectout = new ObjectOutputStream(socket.getOutputStream());
}
//验证用户
public boolean sendUserToServerLogin(User user) throws IOException, ClassNotFoundException{
String str = new String("login");
objectout.writeObject(str);
objectout.flush();
objectout.writeObject(user);
objectout.flush();
//输入对象, 一定要flush()
//验证结果
while(true){
String msg = objectin.readObject().toString();
System.out.println(msg);
if(msg.equals("true")){
return true;
}
else {
socket.close();
return false;
}
}
}
//注册用户
public boolean sendUserToServerRegister(User user) throws IOException, ClassNotFoundException{
objectout.writeObject("register");
objectout.flush();
objectout.writeObject(user);
objectout.flush();
//输入对象, 一定要flush()
//返回是否注册成功
while(true){
String msg = objectin.readObject().toString();
if(msg.equals("true")){
// socket.close();
return true;
}
else {
socket.close();
return false;
}
}
}
//加载用户信息
public User loadUser(Integer number) throws IOException, ClassNotFoundException{
objectout.writeObject("loadUser");
objectout.flush();
objectout.writeObject(number);
objectout.flush();
while(true){
Object obj = objectin.readObject();
if(obj instanceof User){
user = (User) obj;
socket.close();
return user;
}
else {
socket.close();
return null;
}
}
}
//成功进入群聊后,开启监听线程
public boolean enterGroup(User user,ChatJFrame chatFrame) throws IOException, ClassNotFoundException{
objectout.writeObject("enterGroup");
objectout.flush();
System.out.println(user);
objectout.writeObject(user);
objectout.flush();
System.out.println("flush");
//开启监听线程
this.startClintReadThread(chatFrame);
return true;
}
//监听线程
public void startClintReadThread(ChatJFrame chatFrame){
readThread = new ClientReadThread(objectin,chatFrame);
readThread.start();
}
//退出群聊
public void quitGrpou(){
try {
objectout.writeObject("quitGroup");
objectout.flush();
//关闭监听线程
readThread.interrupt();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//退出客户端
public void quitWTClient(){
try {
objectout.writeObject("quit");
objectout.flush();
//关闭监听线程
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//发送文件至服务器
public void sendFlieToServer(String fileName) throws ClassNotFoundException{
try {
Connection();
//要发送的文件绝对路径
File file=new File(fileName);
// System.out.println(fileName);
objectout.writeObject("sendFileToServer");
objectout.flush();
//文件名
objectout.writeObject(file.getName());
objectout.flush();
DataOutputStream dos=new DataOutputStream(socket.getOutputStream());
DataInputStream dis=new DataInputStream(
new BufferedInputStream(new FileInputStream(fileName)));
//缓冲区
int buffferSize=1024;
byte[]bufArray=new byte[buffferSize];
while (true) {
int read = 0;
if (dis!= null) {
read = dis.read(bufArray);
}
if (read == -1) {
break;
}
dos.write(bufArray, 0, read);
}
dis.close();
dos.flush();
dos.close();
this.socket.close();
JOptionPane.showMessageDialog(null, "上传成功",
"提示 ", JOptionPane.ERROR_MESSAGE);
} catch (IOException e) {
e.printStackTrace();
}
}
public void downloadFileFromServer(String fileName) throws IOException {
objectout.writeObject("downloadFileFromServer");
objectout.flush();
objectout.writeObject(fileName);
objectout.flush();
DataInputStream dis = new DataInputStream(new BufferedInputStream(
this.socket.getInputStream()));
int bufferSize = 1024;
// 缓冲区
byte[] buf = new byte[bufferSize];
//写入文件至目录
DataOutputStream fileOut = new DataOutputStream(
new BufferedOutputStream(new BufferedOutputStream(
new FileOutputStream(downloadFilePath+fileName))));
while (true) {
int read = 0;
if (dis!= null) {
read = dis.read(buf);
}
if (read == -1) {
break;
}
fileOut.write(buf, 0, read);
}
fileOut.close();
JOptionPane.showMessageDialog(null, "下载成功,保存在目录H:\\Client\\",
"提示 ", JOptionPane.ERROR_MESSAGE);
}
}
/*
*
* UserDao模式实现类
* 功能
* 1.检验登入功能
* 2.注册功能
* 3.加载用户信息
* 4.进入群聊后启动监听线程
* 5.文件上传与下载
*
*/
public class ClientUserDaoimpl implements ClientUserDao {
public ClientUserDaoimpl(){
}
public initClient getNewClient() {
return newClient;
}
public void setNewClient(initClient newClient) {
this.newClient = newClient;
}
private initClient newClient;
@Override
public boolean Login(User user) {
newClient = new initClient();
try {
//查看返回结果
if(newClient.sendUserToServerLogin(user))return true;
else return false;
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean Register(User user) {
newClient = new initClient();
try {
if(newClient.sendUserToServerRegister(user))return true;
else return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
@Override
public User loadUser(int number) {
try {
newClient = new initClient();
return newClient.loadUser(number);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
@Override
public boolean enterGroup(User user,ChatJFrame chatFrame) {
try {
newClient = new initClient();
chatFrame = new ChatJFrame(this);
chatFrame.setVisible(true);
return newClient.enterGroup(user,chatFrame);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
@Override
public void quitGroup() {
newClient.quitGrpou();
}
public void quitWTClient(){
newClient.quitWTClient();
}
@Override
public void sendFileToServer(String fileName) {
try {
newClient = new initClient();
newClient.sendFlieToServer(fileName);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void downloadFileFromServer(String fileName) throws IOException {
newClient = new initClient();
newClient.downloadFileFromServer(fileName);
}
}
服务端
//初始化配置
public class InitAll {
//服务器存储文件位置
// public String serverFliePath = "F:\\";
public String serverFliePath = "/java/WTServerFiles/";
// 重新连接次数
public int reconnect = 3;
// 数据库用户名密码
// public static String dbUserName = "root";
// public static String dbPassword = "root";
public static String dbUserName = "user_user";
public static String dbPassword = "...";
//日志保存位置
// public String logPath = "H://Serverlog.log";
public String logPath = "/java/Serverlog.log";
}
/*
*
* 服务端主线程
* 实例化的时候建立连接
* 运行后开启监听
* @author Wang
* 2017-6-20
* update 6-26
*/
public class MainThread extends Thread{
//在线用户列表
public static final List<ServerReadThread>
onLineUserList = new ArrayList<ServerReadThread>();
ServerReadThread serverReadThread;
ServerSocket serverSocket;
Socket socket;
boolean isStop;
//同时开启UDPServer
// UDPServer udpServer;
public MainThread(){
// udpServer = new UDPServer(this);
int port = 7890;
try {
//建立服务
serverSocket = new ServerSocket(port);
} catch (IOException e1) {
e1.printStackTrace();
}
}
@Override
public void run() {
while(isStop==false){
//监听
try {
socket = serverSocket.accept();
serverReadThread = new ServerReadThread(this,new InitAll());
serverReadThread.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
*
* 服务器消息监听线程
* 通过标识来实现不同功能
* 2017-6-20
*
* update:2017-6-20
* 增加文件读取
*
*/
public class ServerReadThread extends Thread {
//服务器文件存储位置
String serverFliePath;
ObjectOutputStream objectout;
ObjectInputStream objectin;
MainThread mainThread;
boolean flag;
int reconnect;
ServerUserDaoJDBCImpl serverUserDaoJDBCImpl;
User user;
String mgs;
Object obj;
InitAll init;
//初始化文件存储位置等配置...
private void initThis(){
this.serverFliePath = init.serverFliePath;
this.reconnect = init.reconnect;
}
public ServerReadThread(MainThread mainThread,InitAll init){
this.init = init;
initThis();
this.mainThread = mainThread;
serverUserDaoJDBCImpl = new ServerUserDaoJDBCImpl();
try {
objectout = new ObjectOutputStream(mainThread.socket.getOutputStream());
objectin = new ObjectInputStream(mainThread.socket.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void run() {
while(Thread.interrupted()==false){
if(reconnect < 0){System.out.println("break connect " );try {
mainThread.socket.close();
} catch (IOException e) {
e.printStackTrace();
}break;}
else{
try {
// System.out.println("当前线程个数0000="+ mainThread.onLineUserList.size());
obj = objectin.readObject();
if(obj!=null)
mgs = obj.toString();
System.out.println(this.mainThread.socket.getInetAddress() +":"+
this.mainThread.socket.getPort() + " request:" +mgs);
//0.关闭请求
if(mgs.equals("quit"))destoryThread(mgs);
//1.登入请求,接收到一个User对象,验证其用户名和密码
if(mgs.equals("login")){
if((obj = objectin.readObject()) !=null && obj instanceof User){
User user = (User)obj;
if(serverUserDaoJDBCImpl.checkUser(user)){
ServerRunLog.log.info("User("+user.getNumber()+") Login." );
objectout.writeObject("true");
objectout.flush();
destoryThread(mgs);
}
else{
objectout.writeObject("false");
objectout.flush();
destoryThread(mgs);
}
}
}
//2.注册请求,接收到一个User对象,如果插入数据库成功,则返回ture
if(mgs.equals("register")){
if((obj = objectin.readObject()) !=null){
User user = (User)obj;
if(serverUserDaoJDBCImpl.writeUser(user)){
ServerRunLog.log.info("Add User:"+user);
objectout.writeObject("true");
objectout.flush();
destoryThread(mgs);
}
else{
objectout.writeObject("false");
objectout.flush();
destoryThread(mgs);
}
}
}
//3.用户要进入群聊提示,接收到一个user对象,用来业务处理(告知其他用户等)
if(mgs.equals("enterGroup")){
if((obj = objectin.readObject()) !=null ){
User user = (User)obj;
this.user = user;
//若有用户进入群聊,则将其地址和端口加入HashMap
MainThread.onLineUserList.add(this);
String message = null;
if(user.getIsVip() == 0)
message = user.getNetName()+ " 进入了群聊室\n";
else message = "尊贵的 " + user.getNetName()+ " 进入了群聊室\n";
//遍历List,获取所有进入群聊用户线程,用于发送消息
for (int i = 0; i < MainThread.onLineUserList.size(); i++) {
MainThread.onLineUserList.get(i).objectout.writeObject("welcomeMessage");
MainThread.onLineUserList.get(i).objectout.flush();
// System.out.println("当前线程个数1="+MainThread.onLineUserList.size());
MainThread.onLineUserList.get(i).objectout.writeObject(message + "\n");
MainThread.onLineUserList.get(i).objectout.flush();
}
}
}
//4.加载用户信息请求
if(mgs.equals("loadUser")){
if((obj = objectin.readObject()) !=null && obj instanceof Integer){
Integer number = (Integer)obj;
User user = serverUserDaoJDBCImpl.loadUser(number);
objectout.writeObject(user);
objectout.flush();
destoryThread(mgs);
}
else{
objectout.writeObject("false");
objectout.flush();
destoryThread(mgs);
}
}
//5.下线
if(mgs.equals("quitGroup")){
MainThread.onLineUserList.remove(this);
System.out.println("当前群聊在线人数"+
MainThread.onLineUserList.size());
}
//6.普通信息
if(mgs.equals("message")){
String groupMsg = user.getNetName() + ": " + objectin.readObject().toString();
for (int i = 0; i < MainThread.onLineUserList.size(); i++) {
MainThread.onLineUserList.get(i).objectout.writeObject("groupMessage");
MainThread.onLineUserList.get(i).objectout.flush();
//System.out.println("当前线程个数1="+ MainThread.onLineUserList.size());
MainThread.onLineUserList.get(i).objectout.writeObject(groupMsg + "\n");
MainThread.onLineUserList.get(i).objectout.flush();
}
}
//下载文件,查看文件目录
if(mgs.equals("browseFiles")){
File file = new File(serverFliePath);
System.out.println(file.getName());
destoryThread(mgs);
}
if(mgs.equals("downloadFileFromServer")){
//接受文件名
String fileName = serverFliePath+objectin.readObject().toString();
File file=new File(fileName);
DataOutputStream dos=new DataOutputStream(
mainThread.socket.getOutputStream());
DataInputStream dis=new DataInputStream(
new BufferedInputStream(new FileInputStream(fileName)));
//缓冲区
int buffferSize=1024;
byte[]bufArray=new byte[buffferSize];
while (true) {
int read = 0;
if (dis!= null) {
read = dis.read(bufArray);
}
if (read == -1) {
break;
}
dos.write(bufArray, 0, read);
}
dis.close();
dos.flush();
dos.close();
System.out.println("transFile"+fileName+"succeed");
destoryThread(mgs);
}
//上传文件,把文件添加到服务器
if(mgs.equals("sendFileToServer")){
if((obj = objectin.readObject()) !=null){
//接受文件名信息
String fileName = obj.toString();
DataInputStream dis = new DataInputStream(new BufferedInputStream(
mainThread.socket.getInputStream()));
int bufferSize = 1024;
// 缓冲区
byte[] buf = new byte[bufferSize];
//写入文件至目录
DataOutputStream fileOut = new DataOutputStream(
new BufferedOutputStream(new BufferedOutputStream(
new FileOutputStream(serverFliePath+fileName))));
while (true) {
int read = 0;
if (dis!= null) {
read = dis.read(buf);
}
if (read == -1) {
break;
}
fileOut.write(buf, 0, read);
}
fileOut.close();
//读取结束
destoryThread(mgs);
}
}
}//try结束
catch (IOException e) {
flag = true;
reconnect--;
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//invalid type code: AC
//同一个线程里面多次用了用了new objectOutputStream(socket.getOutputStream());
}
}
}
private void destoryThread(String msg){
//System.out.println(msg + " request cause destory");
this.interrupt();
}
}
/*
*
* ServerUserDao模式
* 1.注册用户writeUser
* 2.读取用户信息loadUser
* 3.修改密码modifyPassword
* 4.修改网名modifyUsername
* 5.修改签名modifySign
* 6.验证用户checkUser
*/
public interface ServerUserDao {
public boolean writeUser(User user);
public User loadUser(int number);
//public boolean createFile(User user);
public boolean modifyUsername(User user);
public boolean modifyPassword(User user);
//public boolean modifySign(User user);
public boolean checkUser(User user);
}
7 尚待改进或者新的想法
由于时间有限,只实现单一的群聊功能,以后可以陆续添加单聊,文件共享等功能
聊天过程使用UDP,建立几张用户关系表,登入等请求使用现在已经完成的TCP部分,就可以实现单聊。文件上传下载使用TCP,利用缓冲技术加速。
对于账号查询功能:
8 团队成员任务分配,团队成员课程设计博客链接(以表格形式呈现),标明组长。
组员 | 负责模块 | 个人博客地址 |
---|---|---|
王威(组长) | 总体布局以及实现群聊,文件共享功能 | slickghost |
倪兢飞 | 数据库相关模块 | JMUNJF |
秦贞一 | 界面设计与实现 | wish-tree |
We Talk -- 团队博客的更多相关文章
- BAT 技术团队博客
1. 美团技术团队博客: 地址: http://tech.meituan.com/ 2. 腾讯社交用户体验设计(ISUX) 地址:http://isux.tencent.com/ 3. 京东设计中心 ...
- 2014年团队博客TOP10
2014年通过这个团队博客,葡萄城共输出了51篇原创技术博客(含翻译),总阅读超过9万人次,约有1万人次是通过RSS订阅方式阅读,总评论超过500人次. 这里我们通过阅读排序,选出2014年团队博客T ...
- 必应缤纷桌面的必应助手-软件分析和用户市场需求之-----二.体验部分 Ryan Mao (毛宇11061171) (完整版本请参考团队博客)
<必应缤纷桌面的必应助手> 2.体验部分 Ryan Mao (毛宇11061171) (完整分析报告请参考团队博客http://www.cnblogs.com/Z-XML/) 我花了2天的 ...
- 团队博客——Sprint计划会议1
每日Scrum:第一天 会议时间:4.14.晚八点半 会议地点:基础教学楼一楼大厅 小组成员:郭庆樑,林彦汝,张金 认领人—使团队成员分工合作,保持团队的积极性. ID 名称(NAME) 重要性(IM ...
- java课程设计--猜数字(团队博客)
java课程设计--猜数字(团队博客) 1.团队名称以及团队成员介绍 团队名称:cz 团队成员:陈伟泽,詹昌锦 团队照片: 2.项目git地址 http://git.oschina.net/Devil ...
- JAVA课程设计——团队博客
JAVA课程设计--团队博客 1. 团队名称.团队成员介绍(需要有照片) 团队名称:"小羊吃蓝莓"小游戏 团队成员介绍: 成员 班级 学号 廖怡洁 网络1513 201521123 ...
- Java课程设计 学生基本信息管理系统 团队博客
学生基本信息管理系统团队博客 项目git地址 https://git.oschina.net/Java_goddess/kechengsheji 项目git提交记录截图 项目功能架构图与主要功能流程图 ...
- Do Now 一个让你静心学习的APP——团队博客
Do Now 一个让你静心学习的APP 来自油条只要半根团队的智慧凝聚的产物! 团队博客总目录: 团队作业第一周 团队作业第二周 Do Now -- 团队冲刺博客一 Do-Now-团队Scrum 冲刺 ...
- 团队博客-第六周:Alpha阶段项目复审(科利尔拉弗队)
团队的排名-点评:以下排名点评谨代表个人观点,如有冒犯,评论联系删除 小组名字和链接 优点 缺点,bug报告(至少140字) 最终名次(无并列) 中午吃啥队 微信小程序应用,新型app会是一个便利的使 ...
随机推荐
- RabbitMQ 使用(一)
RabbitMQ中的使用 这篇文章将会介绍关于RabbbitMQ的使用,并且使用的是kombo(客户端的Python实现)来实现: 安装 如果使用的是mac安装的话,可以先安装到指定的位置,接着配置命 ...
- Qt日常备注(函数/接口实现)
1.判断QString是否为纯数字 2.查找自身最长重复子字符串 3.树形列表复选框操作 4.更改文件权限 5.判断系统64位 6.文件生成md5值 7.版本号比较(字符串比较) //-----实现- ...
- ASP.NET MVC5写.php路由匹配时的问题 ASP.NET MVC 4 在 .NET 4.0 与.NET 4.5 的專案範本差異
由于外包公司结束合作,所以考虑把其APP服务替换过来,因原后台是用php写的,在不影响员客户端使用的情况下在MVC下重写路由配置实现处理原php链接地址的请求,但实现时发现怎么也匹配不到自己写的路由, ...
- 微信小程序源码推荐
wx-gesture-lock 微信小程序的手势密码 WXCustomSwitch 微信小程序自定义 Switch 组件模板 WeixinAppBdNovel 微信小程序demo:百度小说搜索 sh ...
- testNG java.net.SocketException: Software caused connection abort: socket write error
执行用例报错,提示 java.net.SocketException: Software caused connection abort: socket write error java.net.So ...
- JS中的函数、BOM和DOM操作
一.JS中的函数 [关于注释] /** [文档注释]:开头两个*.写在函数上方,在调用函数时可以看到文档上方的描述信息. */ // 单行注释 /* 多行注释 */ 1.函数的声明及调用 (1) ...
- 【Regular Expression】RE分类及案例
背景知识 正则表达式分为三类:基础正则表达式.扩展正则表达式.Perl正则表达式(Perl内建) 通俗来说,这三个一个比一个强大,支持的规则匹配字符更多 1.匹配IP ip addr | grep - ...
- .net 中常用的正则表达式整理
相信很多伙伴都跟我一样有关于正则表达式的爱和恨,怎么说呢? 因为正则表达式规则繁多且复杂,想一个一个学 全部精通,需要耗费很长时间和精力, 但是我们用的地方并不是很多,所以我觉得这类东西需要做成类似工 ...
- LNMP1.4环境中安装fileinfo插件
安装前: 安装前建议先执行 /usr/local/php/bin/php -m (此命令显示目前已经安装好的PHP模块)看一下,要安装的模块是否已安装. 然后下载当前PHP版本的源码并解压. 安装: ...
- oracle导库
cmd窗口直接输入导库命令即可,不需要进入sqlplus C:\Documents and Settings\Administrator> imp username/pass@orcl file ...