前言
由於企業內部的一些考試需要,有些同事要時常通過一個word格式的題庫檔案來查詢相應題目,但在手機上用word進行查詢,總覺得操作上很不方便。藉著這個契機,應用Golang和Kotlin開發了一個小工具,方便同事可快捷的查詢題目。
也是希望把開發過程中的知識點記錄下來,方便以後複習,因為不知道什麼時候就會又一次忘了怎麼寫正則了。
雖然上面說了那麼多,其實就是想幫同事作弊 ლ(╹◡╹ლ)
題庫檔案參考
以下是我的題庫檔案,可參考: tiku.txt
單選題: (共912小題,總分:1分)
1 . ( )是銀行網點直接和顧客接觸的員工,因此在客戶建立對銀行網點第一印象、維持良好的銀行網點服務形象方面起著重要作用 (1.50分)
A 網點負責人
B 大堂經理
C 櫃員
D 客戶經理
標準答案 :C
試題解析 :
1,065 . 櫃員櫃面營銷與櫃面服務包括 (2分)
A 負責業務辦理間隙識別優質客戶的工作,並將客戶引導到最合適的服務渠道
B 保持頭、臉、手、著裝、修整、飾物的清潔、規範,保持職業化服務形象
C 執行站姿挺拔、坐姿端莊、行姿規範、行為檢點、微笑親和、致意得體、道歉真誠的服務要求,保持良好服務行為
D 執行聲音親和、語句清晰、措辭客氣、表達明瞭、稱呼準確、問候得體、適當寒暄的服務語言規範
E 負責詳細記錄客戶資訊,聆聽、發現客戶真實需求,為下一步客戶經理的關係維護打下基礎
標準答案 :A B C D E
試題解析 :
1,480 . 根據我社其它物品管理的規定,對於印章和鑰匙,對應的調撥機構為上級管理機構,而假幣上繳的對應上級機構為現金管理(分)中心。 (1分)
正確
錯誤
標準答案 :正確
複製程式碼
需求就是將這個檔案,儲存為sqlite資料庫檔案,並嵌到Android App裡。
第一步,使用正規表示式解析檔案,並拆分出題幹,選項,答案几個元素,再分別存入資料庫裡。
正則我用Golang實現,資料庫用sqlite ,因為最後這個資料庫是要給Android用的。
一: 先分析題幹部分:
1 . ( )是銀行網點直接和顧客接觸的員工,因此在客戶建立對銀行網點第一印象、維持良好的銀行網點服務形象方面起著重要作用 (1.50分)
可分為三個部分來解析
- 題序:[ 1 . ]
正則表達:
完整的正則: ^\s*?(?P<index>\d+,*?\d*?\s*?\.)\s*?
^\s*? 表示以0或1個以上的空格開頭 ,^表示匹配開頭
(?P<index>) 是golang的分組語法,在這裡不用理會
\d+,*?\d*?\s*?\.
\d+ : 表示1個以上的數字
,*? : 0或1個逗號 , 因文字里的題序格式類似這樣: 1,234 ,這個正則不支援 1,234,567 ,因為我覺得不太可能需要那麼大的數
\d*? : 表示0個以上的數字
\s*?\. : 若干空格並以 . 結束
複製程式碼
Golang 實現:
func findSubject(line string) (result bool, s string) {
reg := regexp.MustCompile(`^\s*?(?P<index>\d+,*?\d*?\s*?\.)\s*?(?P<subject>.*)(?P<score>\s*?(.*分))$`)
matches := reg.FindStringSubmatch(line)
if len(matches) > 0 {
return true, matches[2]
}
return false, ""
}
複製程式碼
- 題幹正文 : [( )是銀行網點直接和顧客接觸的員工,因此在客戶建立對銀行網點第一印象、維持良好的銀行網點服務形象方面起著重要作用 ]
分析題幹需要同時配合結尾來進行解析,可以明顯的看到,每道題都以(1.50分)這樣的格式結尾
(?P<subject>.*)(?P<score>\s*?(.*分))$
複製程式碼
二: 分析選項:
^\s?(?P<index>[A-Z]\s?)\s?(?P<content>.*)
選項總是以字母開頭,所以用 [A-Z] 匹配即可。
複製程式碼
Golang 實現:
func findOptions(line string) (result bool, s string) {
//判斷選擇題
reg := regexp.MustCompile(`^\s?(?P<index>[A-Z]\s?)\s?(?P<content>.*)`)
matches := reg.FindStringSubmatch(line)
if len(matches) > 0 {
return true, line
}
reg = regexp.MustCompile(`^(正確)|^(錯誤)`) //這裡需要注意,判斷題並不是以[A-Z]開頭的。
matches = reg.FindStringSubmatch(line)
if len(matches) > 0 {
return true, matches[0]
}
return false, ""
}
複製程式碼
分析答案就太簡單了:
func findAnswer(line string) (result bool, s string) {
matched, _ := regexp.MatchString(`^(標準答案 :)`, line)
if matched {
return true, line
}
return false, ""
}
複製程式碼
不多說了,最後就是儲存進sqlite了
func saveToDB() {
db, err := sql.Open("sqlite3", "./yee.db")
checkErr(err)
for _, q := range questionList {
stmt, err := db.Prepare(`INSERT INTO question(subject, options, answer) values(?,?,?)`)
checkErr(err)
res, err := stmt.Exec(q.Subject, strings.Join(q.Options, "||"), q.Answer) //選項之間用 || 分隔即可,簡單處理
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
}
}
複製程式碼
完整程式碼請參考Gayhub: https://github.com/yeelone/bankolin-demo
第二步,實現Android App
將第一步生成的 yee.db 資料庫檔案放進新建的Android專案裡,目錄為 src/main/res/raw ,
接著我們需要在APP啟動時,將yee.db檔案拷進android的資料檔案地址
先實現一個Helper類併為context進行擴充套件:
package com.example.elone.myapplication
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import org.jetbrains.anko.db.ManagedSQLiteOpenHelper
class DatabaseHelper(ctx: Context) : ManagedSQLiteOpenHelper(ctx, "yee.db", null, 1) {
companion object {
private var instance: DatabaseHelper? = null
@Synchronized
fun Instance(context: Context): DatabaseHelper {
if (instance == null) {
instance = DatabaseHelper(context.applicationContext)
}
return instance!!
}
}
override fun onCreate(database: SQLiteDatabase) {
}
override fun onUpgrade(database: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
}
}
val Context.database: DatabaseHelper
get() = DatabaseHelper.Instance(applicationContext)
複製程式碼
再接著回到MainActivity
private fun importDatabase() {
// 存放資料庫的目錄
var dirPath = "/data/data/"+PACKAGE_NAME+"/databases"
var dir = File(dirPath)
if (!dir.exists()) {
dir.mkdir()
}
// 資料庫檔案
var file = File(dir, "yee.db")
try {
if (!file.exists()) {
file.createNewFile()
}
// 載入需要匯入的資料庫
var instream: InputStream = this.applicationContext.resources.openRawResource(R.raw.yee)
var fos = FileOutputStream(file)
var buffer = ByteArray(instream.available())
instream.read(buffer)
fos.write(buffer)
instream.close()
fos.close()
} catch ( e: FileNotFoundException) {
e.printStackTrace()
}
}
複製程式碼
這是第一次用到kotlin Anko sqlite,記錄一下查詢語法:
private fun searchQuestion() {
val editText = findViewById<EditText>(R.id.searchText)
val rows = database.use {
select("question")
.whereSimple("(subject like '%"+editText.text+"%') ")
.exec {
parseList(classParser<Question>())
}
}
mListView.adapter = MainAdapter(rows)
}
複製程式碼
最終成果如圖:
歡迎訪問原文地址: Github Page