package main /* #include */ import "C" import ( "encoding/csv" "encoding/json" "fmt" "io" "os" "path/filepath" "strings" "sync" "sync/atomic" "time" "unsafe" ) // CSVManager CSV全局管理器 type CSVManager struct { files sync.Map // handle -> *CSVFile (并发安全的映射) nextHandle int64 // 生成唯一句柄 errorMsg string // 全局错误信息 mu sync.RWMutex // 管理器级别的锁 } // CSVFile 文件结构 type CSVFile struct { filename string // 实际文件路径 handle int64 // 唯一句柄 delimiter rune // 分隔符(如 ',') hasHeader bool // 是否有标题行 // 内存数据缓存 data [][]string // 内存中的数据行 header []string // 标题行(如果有) fileSize int64 // 文件大小 modified bool // 标记是否被修改 // 并发控制 mu sync.RWMutex // 文件级锁 rowLocks []*sync.RWMutex // 行级锁 rowMu sync.Mutex // 行锁数组保护 readers int32 // 活跃读取器计数 writers int32 // 活跃写入器计数 saving int32 // 正在保存的goroutine计数 saveErr chan error // 保存错误通道 done chan struct{} // 关闭信号 } // 单例模式的管理器 var manager *CSVManager var once sync.Once // newCSVFile 创建新的CSVFile对象 func newCSVFile(filename string, delimiter rune, hasHeader bool) *CSVFile { return &CSVFile{ filename: filename, delimiter: delimiter, hasHeader: hasHeader, data: make([][]string, 0), rowLocks: make([]*sync.RWMutex, 0), saveErr: make(chan error, 1), done: make(chan struct{}), } } // getManager 获取全局管理器(单例) func getManager() *CSVManager { once.Do(func() { manager = &CSVManager{ nextHandle: 1, } }) return manager } // setError 设置错误信息 func setError(err string) { mgr := getManager() mgr.mu.Lock() mgr.errorMsg = err mgr.mu.Unlock() } // 初始化管理器 func initCSVManager() int64 { _ = getManager() return 0 // 成功 } // 打开/创建CSV文件(句柄) func openCSVFile(filename string, delimiter rune, hasHeader bool) int64 { // 创建CSV全局管理器 mgr := getManager() // 先检查文件是否已经打开 var existingHandle int64 = -1 mgr.files.Range(func(key, value interface{}) bool { file := value.(*CSVFile) // 比较文件路径(使用绝对路径确保一致性) absFilename, _ := filepath.Abs(filename) absExisting, _ := filepath.Abs(file.filename) if absFilename == absExisting { fmt.Println("absFilename", absFilename) fmt.Println("absExisting", absExisting) fmt.Println("bool", absFilename == absExisting) existingHandle = key.(int64) return false // 停止遍历 } return true // 继续遍历 }) // 如果文件已经打开,返回现有句柄 if existingHandle != -1 { fmt.Printf("文件已打开,返回现有句柄: %d\n", existingHandle) return existingHandle } // 生成句柄 handle := atomic.AddInt64(&mgr.nextHandle, 1) // 创建文件对象 file := newCSVFile(filename, delimiter, hasHeader) file.handle = handle // 加载文件数据 if err := file.load(); err != nil { setError(err.Error()) return -1 } // 存储到管理器 mgr.files.Store(handle, file) return handle } // 读取多行数据 func readRows(handle int64, startRow, count int64, buffer []byte) int64 { mgr := getManager() // 获取文件对象 val, ok := mgr.files.Load(handle) if !ok { setError("Invalid file handle") return -1 } file := val.(*CSVFile) atomic.AddInt32(&file.readers, 1) defer atomic.AddInt32(&file.readers, -1) // 获取读取锁 file.mu.RLock() defer file.mu.RUnlock() totalRows := int64(len(file.data)) if startRow < 0 || startRow >= totalRows { return 0 } // 计算实际读取行数 endRow := startRow + count if endRow > totalRows { endRow = totalRows } rowsToRead := endRow - startRow // 将数据复制到缓冲区 bytesWritten := 0 for i := startRow; i < endRow; i++ { row := file.data[i] // 获取行读锁 if rowLock := file.getRowLock(int(i)); rowLock != nil { rowLock.RLock() } for _, cell := range row { // 写入单元格长度 cellLen := len(cell) if bytesWritten+4 > len(buffer) { break } // 写入4字节长度 buffer[bytesWritten] = byte(cellLen & 0xFF) buffer[bytesWritten+1] = byte((cellLen >> 8) & 0xFF) buffer[bytesWritten+2] = byte((cellLen >> 16) & 0xFF) buffer[bytesWritten+3] = byte((cellLen >> 24) & 0xFF) bytesWritten += 4 // 写入单元格数据 if bytesWritten+cellLen > len(buffer) { // 缓冲区不足,回退长度写入 bytesWritten -= 4 break } copy(buffer[bytesWritten:bytesWritten+cellLen], cell) bytesWritten += cellLen } // 写入行结束标记 if bytesWritten+4 <= len(buffer) { // 4字节的0表示行结束 buffer[bytesWritten] = 0 buffer[bytesWritten+1] = 0 buffer[bytesWritten+2] = 0 buffer[bytesWritten+3] = 0 bytesWritten += 4 } // 释放行锁 if rowLock := file.getRowLock(int(i)); rowLock != nil { rowLock.RUnlock() } if bytesWritten >= len(buffer) { break } } return rowsToRead } // 写入/覆盖行数据 func writeRows(handle int64, rowData [][]string, header int) int64 { mgr := getManager() // 获取文件对象 val, ok := mgr.files.Load(handle) if !ok { setError("文件无效句柄!") return -1 } file := val.(*CSVFile) // 获取写入锁 file.mu.Lock() defer file.mu.Unlock() atomic.AddInt32(&file.writers, 1) defer atomic.AddInt32(&file.writers, -1) // 清空现有数据(因为这是覆盖写入) file.data = make([][]string, 0, len(rowData)) if header == 0 { file.header = rowData[0] // 添加新数据 file.data = rowData[1:] } else { // 添加新数据 for _, row := range rowData { file.data = append(file.data, row) } } // 扩展行锁数组 file.rowMu.Lock() file.rowLocks = make([]*sync.RWMutex, len(file.data)) for i := range file.rowLocks { file.rowLocks[i] = &sync.RWMutex{} } file.rowMu.Unlock() file.modified = true // 异步保存到文件 go file.saveAsync() return int64(len(file.data)) } // 加载CSV文件到内存 func (f *CSVFile) load() error { f.mu.Lock() defer f.mu.Unlock() // 打开文件 file, err := os.Open(f.filename) if err != nil { // 文件不存在则创建空文件 if os.IsNotExist(err) { f.data = make([][]string, 0) // 初始化空数据 f.rowLocks = make([]*sync.RWMutex, 0) // 初始化空行锁数组 return nil } return fmt.Errorf("文件不存在: %v", err) } // 确保函数结束时关闭文件 defer file.Close() // 获取文件大小 stat, _ := file.Stat() // 获取文件信息 f.fileSize = stat.Size() // 获取文件大小 // 创建CSV读取器 reader := csv.NewReader(file) reader.Comma = f.delimiter // 设置分隔符(默认逗号) reader.LazyQuotes = true // 允许宽松的引号解析 reader.TrimLeadingSpace = true // 去除字段前的空格 // 关键修改:允许变长记录,不强制检查字段数量 reader.FieldsPerRecord = -1 firstRecord, err := reader.Read() if err != nil { if err == io.EOF { // 空文件 f.data = make([][]string, 0) f.rowLocks = make([]*sync.RWMutex, 0) return nil } return err } maxColumns := len(firstRecord) allData := [][]string{firstRecord} // 读取剩余行 for { record, err := reader.Read() if err == io.EOF { break } if err != nil { // 对于有问题的行,可以填充或跳过 continue } // 确保所有行都有相同的列数 if len(record) < maxColumns { // 填充缺失的列为空字符串 paddedRecord := make([]string, maxColumns) copy(paddedRecord, record) for i := len(record); i < maxColumns; i++ { paddedRecord[i] = "" } record = paddedRecord } else if len(record) > maxColumns { // 如果行有更多列,更新最大列数 maxColumns = len(record) // 重新处理之前的所有行 for i := range allData { if len(allData[i]) < maxColumns { paddedRecord := make([]string, maxColumns) copy(paddedRecord, allData[i]) allData[i] = paddedRecord } } } allData = append(allData, record) } if len(allData) == 0 { f.data = make([][]string, 0) f.rowLocks = make([]*sync.RWMutex, 0) return nil } // 处理表头 if f.hasHeader && len(allData) > 0 { f.header = allData[0] f.data = allData[1:] } else { f.data = allData } // 初始化行锁 f.initRowLocks() return nil } // initRowLocks 初始化行锁数组 func (f *CSVFile) initRowLocks() { count := len(f.data) f.rowLocks = make([]*sync.RWMutex, count) for i := 0; i < count; i++ { f.rowLocks[i] = &sync.RWMutex{} } } // getRowLock 获取行锁(线程安全) func (f *CSVFile) getRowLock(rowIndex int) *sync.RWMutex { if rowIndex < 0 { return nil } f.rowMu.Lock() defer f.rowMu.Unlock() // 确保行锁存在 if rowIndex >= len(f.rowLocks) { // 扩展行锁数组 newLocks := make([]*sync.RWMutex, rowIndex+1) copy(newLocks, f.rowLocks) for i := len(f.rowLocks); i <= rowIndex; i++ { newLocks[i] = &sync.RWMutex{} } f.rowLocks = newLocks } return f.rowLocks[rowIndex] } // save 保存到文件 func (f *CSVFile) save() error { // 标记正在保存 if !atomic.CompareAndSwapInt32(&f.saving, 0, 1) { // 已经在保存中,直接返回 return nil } defer atomic.StoreInt32(&f.saving, 0) // 如果没有修改,直接返回 f.mu.RLock() if !f.modified { f.mu.RUnlock() return nil } // 复制数据 dataCopy := make([][]string, len(f.data)) for i := range f.data { dataCopy[i] = make([]string, len(f.data[i])) copy(dataCopy[i], f.data[i]) } // 复制表头 headerCopy := make([]string, len(f.header)) copy(headerCopy, f.header) // 复制配置(值类型,直接赋值) hasHeader := f.hasHeader delimiter := f.delimiter filename := f.filename f.mu.RUnlock() // 释放读锁 // 创建临时文件(使用不同的扩展名避免冲突) tempFile := filename + ".tmp" file, err := os.Create(tempFile) if err != nil { return err } // 创建CSV写入器 writer := csv.NewWriter(file) writer.Comma = delimiter // 写入数据 if hasHeader && len(headerCopy) > 0 { if err := writer.Write(headerCopy); err != nil { file.Close() os.Remove(tempFile) return err } } if err := writer.WriteAll(dataCopy); err != nil { file.Close() os.Remove(tempFile) return err } writer.Flush() if err := writer.Error(); err != nil { file.Close() os.Remove(tempFile) return err } // 关闭文件,确保数据写入磁盘 if err := file.Close(); err != nil { os.Remove(tempFile) return err } // 尝试重命名,如果失败可能是文件被占用 var renameErr error for retry := 0; retry < 3; retry++ { renameErr = os.Rename(tempFile, filename) if renameErr == nil { break } time.Sleep(100 * time.Millisecond) // 等待重试 } if renameErr != nil { os.Remove(tempFile) return renameErr } // 标记为已保存 f.mu.Lock() f.modified = false f.mu.Unlock() return nil } // saveAsync 异步保存,带错误处理 func (f *CSVFile) saveAsync() { select { case f.saveErr <- f.save(): // 保存完成 default: // 通道已满,忽略错误 } } // 追加行数据 func appendRows(handle int64, rowsData []byte, rowCount int64) int { mgr := getManager() // 获取文件对象 val, ok := mgr.files.Load(handle) if !ok { setError("Invalid file handle") return -1 } file := val.(*CSVFile) // 获取写入锁 file.mu.Lock() atomic.AddInt32(&file.writers, 1) // 解析行数据 offset := 0 for i := int64(0); i < rowCount; i++ { var row []string // 读取行数据 for { if offset+4 > len(rowsData) { break } cellLen := int(uint32(rowsData[offset]) | uint32(rowsData[offset+1])<<8 | uint32(rowsData[offset+2])<<16 | uint32(rowsData[offset+3])<<24) offset += 4 if cellLen == 0 { break } if offset+cellLen > len(rowsData) { break } cell := string(rowsData[offset : offset+cellLen]) offset += cellLen row = append(row, cell) } // 追加到数据 file.data = append(file.data, row) } file.modified = true atomic.AddInt32(&file.writers, -1) file.mu.Unlock() // 异步保存 go file.saveAsync() // 获取总行数 count := getRowCount(handle) fmt.Println("count:", count) return int(count) } // 打开/创建CSV文件(句柄) func createOpenCSVFile(filename string, delimiter rune, hasHeader bool) int64 { // 创建CSV全局管理器 mgr := getManager() // 生成句柄 handle := atomic.AddInt64(&mgr.nextHandle, 1) // 创建文件对象 file := newCSVFile(filename, delimiter, hasHeader) file.handle = handle //// 加载文件数据 //if err := file.load(); err != nil { // setError(err.Error()) // return -1 //} // 存储到管理器 mgr.files.Store(handle, file) return handle } // updateCSVRowSafe 修改csv文件行数据 func updateCSVRowSafe(handleID int64, rowNum int, newRow []string) error { mgr := getManager() // 获取文件对象 val, ok := mgr.files.Load(handleID) if !ok { setError("Invalid file handle") return fmt.Errorf("无效句柄: %d", handleID) } file := val.(*CSVFile) // 1. 创建临时文件 tempDir := filepath.Dir(file.filename) if tempDir == "" { tempDir = "." } tempFile, err := os.CreateTemp(tempDir, "temp_*.csv") if err != nil { return fmt.Errorf("创建临时文件失败: %v", err) } tempFileName := tempFile.Name() // 确保临时文件被关闭和清理 defer func() { tempFile.Close() // 如果临时文件还存在(替换失败),则清理它 if _, err := os.Stat(tempFileName); err == nil { os.Remove(tempFileName) } }() // 2. 读取原始文件 sourceFile, err := os.Open(file.filename) if err != nil { return fmt.Errorf("打开源文件失败: %v", err) } defer sourceFile.Close() // 3. 读取并处理数据 reader := csv.NewReader(sourceFile) allRows, err := reader.ReadAll() if err != nil { return fmt.Errorf("读取CSV失败: %v", err) } // 4. 验证并更新 if rowNum < 1 || rowNum > len(allRows) { return fmt.Errorf("行号 %d 超出范围 (1-%d)", rowNum, len(allRows)) } // 显示修改前后的对比 oldRow := allRows[rowNum-1] fmt.Printf("修改前第 %d 行: %v\n", rowNum, oldRow) fmt.Printf("修改后第 %d 行: %v\n", rowNum, newRow) allRows[rowNum-1] = newRow // 5. 写入临时文件 writer := csv.NewWriter(tempFile) if err := writer.WriteAll(allRows); err != nil { return fmt.Errorf("写入临时文件失败: %v", err) } writer.Flush() if err := writer.Error(); err != nil { return fmt.Errorf("刷新写入失败: %v", err) } // 6. 确保数据写入磁盘 if err := tempFile.Sync(); err != nil { return fmt.Errorf("同步文件失败: %v", err) } tempFile.Close() // 7. 使用复制而不是重命名(解决Windows文件占用问题) if err := copyFile(tempFileName, file.filename); err != nil { return fmt.Errorf("复制文件失败: %v", err) } fmt.Printf("✅ 成功更新第 %d 行,文件已直接更新\n", rowNum) return nil } // copyFile 复制文件内容 func copyFile(src, dst string) error { // 打开源文件 source, err := os.Open(src) if err != nil { return err } defer source.Close() // 创建目标文件 destination, err := os.Create(dst) if err != nil { return err } defer destination.Close() // 复制内容 _, err = io.Copy(destination, source) if err != nil { return err } // 确保数据写入磁盘 err = destination.Sync() if err != nil { return err } return nil } // 获取总行数 func getRowCount(handle int64) int64 { mgr := getManager() val, ok := mgr.files.Load(handle) if !ok { setError("Invalid file handle") return -1 } file := val.(*CSVFile) file.mu.RLock() defer file.mu.RUnlock() if file.header != nil { return int64(len(file.data) + 1) } return int64(len(file.data)) } // 搜索行 func findRows(handle int64, searchText string, columnIndex int64, resultBuffer []byte, maxResults int64) int64 { mgr := getManager() val, ok := mgr.files.Load(handle) if !ok { setError("Invalid file handle") return -1 } file := val.(*CSVFile) file.mu.RLock() defer file.mu.RUnlock() atomic.AddInt32(&file.readers, 1) defer atomic.AddInt32(&file.readers, -1) var foundRows []int64 // 搜索行 for i, row := range file.data { if maxResults > 0 && int64(len(foundRows)) >= maxResults { break } // 获取行读锁 if rowLock := file.getRowLock(i); rowLock != nil { rowLock.RLock() } // 检查列 if columnIndex < 0 || columnIndex >= int64(len(row)) { // 搜索所有列 for _, cell := range row { if cell == searchText { foundRows = append(foundRows, int64(i)) break } } } else if row[columnIndex] == searchText { foundRows = append(foundRows, int64(i)) } // 释放行锁 if rowLock := file.getRowLock(i); rowLock != nil { rowLock.RUnlock() } } // 写入结果到缓冲区 if resultBuffer != nil && len(foundRows) > 0 { bytesWritten := 0 for _, rowIndex := range foundRows { if bytesWritten+8 > len(resultBuffer) { break } // 写入行索引(8字节) for j := 0; j < 8; j++ { resultBuffer[bytesWritten] = byte((rowIndex >> (uint(j) * 8)) & 0xFF) bytesWritten++ } } } return int64(len(foundRows)) } // 合并多个CSV文件(线程安全) func mergeCSVFiles(handles []int64, outputFilename string, delimiter rune, hasHeader bool) int64 { mgr := getManager() // 验证所有句柄并获取文件对象 files := make([]*CSVFile, 0, len(handles)) for _, handle := range handles { val, ok := mgr.files.Load(handle) if !ok { setError("Invalid file handle: " + string(handle)) return -1 } files = append(files, val.(*CSVFile)) } // 创建输出文件对象 outputFile := newCSVFile(outputFilename, delimiter, hasHeader) outputFile.modified = true // 标记为需要保存 // 第一步:合并表头 mergedHeader := make([]string, 0) headerSet := make(map[string]bool) if hasHeader { // 收集所有不重复的表头 for _, file := range files { file.mu.RLock() if file.hasHeader && len(file.header) > 0 { for _, h := range file.header { if !headerSet[h] { headerSet[h] = true mergedHeader = append(mergedHeader, h) } } } file.mu.RUnlock() } // 如果没有找到表头,创建一个默认的表头 if len(mergedHeader) == 0 && len(files) > 0 { files[0].mu.RLock() maxColumns := len(files[0].data[0]) files[0].mu.RUnlock() for i := 0; i < maxColumns; i++ { mergedHeader = append(mergedHeader, fmt.Sprintf("Column%d", i+1)) } } } outputFile.header = mergedHeader // 第二步:合并数据 mergedData := make([][]string, 0) // 为每个输入文件创建读取锁并并发读取 var wg sync.WaitGroup dataChan := make(chan [][]string, len(files)) errorChan := make(chan error, len(files)) for idx, file := range files { wg.Add(1) go func(fileIdx int, f *CSVFile) { defer wg.Done() // 获取文件的读取锁 f.mu.RLock() defer f.mu.RUnlock() // 增加活跃读取器计数 atomic.AddInt32(&f.readers, 1) defer atomic.AddInt32(&f.readers, -1) // 读取数据 fileData := make([][]string, len(f.data)) for i := 0; i < len(f.data); i++ { // 获取行读锁 if rowLock := f.getRowLock(i); rowLock != nil { rowLock.RLock() } // 复制行数据 row := make([]string, len(f.data[i])) copy(row, f.data[i]) // 释放行锁 if rowLock := f.getRowLock(i); rowLock != nil { rowLock.RUnlock() } fileData[i] = row } // 如果需要处理表头映射 if hasHeader && f.hasHeader && len(f.header) > 0 { // 创建列映射:源列 -> 目标列 columnMapping := make(map[int]int) for srcIdx, srcHeader := range f.header { for dstIdx, dstHeader := range mergedHeader { if srcHeader == dstHeader { columnMapping[srcIdx] = dstIdx break } } } // 重新排列数据以匹配合并后的表头 for i := 0; i < len(fileData); i++ { newRow := make([]string, len(mergedHeader)) for srcIdx, dstIdx := range columnMapping { if srcIdx < len(fileData[i]) { newRow[dstIdx] = fileData[i][srcIdx] } } fileData[i] = newRow } } else if hasHeader && len(mergedHeader) > 0 { // 文件没有表头,但输出需要表头 // 简单地将数据填充到对应位置 for i := 0; i < len(fileData); i++ { newRow := make([]string, len(mergedHeader)) for j := 0; j < len(fileData[i]) && j < len(newRow); j++ { newRow[j] = fileData[i][j] } fileData[i] = newRow } } // 将处理后的数据发送到通道 dataChan <- fileData }(idx, file) } // 等待所有goroutine完成 go func() { wg.Wait() close(dataChan) close(errorChan) }() // 收集所有数据 for data := range dataChan { mergedData = append(mergedData, data...) } // 检查是否有错误 select { case err := <-errorChan: if err != nil { setError("Error merging files: " + err.Error()) return -1 } default: } // 第三步:设置输出文件的数据 outputFile.data = mergedData outputFile.initRowLocks() // 第四步:保存到文件 if err := outputFile.save(); err != nil { setError("Error saving merged file: " + err.Error()) return -1 } // 第五步:将输出文件添加到管理器 handle := atomic.AddInt64(&mgr.nextHandle, 1) outputFile.handle = handle mgr.files.Store(handle, outputFile) return handle } // 关闭文件 func closeCSVFile(handle int64) int64 { mgr := getManager() val, ok := mgr.files.Load(handle) if !ok { setError("文件句柄无效!") return -1 } file := val.(*CSVFile) // 等待所有读写操作完成 for atomic.LoadInt32(&file.readers) > 0 || atomic.LoadInt32(&file.writers) > 0 { time.Sleep(time.Millisecond) } // 等待异步保存完成 for i := 0; i < 100; i++ { // 最多等待100ms if atomic.LoadInt32(&file.saving) == 0 { break } time.Sleep(time.Millisecond) } // 如果有正在进行的保存,等待一小段时间 if atomic.LoadInt32(&file.saving) > 0 { time.Sleep(50 * time.Millisecond) } // 检查是否需要保存 file.mu.RLock() needSave := file.modified file.mu.RUnlock() if needSave { // 同步保存修改 if err := file.save(); err != nil { setError(err.Error()) return -1 } } // 从管理器移除 mgr.files.Delete(handle) //// 安全关闭通道(如果存在) //if file.done != nil { // close(file.done) //} return 0 } // 获取错误信息 func getError() string { mgr := getManager() mgr.mu.RLock() defer mgr.mu.RUnlock() if mgr.errorMsg == "" { return "" } err := mgr.errorMsg mgr.errorMsg = "" // 清空错误 return err } func parseSimpleTable(goData string) [][]string { lines := strings.Split(strings.TrimSpace(goData), "\n") result := make([][]string, len(lines)) for i, line := range lines { // 根据你的分隔符分割,这里用逗号举例 fields := strings.Split(line, ",") // 如果需要去除每个字段的空格 for j := range fields { fields[j] = strings.TrimSpace(fields[j]) } result[i] = fields } return result } // ============ C 导出接口 ============ //export InitCSVManager func InitCSVManager() C.longlong { return C.longlong(initCSVManager()) } // OpenCSVFile 打开/创建CSV文件 // //export OpenCSVFile func OpenCSVFile(filename *C.char, delimiter C.char, hasHeader C.int) C.longlong { return C.longlong(openCSVFile(C.GoString(filename), rune(delimiter), hasHeader != 0)) } // CSV响应结构体 type CSVResponse struct { Success bool `json:"success"` Message string `json:"message,omitempty"` Data interface{} `json:"data,omitempty"` } // UpdateCSVRowSafe 修改csv文件行数据 // //export UpdateCSVRowSafe func UpdateCSVRowSafe(handleID C.longlong, rowNum C.int, newRow *C.char) *C.char { goHandle := int64(handleID) goRowNum := int(rowNum) goNewRow := C.GoString(newRow) var row []string var csvResponse CSVResponse // 解析JSON err := json.Unmarshal([]byte(goNewRow), &row) if err != nil { csvResponse = CSVResponse{ Success: false, Message: fmt.Sprintf("解析JSON失败: %v", err), } errorJson, _ := json.Marshal(csvResponse) return C.CString(string(errorJson)) } // 修改csv行数据 err = updateCSVRowSafe(goHandle, goRowNum, row) if err != nil { csvResponse = CSVResponse{ Success: false, Message: fmt.Sprintf(err.Error()), } errorJson, _ := json.Marshal(csvResponse) return C.CString(string(errorJson)) } else { csvResponse = CSVResponse{ Success: true, } } // 转换为JSON字符串 jsonData, err := json.Marshal(csvResponse) if err != nil { // 如果JSON序列化失败,返回错误信息 csvResponse = CSVResponse{ Success: false, Message: fmt.Sprintf("JSON序列化失败: %v", err), } errorJson, _ := json.Marshal(csvResponse) return C.CString(string(errorJson)) } return C.CString(string(jsonData)) } //export CreateOpenCSVFile func CreateOpenCSVFile(filename *C.char, delimiter C.char, hasHeader C.int) *C.char { goFilename := C.GoString(filename) goDelimiter := rune(delimiter) var goHasHeader bool if int(hasHeader) == 0 { goHasHeader = true } goHasHeader = false handle := createOpenCSVFile(goFilename, goDelimiter, goHasHeader) var csvResponse CSVResponse response := struct { HandleID int64 `json:"handleID"` }{ HandleID: handle, } csvResponse.Success = true csvResponse.Data = response jsonData, _ := json.Marshal(csvResponse) return C.CString(string(jsonData)) } // ReadRows 读取多行数据 // //export ReadRows func ReadRows(handle C.longlong, startRow C.longlong, count C.longlong, buffer *C.char, bufferSize C.int) C.longlong { // 将 C 缓冲区转换为 Go 的字节切片 goBuffer := unsafe.Slice((*byte)(unsafe.Pointer(buffer)), int(bufferSize)) result := readRows(int64(handle), int64(startRow), int64(count), goBuffer) return C.longlong(result) } // WriteRows 写入/覆盖行数据 // //export WriteRows func WriteRows(handle C.longlong, rowsData *C.char, header C.int) C.int { goData := C.GoString(rowsData) goHeader := int(header) //data := parseSimpleTable(goData) var data [][]string err := json.Unmarshal([]byte(goData), &data) if err != nil { setError(err.Error()) } result := writeRows(int64(handle), data, goHeader) return C.int(result) } // AppendRows 追加行数据 // //export AppendRows func AppendRows(handle C.longlong, rowsData *C.char, dataSize C.int, rowCount C.longlong) C.int { goData := unsafe.Slice((*byte)(unsafe.Pointer(rowsData)), int(dataSize)) result := appendRows(int64(handle), goData, int64(rowCount)) return C.int(result) } // GetRowCount 获取总行数 // //export GetRowCount func GetRowCount(handle C.longlong) C.longlong { result := getRowCount(int64(handle)) return C.longlong(result) } // FindRows 搜索行 // //export FindRows func FindRows(handle C.longlong, searchText *C.char, columnIndex C.longlong, resultBuffer *C.char, bufferSize C.int, maxResults C.longlong) C.longlong { goSearchText := C.GoString(searchText) goResultBuffer := unsafe.Slice((*byte)(unsafe.Pointer(resultBuffer)), int(bufferSize)) result := findRows(int64(handle), goSearchText, int64(columnIndex), goResultBuffer, int64(maxResults)) return C.longlong(result) } // MergeCSVFiles 合并多个CSV文件(线程安全) // //export MergeCSVFiles func MergeCSVFiles(handlesPtr *C.longlong, handlesCount C.int, outputFilename *C.char, delimiter C.char, hasHeader C.int) C.longlong { // 将C数组转换为Go切片 goHandles := unsafe.Slice(handlesPtr, int(handlesCount)) handles := make([]int64, len(goHandles)) for i := 0; i < len(goHandles); i++ { handles[i] = int64(goHandles[i]) } // 调用合并函数 result := mergeCSVFiles(handles, C.GoString(outputFilename), rune(delimiter), hasHeader != 0) return C.longlong(result) } // CloseCSVFile 关闭文件 // //export CloseCSVFile func CloseCSVFile(handle C.longlong) C.int { result := closeCSVFile(int64(handle)) return C.int(result) } // GetError 获取错误信息 // //export GetError func GetError(buffer *C.char, bufferSize C.int) C.int { errMsg := getError() if errMsg == "" { return 0 } // 将错误信息复制到缓冲区 goBuffer := unsafe.Slice((*byte)(unsafe.Pointer(buffer)), int(bufferSize)) n := copy(goBuffer, errMsg) return C.int(n) } // 导出函数:释放C字符串内存 // //export FreeCString func FreeCString(str *C.char) { C.free(unsafe.Pointer(str)) } // CSV_VERSION 版本号 const ( CSV_VERSION = "v1" ) // 获取版本信息 // //export GetVersion func GetVersion() *C.char { return C.CString(CSV_VERSION) } // main 函数是必需的,即使为空 func main() { }