玩具kv数据库
介紹
用java寫一個簡陋的kv數(shù)據(jù)庫(倆小時的貨),用來復(fù)習(xí)一下java流知識、線程、socket等知識。
客戶端:很簡單的寫了一下功能:就是發(fā)送用戶的命令,還有接收數(shù)據(jù)顯示出來 服務(wù)端:redis類:讀寫和操作數(shù)據(jù)庫(就是封裝了一堆map)socket類:接收命令,發(fā)送數(shù)據(jù)打開這兩個,然后在客戶端打命令即可。使用規(guī)范: *************************************** create tableName//創(chuàng)建表(最多一百個,可以改) 例:create stu//創(chuàng)建名為stu的表 *************************************** use tableName//操作表 例:use stu//操作名字為stu的表 *************************************** showall//打印所有表名 *************************************** 增:add key value 刪:delete key 改:change key 查:get key 是否存在:contains key *************************************** end//結(jié)束redis.java:
大概思路:
屬性:
?? ?private Map<String, String>[] r // 存儲所有表
?? ?private String[] tableName//存儲所有表名
?? ?private int num = 0;// 表數(shù)量
?? ?private int target;// 當(dāng)前操作的表
方法:
? ? 增刪改查
? ? 更換操作的表
? ? 打印
? ? 寫入硬盤
? ? 從硬盤讀出數(shù)據(jù)
? ? 接受命令并執(zhí)行,給反饋
package redisDemo01;import java.io.*; import java.util.*;public class redis {Scanner in = new Scanner(System.in);private Map<String, String>[] r = new Map[100];// 最多創(chuàng)建100個表private String[] tableName = new String[100];private int num = 0;// 表數(shù)量private int target;// 當(dāng)前操作的表// 創(chuàng)建表public void create(String name) {r[num] = new HashMap<String, String>();tableName[num] = name;target = num;num++;}// 操作表public void use(int target) {this.target = target;}public void use(String name) {for (int i = 0; i < num; i++) {if (tableName[i].equals(name)) {target = i;break;}}}// 判斷是否存在public boolean contains(String key) {return r[target].containsKey(key);}// 增public void add(String key, String value) {r[target].put(key, value);}// 刪public void delete(String key) {r[target].remove(key);}// 改public void change(String key, String value) {r[target].put(key, value);}// 查public String get(String key) {return r[target].get(key);}// 打印表public String show() {String ans = "";for (String key : r[target].keySet()) {ans = ans + key + " " + r[target].get(key) + " ";}return ans;}public String showAllTableName() {String anString="";for(int i=0;i<num;i++)anString=anString+i+":"+tableName[i];return anString;}//寫入硬盤public void write() {try {Writer writer = new FileWriter(new File("member.txt"));int i=0;//表的下標(biāo)while (i<num) {writer.write("table " + tableName[i] + "\r\n");//表名for (String key : r[i].keySet()) {writer.write(key + " " + r[i].get(key) + "\r\n");//數(shù)據(jù)}i++;}writer.close();} catch (IOException e) {e.printStackTrace();}}//讀數(shù)據(jù)public void read() {try {FileReader fileReader = new FileReader("member.txt");BufferedReader bufferedReader = new BufferedReader(fileReader);String str;while ((str = bufferedReader.readLine()) != null) {String[] a = str.split(" ");if (a[0].equals("table")) {create(a[1]);//新表} else {add(a[0], a[1]);//表里的數(shù)據(jù)}}bufferedReader.close();fileReader.close();} catch (IOException e) {e.printStackTrace();}}// 接收命令public String command(String aString) {String ans = "success";String[] cmd = aString.split(" ");for (int i = 0; i < cmd.length; i++) {cmd[i] = cmd[i].replaceAll(" ", "");}String command = cmd[0];if (command.equals("create")) {create(cmd[1]);} else if (command.equals("use")) {use(cmd[1]);} else if (command.equals("add")) {add(cmd[1], cmd[2]);} else if (command.equals("contains")) {if (contains(cmd[1]))ans = "This key exists";elseans = "This key does not exists";} else if (command.equals("get")) {ans = "key:" + cmd[1] + " value:" + get(cmd[1]);} else if (command.equals("delete")) {delete(cmd[1]);} else if (command.equals("show")) {ans = show();} else if (command.equals("showall")) {ans = showAllTableName();} else if (command.equals("end")) {write();return "end";}else {return "false,tryAgain";}return ans;} }socket.java
屬性:
?? ?String cmd;// 命令
?? ?redis r0 // 數(shù)據(jù)庫
?? ?String returnText // 給客戶看的信息
方法:
? ? 主要任務(wù)是和客戶端通信,接受命令,發(fā)出客戶看到的界面數(shù)據(jù)。
package redisDemo01;import java.io.*; import java.net.*;public class socket implements Runnable {String cmd;// 命令redis r0 = new redis();// 數(shù)據(jù)庫String returnText = "success";// 給客戶看的信息public void run() {try {r0.read();ServerSocket serverSocket = new ServerSocket(12016);do {Socket socket = serverSocket.accept();InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();byte[] cache = new byte[1024];is.read(cache);cmd = new String(cache);cmd = cmd.trim();// 去掉多余空格,這個bug調(diào)了半天System.out.println("redis > " + cmd);returnText = r0.command(cmd);//操作數(shù)據(jù)庫os.write(returnText.getBytes());// 給客戶打印的數(shù)據(jù)os.flush();is.close();os.close();} while (!returnText.equals("end"));// serverSocket.close();} catch (Exception e) {e.printStackTrace();}} }然后你run一下socket,服務(wù)端這邊就完事了。
ClientThread.java
接受客戶命令然后發(fā)給服務(wù)端
接受服務(wù)端處理完的數(shù)據(jù)
用自己的方式呈現(xiàn)給客戶(慚愧慚愧)
package Demo;import java.io.*; import java.net.*; import java.util.*;public class ClientThread implements Runnable {@Overridepublic void run() {try {while (true) {Scanner s = new Scanner(System.in);String temp = s.nextLine();Socket socket = new Socket("127.0.0.1", 12016);// 獲取輸入輸出流InputStream is = socket.getInputStream();OutputStream os = socket.getOutputStream();// 發(fā)送os.write(temp.getBytes());os.flush();// 接收byte[] cache = new byte[1024];is.read(cache);String a = new String(cache);if (temp.equals("show")) {//打印所有k——va = a.trim();//去空格String[] c = a.split(" ");for (int i = 0; i < c.length; i++) {c[i] = c[i].replaceAll(" ", "");}for (int i = 0; i < c.length - 1; i += 2)//依次打印k——vSystem.out.printf("key:%10s value:%10s\n", c[i], c[i + 1]);} elseSystem.out.println(a);os.close();socket.close();if (temp.equals("end"))break;}} catch (Exception e) {e.printStackTrace();}} }界面賊丑但是就是隨便練個手啦。。。
總結(jié)
- 上一篇: leetcode303 区域和检索
- 下一篇: leetcode57. 插入区间