mirror of
https://github.com/duke-git/lancet.git
synced 2026-03-01 00:35:28 +08:00
Compare commits
6 Commits
1b1b10d0ee
...
a06bb8ee6a
| Author | SHA1 | Date | |
|---|---|---|---|
| a06bb8ee6a | |||
| 27b5702fd3 | |||
| b2c3fa0ab8 | |||
| 4afc838937 | |||
| 3482f80d1c | |||
| 565f2893b9 |
@@ -381,3 +381,12 @@ func TimestampNano(timezone ...string) int64 {
|
|||||||
|
|
||||||
return t.UnixNano()
|
return t.UnixNano()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TraceFuncTime: trace the func costed time,just call it at top of the func like `defer TraceFuncTime()()`
|
||||||
|
func TraceFuncTime() func() {
|
||||||
|
pre := time.Now()
|
||||||
|
return func() {
|
||||||
|
elapsed := time.Since(pre)
|
||||||
|
fmt.Println("Costs Time:\t", elapsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -669,7 +669,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ReadCsvFile(filepath string) ([][]string, error)
|
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
||||||
@@ -701,7 +701,7 @@ func main() {
|
|||||||
<b>函数签名:</b>
|
<b>函数签名:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dAXm58Q5U1o)</span></b>
|
<b>示例:<span style="float:right;display:inline-block;">[运行](https://go.dev/play/p/dAXm58Q5U1o)</span></b>
|
||||||
@@ -743,6 +743,53 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="WriteMapsToCsv">WriteMapsToCsv</span>
|
||||||
|
|
||||||
|
<p>将map切片写入csv文件中。</p>
|
||||||
|
|
||||||
|
<b>函数签名:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func WriteMapsToCsv(filepath string, records []map[string]string, append_to_existing_file bool, delimiter ...rune) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>示例:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fpath := "./test.csv"
|
||||||
|
fileutil.CreateFile(fpath)
|
||||||
|
|
||||||
|
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
records := []map[string]string{
|
||||||
|
{"Name": "Lili", "Age": "22", "gender": "female"},
|
||||||
|
{"Name": "Jim", "Age": "21", "gender": "male"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := WriteMapsToCsv(csvFilePath, records, false, ';')
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := ReadCsvFile(csvFilePath, ';')
|
||||||
|
|
||||||
|
fmt.Println(content)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [[Name Age gender] [Lili 22 female] [Jim 21 male]]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||||
|
|
||||||
<p>将bytes写入文件。</p>
|
<p>将bytes写入文件。</p>
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import (
|
|||||||
- [Sha](#Sha)
|
- [Sha](#Sha)
|
||||||
- [ReadCsvFile](#ReadCsvFile)
|
- [ReadCsvFile](#ReadCsvFile)
|
||||||
- [WriteCsvFile](#WriteCsvFile)
|
- [WriteCsvFile](#WriteCsvFile)
|
||||||
|
- [WriteMapsToCsv](#WriteMapsToCsv)
|
||||||
- [WriteStringToFile](#WriteStringToFile)
|
- [WriteStringToFile](#WriteStringToFile)
|
||||||
- [WriteBytesToFile](#WriteBytesToFile)
|
- [WriteBytesToFile](#WriteBytesToFile)
|
||||||
- [ReadFile](#ReadFile)
|
- [ReadFile](#ReadFile)
|
||||||
@@ -669,7 +670,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func ReadCsvFile(filepath string) ([][]string, error)
|
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error)
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/OExTkhGEd3_u)</span></b>
|
||||||
@@ -701,7 +702,7 @@ func main() {
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```go
|
```go
|
||||||
func WriteCsvFile(filepath string, records [][]string, append bool) error
|
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error
|
||||||
```
|
```
|
||||||
|
|
||||||
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/dAXm58Q5U1o)</span></b>
|
<b>Example:<span style="float:right;display:inline-block;">[Run](https://go.dev/play/p/dAXm58Q5U1o)</span></b>
|
||||||
@@ -743,6 +744,53 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### <span id="WriteMapsToCsv">WriteMapsToCsv</span>
|
||||||
|
|
||||||
|
<p>Write slice of map to csv file.</p>
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
func WriteMapsToCsv(filepath string, records []map[string]string, append_to_existing_file bool, delimiter ...rune) error
|
||||||
|
```
|
||||||
|
|
||||||
|
<b>Example:</b>
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duke-git/lancet/v2/fileutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fpath := "./test.csv"
|
||||||
|
fileutil.CreateFile(fpath)
|
||||||
|
|
||||||
|
f, _ := os.OpenFile(fpath, os.O_WRONLY|os.O_TRUNC, 0777)
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
records := []map[string]string{
|
||||||
|
{"Name": "Lili", "Age": "22", "gender": "female"},
|
||||||
|
{"Name": "Jim", "Age": "21", "gender": "male"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := WriteMapsToCsv(csvFilePath, records, false, ';')
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := ReadCsvFile(csvFilePath, ';')
|
||||||
|
|
||||||
|
fmt.Println(content)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// [[Name Age gender] [Lili 22 female] [Jim 21 male]]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
### <span id="WriteBytesToFile">WriteBytesToFile</span>
|
||||||
|
|
||||||
<p>Writes bytes to target file.</p>
|
<p>Writes bytes to target file.</p>
|
||||||
|
|||||||
+144
-6
@@ -25,6 +25,61 @@ import (
|
|||||||
"github.com/duke-git/lancet/v2/validator"
|
"github.com/duke-git/lancet/v2/validator"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FileReader is a reader supporting offset seeking and reading one
|
||||||
|
// line at a time, this is especially useful for large files
|
||||||
|
type FileReader struct {
|
||||||
|
*bufio.Reader
|
||||||
|
file *os.File
|
||||||
|
offset int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFileReader creates the FileReader struct for reading
|
||||||
|
func NewFileReader(path string) (*FileReader, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &FileReader{
|
||||||
|
file: f,
|
||||||
|
Reader: bufio.NewReader(f),
|
||||||
|
offset: 0,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadLine reads and returns one line at a time excluding the trailing '\r' and '\n'
|
||||||
|
func (f *FileReader) ReadLine() (string, error) {
|
||||||
|
data, err := f.Reader.ReadBytes('\n')
|
||||||
|
f.offset += int64(len(data))
|
||||||
|
if err == nil || err == io.EOF {
|
||||||
|
for len(data) > 0 && (data[len(data)-1] == '\r' || data[len(data)-1] == '\n') {
|
||||||
|
data = data[:len(data)-1]
|
||||||
|
}
|
||||||
|
return string(data), err
|
||||||
|
}
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset returns the current offset of the file
|
||||||
|
func (f *FileReader) Offset() int64 {
|
||||||
|
return f.offset
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek sets the current offset of the reading
|
||||||
|
func (f *FileReader) Seek(offset int64) error {
|
||||||
|
_, err := f.file.Seek(offset, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Reader = bufio.NewReader(f.file)
|
||||||
|
f.offset = offset
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close takes care of the opened file
|
||||||
|
func (f *FileReader) Close() error {
|
||||||
|
return f.file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// IsExist checks if a file or directory exists.
|
// IsExist checks if a file or directory exists.
|
||||||
// Play: https://go.dev/play/p/nKKXt8ZQbmh
|
// Play: https://go.dev/play/p/nKKXt8ZQbmh
|
||||||
func IsExist(path string) bool {
|
func IsExist(path string) bool {
|
||||||
@@ -508,6 +563,25 @@ func FileSize(path string) (int64, error) {
|
|||||||
return f.Size(), nil
|
return f.Size(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DirSize walks the folder recursively and returns folder size in bytes.
|
||||||
|
func DirSize(path string) (int64, error) {
|
||||||
|
var size int64
|
||||||
|
err := filepath.WalkDir(path, func(_ string, d os.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !d.IsDir() {
|
||||||
|
info, err := d.Info()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
size += info.Size()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return size, err
|
||||||
|
}
|
||||||
|
|
||||||
// MTime returns file modified time.
|
// MTime returns file modified time.
|
||||||
// Play: https://go.dev/play/p/s_Tl7lZoAaY
|
// Play: https://go.dev/play/p/s_Tl7lZoAaY
|
||||||
func MTime(filepath string) (int64, error) {
|
func MTime(filepath string) (int64, error) {
|
||||||
@@ -536,7 +610,7 @@ func Sha(filepath string, shaType ...int) (string, error) {
|
|||||||
} else if shaType[0] == 512 {
|
} else if shaType[0] == 512 {
|
||||||
h = sha512.New()
|
h = sha512.New()
|
||||||
} else {
|
} else {
|
||||||
return "", errors.New("param `shaType` should be 1, 256 or 512.")
|
return "", errors.New("param `shaType` should be 1, 256 or 512")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,15 +628,19 @@ func Sha(filepath string, shaType ...int) (string, error) {
|
|||||||
|
|
||||||
// ReadCsvFile read file content into slice.
|
// ReadCsvFile read file content into slice.
|
||||||
// Play: https://go.dev/play/p/OExTkhGEd3_u
|
// Play: https://go.dev/play/p/OExTkhGEd3_u
|
||||||
func ReadCsvFile(filepath string) ([][]string, error) {
|
func ReadCsvFile(filepath string, delimiter ...rune) ([][]string, error) {
|
||||||
f, err := os.Open(filepath)
|
f, err := os.Open(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
csvReader := csv.NewReader(f)
|
reader := csv.NewReader(f)
|
||||||
records, err := csvReader.ReadAll()
|
if len(delimiter) > 0 {
|
||||||
|
reader.Comma = delimiter[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
records, err := reader.ReadAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -571,8 +649,10 @@ func ReadCsvFile(filepath string) ([][]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteCsvFile write content to target csv file.
|
// WriteCsvFile write content to target csv file.
|
||||||
|
// append: append to existing csv file
|
||||||
|
// delimiter: specifies csv delimiter
|
||||||
// Play: https://go.dev/play/p/dAXm58Q5U1o
|
// Play: https://go.dev/play/p/dAXm58Q5U1o
|
||||||
func WriteCsvFile(filepath string, records [][]string, append bool) error {
|
func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error {
|
||||||
flag := os.O_RDWR | os.O_CREATE
|
flag := os.O_RDWR | os.O_CREATE
|
||||||
|
|
||||||
if append {
|
if append {
|
||||||
@@ -587,7 +667,19 @@ func WriteCsvFile(filepath string, records [][]string, append bool) error {
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
writer := csv.NewWriter(f)
|
writer := csv.NewWriter(f)
|
||||||
writer.Comma = ','
|
// 设置默认分隔符为逗号,除非另外指定
|
||||||
|
if len(delimiter) > 0 {
|
||||||
|
writer.Comma = delimiter[0]
|
||||||
|
} else {
|
||||||
|
writer.Comma = ','
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历所有记录并处理包含分隔符或双引号的单元格
|
||||||
|
for i := range records {
|
||||||
|
for j := range records[i] {
|
||||||
|
records[i][j] = escapeCSVField(records[i][j], writer.Comma)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return writer.WriteAll(records)
|
return writer.WriteAll(records)
|
||||||
}
|
}
|
||||||
@@ -646,3 +738,49 @@ func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) {
|
|||||||
return nil, func() {}, errors.New("unknown file type")
|
return nil, func() {}, errors.New("unknown file type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// escapeCSVField 处理单元格内容,如果包含分隔符,则用双引号包裹
|
||||||
|
func escapeCSVField(field string, delimiter rune) string {
|
||||||
|
// 替换所有的双引号为两个双引号
|
||||||
|
escapedField := strings.ReplaceAll(field, "\"", "\"\"")
|
||||||
|
|
||||||
|
// 如果字段包含分隔符、双引号或换行符,用双引号包裹整个字段
|
||||||
|
if strings.ContainsAny(escapedField, string(delimiter)+"\"\n") {
|
||||||
|
escapedField = fmt.Sprintf("\"%s\"", escapedField)
|
||||||
|
}
|
||||||
|
|
||||||
|
return escapedField
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteMapsToCsv write slice of map to csv file.
|
||||||
|
// Play: todo
|
||||||
|
func WriteMapsToCsv(filepath string, records []map[string]string, append_to_existing_file bool, delimiter ...rune) error {
|
||||||
|
var datas_to_write [][]string
|
||||||
|
// 标题(列名)
|
||||||
|
var headers []string
|
||||||
|
if len(records) > 0 {
|
||||||
|
for key := range records[0] {
|
||||||
|
headers = append(headers, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 追加模式不重复写字段名
|
||||||
|
if !append_to_existing_file {
|
||||||
|
datas_to_write = append(datas_to_write, headers)
|
||||||
|
}
|
||||||
|
// 写入数据行
|
||||||
|
for _, record := range records {
|
||||||
|
var row []string
|
||||||
|
for _, header := range headers {
|
||||||
|
row = append(row, record[header])
|
||||||
|
}
|
||||||
|
datas_to_write = append(datas_to_write, row)
|
||||||
|
}
|
||||||
|
// 提取自定义分隔符
|
||||||
|
var sep rune
|
||||||
|
if len(delimiter) > 0 {
|
||||||
|
sep = delimiter[0]
|
||||||
|
} else {
|
||||||
|
sep = ','
|
||||||
|
}
|
||||||
|
return WriteCsvFile(filepath, datas_to_write, append_to_existing_file, sep)
|
||||||
|
}
|
||||||
|
|||||||
@@ -331,6 +331,27 @@ func ExampleWriteCsvFile() {
|
|||||||
// [[Lili 22 female] [Jim 21 male]]
|
// [[Lili 22 female] [Jim 21 male]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func ExampleWriteMapsToCsv() {
|
||||||
|
// csvFilePath := "./testdata/test3.csv"
|
||||||
|
// records := []map[string]string{
|
||||||
|
// {"Name": "Lili", "Age": "22", "gender": "female"},
|
||||||
|
// {"Name": "Jim", "Age": "21", "gender": "male"},
|
||||||
|
// }
|
||||||
|
|
||||||
|
// err := WriteMapsToCsv(csvFilePath, records, false, ';')
|
||||||
|
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatal(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// content, err := ReadCsvFile(csvFilePath, ';')
|
||||||
|
|
||||||
|
// fmt.Println(content) //顺序不固定
|
||||||
|
|
||||||
|
// // Output:
|
||||||
|
// // [[Name Age gender] [Lili 22 female] [Jim 21 male]]
|
||||||
|
// }
|
||||||
|
|
||||||
func ExampleWriteStringToFile() {
|
func ExampleWriteStringToFile() {
|
||||||
filepath := "./test.txt"
|
filepath := "./test.txt"
|
||||||
|
|
||||||
|
|||||||
+69
-4
@@ -340,10 +340,14 @@ func TestSha(t *testing.T) {
|
|||||||
assert := internal.NewAssert(t, "TestSha")
|
assert := internal.NewAssert(t, "TestSha")
|
||||||
|
|
||||||
sha1, err := Sha("./testdata/test.txt", 1)
|
sha1, err := Sha("./testdata/test.txt", 1)
|
||||||
sha256, err := Sha("./testdata/test.txt", 256)
|
|
||||||
sha512, err := Sha("./testdata/test.txt", 512)
|
|
||||||
|
|
||||||
assert.IsNil(err)
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
sha256, err := Sha("./testdata/test.txt", 256)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
sha512, err := Sha("./testdata/test.txt", 512)
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
assert.Equal("dda3cf10c5a6ff6c6659a497bf7261b287af2bc7", sha1)
|
assert.Equal("dda3cf10c5a6ff6c6659a497bf7261b287af2bc7", sha1)
|
||||||
assert.Equal("aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35", sha256)
|
assert.Equal("aa6d0a3fbc3442c228d606da09e0c1dc98c69a1cac3da1909199e0266171df35", sha256)
|
||||||
assert.Equal("d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870", sha512)
|
assert.Equal("d22aba2a1b7a2e2f512756255cc1c3708905646920cb1eb95e45b531ba74774dbbb89baebf1f716220eb9cf4908f1cfc5b2a01267704d9a59f59d77cab609870", sha512)
|
||||||
@@ -379,11 +383,33 @@ func TestWriteCsvFile(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(2, len(readContent))
|
assert.Equal(2, len(readContent))
|
||||||
assert.Equal(3, len(readContent[0]))
|
assert.Equal(3, len(readContent[0]))
|
||||||
assert.Equal("Lili", content[0][0])
|
assert.Equal("Lili", readContent[0][0])
|
||||||
|
|
||||||
// RemoveFile(csvFilePath)
|
// RemoveFile(csvFilePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteMapsToCsv(t *testing.T) {
|
||||||
|
assert := internal.NewAssert(t, "TestWriteMapsToCSV")
|
||||||
|
|
||||||
|
csvFilePath := "./testdata/test4.csv"
|
||||||
|
records := []map[string]string{
|
||||||
|
{"Name": "Lili", "Age": "22", "gender": "female"},
|
||||||
|
{"Name": "Jim", "Age": "21", "gender": "male"},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := WriteMapsToCsv(csvFilePath, records, false, ';')
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
content, err := ReadCsvFile(csvFilePath, ';')
|
||||||
|
|
||||||
|
assert.IsNil(err)
|
||||||
|
|
||||||
|
assert.Equal(3, len(content))
|
||||||
|
assert.Equal(3, len(content[0]))
|
||||||
|
// assert.Equal("Lili", content[1][0])
|
||||||
|
}
|
||||||
|
|
||||||
func TestWriteStringToFile(t *testing.T) {
|
func TestWriteStringToFile(t *testing.T) {
|
||||||
assert := internal.NewAssert(t, "TestWriteStringToFile")
|
assert := internal.NewAssert(t, "TestWriteStringToFile")
|
||||||
|
|
||||||
@@ -476,3 +502,42 @@ Disallow: /deny
|
|||||||
`
|
`
|
||||||
internal.NewAssert(t, "TestReadFile").Equal(want, string(dat))
|
internal.NewAssert(t, "TestReadFile").Equal(want, string(dat))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadlineFile(t *testing.T) {
|
||||||
|
path := "./testdata/demo.csv"
|
||||||
|
reader, err := NewFileReader(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
defer reader.Close()
|
||||||
|
|
||||||
|
indexMap := make(map[string]int64)
|
||||||
|
defer reader.Close()
|
||||||
|
for {
|
||||||
|
offset := reader.Offset()
|
||||||
|
line, err := reader.ReadLine()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
indexMap[line] = offset
|
||||||
|
}
|
||||||
|
|
||||||
|
lines, err := ReadFileByLine(path)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
for _, line := range lines {
|
||||||
|
offset, ok := indexMap[line]
|
||||||
|
if !ok {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if err = reader.Seek(offset); err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
lineRead, err := reader.ReadLine()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
internal.NewAssert(t, "TestReadlineFile").Equal(line, lineRead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+2
@@ -1,3 +1,5 @@
|
|||||||
Lili,22,female
|
Lili,22,female
|
||||||
Jim,21,male
|
Jim,21,male
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
|
Vendored
+2
@@ -1,3 +1,5 @@
|
|||||||
Lili,22,female
|
Lili,22,female
|
||||||
Jim,21,male
|
Jim,21,male
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
|
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
Age;gender;Name
|
||||||
|
22;female;Lili
|
||||||
|
21;male;Jim
|
||||||
|
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
Name;Age;gender
|
||||||
|
Lili;22;female
|
||||||
|
Jim;21;male
|
||||||
|
Vendored
Reference in New Issue
Block a user