Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3392c15
忽略 .idea 文件夹
May 23, 2023
2978db2
建立代码框架;开发 unpack 部分。
May 23, 2023
680ae07
追加打印
seedjyh May 23, 2023
8b8eba3
修正 offset 计算
seedjyh May 23, 2023
97a17c0
完成 unpack
seedjyh May 23, 2023
25dd366
开发打包代码:实现 offset
May 24, 2023
63e9ed1
实现 version part
May 24, 2023
2c73f25
实现 record part parsePlainText
May 24, 2023
3303b39
调整 version part 方法顺序
May 24, 2023
4ba592b
实现了 record part bytes
May 24, 2023
a31aa84
实现了 index part parsePlainText
May 24, 2023
e36cee0
实现了 index part bytes
May 24, 2023
f1a7151
实现了 pack
May 24, 2023
3953ac8
version 0.1.0
May 24, 2023
c48719f
重构:将文件操作移动到 main 里。
May 24, 2023
6618459
将 unpack 部分的文件操作移动到 main
May 24, 2023
4a10105
开发新的 version part parse 和 bytesPlainText
May 24, 2023
54a70b6
开发新的 offset parse
May 24, 2023
b38427f
开发新的 record Parse
May 24, 2023
519fb85
开发新的 record part BytesPlainText
May 24, 2023
a639673
开发新的 index part parse
May 24, 2023
a2cd8b1
开发新的 index part bytesPlainText
May 24, 2023
49d2548
开发新的 pack.unpack
May 24, 2023
9163b55
plaintext 文件名放在 main 里。
May 24, 2023
6be29d4
彻底删除 unpack 包。
May 24, 2023
78e4db0
彻底删除 query 包。
May 24, 2023
15d4606
重构完成,并加入了号码查询功能。
May 24, 2023
0ad63e6
更新说明文档。加入了查询功能说明,以及更详细的文本修改说明。
May 24, 2023
afa57c7
version 0.2.0
May 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/.idea
24 changes: 24 additions & 0 deletions CHANGELOG.phoneatatool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# CHANGELOG.phoneatatool

## [0.2.0] - 2023-05-21

### 新增

- 实现了号码查询功能。

### 改动

- 说明文档更清晰了。

### 修复

## [0.1.0] - 2023-05-21

### 新增

- 实现了打包功能。
- 实习了解包功能。

### 改动

### 修复
120 changes: 120 additions & 0 deletions README.phonedatatool.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# README.phonedatatool.md

工具 phonedatatool 用于对给定 phone.dat 的解包和打包。

## 1. 使用方法

- 第一步:将原始二进制文件解包成文本。
- 第二步:根据需要手动修改文本。
- 第三步:将修改后的文本打包成二进制文件。
- 第四步:用修改后的二进制文件查询号码。

## 2. 解包

```shell
D:\seedjyh\phonedata>phonedatatool.exe -unpack -i phone.dat -o tmp
Unpack completed.
```

可以将二进制文件 phone.dat 解包到一个名为 abc 的目录。里面有三个文本文件。

## 3. 打包

```shell
D:\seedjyh\phonedata>phonedatatool.exe -pack -i tmp -o phone.2.dat
Pack completed.
```

可以将目录 abc 里的文本文件打包成二进制文件 phone.2.dat

## 4. 查询号码

```shell
D:\seedjyh\phonedata>phonedatatool.exe -query -i phone.2.dat -number 13336061916
PhoneNum: 13336061916
AreaZone: 0571
CardType: 中国电信
City: 杭州
ZipCode: 310000
Province: 浙江
Query completed.
```

## 5. 解包后文件说明

解包后的目录下会产生 3 个文本文件,功能分别是:

| 文件名 | 原始二进制文件 |
| ----------- | --------------------------------------------- |
| version.txt | 版本号 |
| record.txt | 记录区(省、市、邮编、区号) |
| index.txt | 索引区(号码前 7 位、记录区偏移量、号码类型) |

### 5.1. version.txt

里面应该是 4 个字符。比如 "2307"。

### 5.2. record.txt

有多行,每行包括一条记录,例如`1|安徽|巢湖|238000|0551`。

由竖线分隔成 5 段,含义分别是:

| 例子 | 含义 |
| ------ | --------- |
| 1 | 记录区 ID |
| 安徽 | 省名 |
| 巢湖 | 城市名 |
| 238000 | 邮政编码 |
| 0551 | 区号 |

其中「记录区 ID」必须是整数,不一定要连续,但每行的「记录区 ID」必须不同。

### 5.3. index.txt

有多行,每行包括一条索引,例如`1300000|251|2`

由竖线分隔成 3 段,含义分别是:

| 例子 | 含义 |
| ------- | ----------------------------------- |
| 1300000 | 手机号码前 7 位 |
| 251 | 记录区 ID(含义见 record.txt 章节) |
| 2 | 卡片类型码 |

### 5.4. 文本文件修改方式

#### 5.4.1. 新增一个号码段

如果一个号码段(前七位)在索引文件 index.txt 里没有,则可以直接在 index.txt 末尾加入一条记录。

如果这个号段前缀归属于 record.txt 里已有的某一地区,则「记录区 ID」直接填该地区的 ID 即可。

否则,需要先在 record.txt 里添加一条记录(注意新记录的 ID 必须和已有的所有 ID 均不相同),然后再往 index.txt 里添加记录。

#### 5.4.2. 修改一个号码段

直接修改该号码段在 index.txt 里的信息即可。例如,将「记录区 ID」修改成另一个数。必要时也要先在 record.txt 里新增记录。

#### 5.4.3. 删除一个号码段

直接删除 index.txt 里的信息即可。

#### 5.4.4. 备注

所有文本文件都必须以换行符结尾。

## 6. 备注

### 6.1. 卡片类型码

卡片类型码的含义由 phonedata 原项目规定。目前(2023-05-24)类型码的含义为:

| 卡片类型码 | 卡片类型 |
| ---------- | -------------- |
| 1 | 中国移动 |
| 2 | 中国联通 |
| 3 | 中国电信 |
| 4 | 电信虚拟运营商 |
| 5 | 联通虚拟运营商 |
| 6 | 移动虚拟运营商 |
197 changes: 197 additions & 0 deletions cmd/phonedatatool/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package main

import (
"flag"
"fmt"
"github.com/xluohome/phonedata/phonedatatool/pack"
"github.com/xluohome/phonedata/phonedatatool/util"
"os"
"path"
)

// 这里编译出来的可执行程序具备打包、查询、解包三个功能。
// ./phonedatatool -unpack -i phone.dat -o tmp
// ./phonedatatool -pack -i tmp -o phone.dat
// ./phonedatatool -query -i phone.dat -number 13000001234

const (
Name = "phonedatatool"
Version = "0.2.0"
Author = "seedjyh@gmail.com"
FullName = Name + "_" + Version + "(" + Author + ")"
)

const (
VersionFileName = "version.txt"
RecordFileName = "record.txt"
IndexFileName = "index.txt"
)

func main() {
showVersionFlag := flag.Bool("v", false, "Just show version string")
showHelpFlag := flag.Bool("help", false, "Just print help.")
unpackFlag := flag.Bool("unpack", false, "Unpack phone data to plain text")
packFlag := flag.Bool("pack", false, "Pack plain text to phone data")
queryFlag := flag.Bool("query", false, "Query number from phone data")
source := flag.String("i", "", "Source of operation")
destination := flag.String("o", "", "Destination of operation")
number := flag.String("number", "", "Number to query")
flag.Parse()
if *showVersionFlag {
fmt.Println("Version:", FullName)
return
}
if *showHelpFlag {
showHelp()
return
}
if *unpackFlag {
if source == nil {
fmt.Println("ERROR! No source")
return
}
if destination == nil {
fmt.Println("ERROR! No destination")
return
}
if err := Unpack(*source, *destination); err != nil {
fmt.Println("ERROR! Unpack failed.", err)
return
} else {
fmt.Println("Unpack completed.")
return
}
}
if *packFlag {
if source == nil {
fmt.Println("ERROR! No source")
return
}
if destination == nil {
fmt.Println("ERROR! No destination")
return
}
if err := Pack(*source, *destination); err != nil {
fmt.Println("ERROR! Pack failed.", err)
return
} else {
fmt.Println("Pack completed.")
return
}
}
if *queryFlag {
if source == nil {
fmt.Println("ERROR! No source")
return
}
if number == nil {
fmt.Println("ERROR! No number to query")
return
}
if err := QueryNumber(*source, *number); err != nil {
fmt.Println("ERROR! Query failed.", err)
return
} else {
fmt.Println("Query completed.")
return
}
}
fmt.Println("Did nothing.")
showHelp()
return
}

func showHelp() {
fmt.Println("<< HELP >>")
fmt.Println("./phonedatatool -unpack -i phone.dat -o tmp")
fmt.Println("./phonedatatool -pack -i tmp -o phone.dat")
fmt.Println("./phonedatatool -query -i phone.dat -n 13000001234")
}

func Pack(plainDirectoryPath string, phoneDataFilePath string) error {
if err := util.AssureFileNotExist(phoneDataFilePath); err != nil {
return err
}
var versionPlainTextBuf []byte
if buf, err := os.ReadFile(path.Join(plainDirectoryPath, VersionFileName)); err != nil {
return err
} else {
versionPlainTextBuf = buf
}

var recordPlainTextBuf []byte
if buf, err := os.ReadFile(path.Join(plainDirectoryPath, RecordFileName)); err != nil {
return err
} else {
recordPlainTextBuf = buf
}

var indexPlainTextBuf []byte
if buf, err := os.ReadFile(path.Join(plainDirectoryPath, IndexFileName)); err != nil {
return err
} else {
indexPlainTextBuf = buf
}

if buf, err := pack.NewPacker().Pack(versionPlainTextBuf, recordPlainTextBuf, indexPlainTextBuf); err != nil {
return err
} else {
return os.WriteFile(phoneDataFilePath, buf, 0)
}
}

func Unpack(phoneDataFilePath string, plainDirectoryPath string) error {
if err := os.MkdirAll(plainDirectoryPath, 0); err != nil {
return fmt.Errorf("target directory %v not exist and can't be created: %v", plainDirectoryPath, err)
}

versionFilePath := path.Join(plainDirectoryPath, VersionFileName)
recordFilePath := path.Join(plainDirectoryPath, RecordFileName)
indexFilePath := path.Join(plainDirectoryPath, IndexFileName)

if err := util.AssureAllFileNotExist(versionFilePath, recordFilePath, indexFilePath); err != nil {
return err
}

var rawBuf []byte
if b, err := os.ReadFile(phoneDataFilePath); err != nil {
return err
} else {
rawBuf = b
}

if versionPlainTextBuf, recordPlainTextBuf, indexPlainTextBuf, err := pack.NewUnpacker().Unpack(rawBuf); err != nil {
return err
} else {
if err := os.WriteFile(versionFilePath, versionPlainTextBuf, 0); err != nil {
return err
}
if err := os.WriteFile(recordFilePath, recordPlainTextBuf, 0); err != nil {
return err
}
if err := os.WriteFile(indexFilePath, indexPlainTextBuf, 0); err != nil {
return err
}
return nil
}
}

func QueryNumber(phoneDataFilePath string, number string) error {
var rawBuf []byte
if b, err := os.ReadFile(phoneDataFilePath); err != nil {
return err
} else {
rawBuf = b
}
if info, err := pack.NewQuerier().Query(rawBuf, number); err != nil {
return err
} else {
fmt.Println("PhoneNum: ", info.PhoneNumber)
fmt.Println("AreaZone: ", info.AreaCode)
fmt.Println("CardType: ", info.CardTypeID.ToName().String())
fmt.Println("City: ", info.CityName)
fmt.Println("ZipCode: ", info.ZipCode)
fmt.Println("Province: ", info.ProvinceName)
return nil
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/xluohome/phonedata

go 1.16

require github.com/stretchr/testify v1.8.3
Loading