package main import "C" import ( "bytes" "encoding/csv" "encoding/json" "fmt" "io" "net/http" "os" "path/filepath" "syscall" "unsafe" ) // CsvDLL 代理DLL结构 type csvDLL struct { dll *syscall.DLL openCSVFile *syscall.Proc // 打开/创建CSV文件 readRows *syscall.Proc // 读取多行数据 writeRows *syscall.Proc // 写入/覆盖行数据 appendRows *syscall.Proc // 追加行数据 getRowCount *syscall.Proc // 获取总行数 findRows *syscall.Proc // 搜索行 closeCSVFile *syscall.Proc // 关闭CSV文件 mergeCSVFiles *syscall.Proc // 合并多个CSV文件 getError *syscall.Proc // 获取错误信息 updateCSVRowSafe *syscall.Proc createOpenCSVFile *syscall.Proc freeCString *syscall.Proc // 释放C字符串 } // 初始化csvDLL func InitCsvDLL() (*csvDLL, error) { dllPath := filepath.Join("csv/dll", "csv.dll") if _, err := os.Stat(dllPath); os.IsNotExist(err) { return nil, fmt.Errorf("csv DLL 不存在: %s", dllPath) } if dll, err := syscall.LoadDLL(dllPath); err != nil { return nil, fmt.Errorf("加载csv DLL 失败: %s", err) } else { return &csvDLL{ dll: dll, openCSVFile: dll.MustFindProc("OpenCSVFile"), updateCSVRowSafe: dll.MustFindProc("UpdateCSVRowSafe"), readRows: dll.MustFindProc("ReadRows"), writeRows: dll.MustFindProc("WriteRows"), appendRows: dll.MustFindProc("AppendRows"), getRowCount: dll.MustFindProc("GetRowCount"), findRows: dll.MustFindProc("FindRows"), closeCSVFile: dll.MustFindProc("CloseCSVFile"), mergeCSVFiles: dll.MustFindProc("MergeCSVFiles"), createOpenCSVFile: dll.MustFindProc("CreateOpenCSVFile"), getError: dll.MustFindProc("GetError"), freeCString: dll.MustFindProc("FreeCString"), }, nil } } // cStr 获取C字符串 func (m *csvDLL) cStr(p uintptr) string { if p == 0 { return "" } b := []byte{} for i := uintptr(0); ; i++ { c := *(*byte)(unsafe.Pointer(p + i)) if c == 0 { break } b = append(b, c) } s := string(b) if m.freeCString != nil { m.freeCString.Call(p) } return s } // 打开/创建CSV文件 func (m *csvDLL) OpenCSVFile(filePath string, delimiter byte, hasHeader bool) (int64, error) { proc, err := m.dll.FindProc("OpenCSVFile") if err != nil { return -1, fmt.Errorf("找不到函数 OpenCSVFile: %v", err) } filePathPtr, _ := syscall.BytePtrFromString(filePath) hasHeaderInt := 0 if hasHeader { hasHeaderInt = 1 } info, _, _ := proc.Call( uintptr(unsafe.Pointer(filePathPtr)), uintptr(delimiter), uintptr(hasHeaderInt)) return int64(info), nil } // CSV响应结构体 type CSVResponses struct { Success bool `json:"success"` Message string `json:"message,omitempty"` Data CSVData `json:"data,omitempty"` } type CSVData struct { HandleID int64 `json:"handleID"` } func (m *csvDLL) CreateOpenCSVFile(filePath string, delimiter byte, hasHeader bool) (*CSVResponses, error) { proc, err := m.dll.FindProc("CreateOpenCSVFile") if err != nil { return nil, fmt.Errorf("找不到函数 CreateOpenCSVFile: %v", err) } filePathPtr, _ := syscall.BytePtrFromString(filePath) hasHeaderInt := 0 if hasHeader { hasHeaderInt = 1 } info, _, _ := proc.Call( uintptr(unsafe.Pointer(filePathPtr)), uintptr(delimiter), uintptr(hasHeaderInt)) var csvResponse CSVResponses str := m.cStr(info) if err := json.Unmarshal([]byte(str), &csvResponse); err != nil { return nil, err } return &csvResponse, nil } func (m *csvDLL) UpdateCSVRowSafe(handleID int64, rowNum int, newRow []string) (*CSVResponses, error) { proc, err := m.dll.FindProc("UpdateCSVRowSafe") if err != nil { return nil, fmt.Errorf("找不到函数 UpdateCSVRowSafe: %v", err) } jsonString, _ := json.Marshal(newRow) newRowPtr, _ := syscall.BytePtrFromString(string(jsonString)) info, _, _ := proc.Call( uintptr(handleID), uintptr(rowNum), uintptr(unsafe.Pointer(newRowPtr))) var csvResponse CSVResponses str := m.cStr(info) if err := json.Unmarshal([]byte(str), &csvResponse); err != nil { return nil, err } return &csvResponse, nil } //// 读取多行数据 //func (m *csvDLL) ReadRows(handle int64) ([]string, error) { // proc, err := m.dll.FindProc("ReadRows") // if err != nil { // return nil, fmt.Errorf("找不到函数 ReadRows: %v", err) // } // //} // 写入/覆盖行数据 func (m *csvDLL) WriteRows(handle int64, rowsData [][]string, header int) (int, error) { proc, err := m.dll.FindProc("WriteRows") if err != nil { return -1, fmt.Errorf("找不到函数 WriteRows: %v", err) } var buffer bytes.Buffer writer := csv.NewWriter(&buffer) // 写入所有行 if err := writer.WriteAll(rowsData); err != nil { return -1, fmt.Errorf("序列化 CSV 数据失败: %v", err) } writer.Flush() // 转换为 C 字符串 cStr := C.CString(buffer.String()) ret, _, _ := proc.Call( uintptr(handle), uintptr(unsafe.Pointer(cStr)), uintptr(header)) freeProc, _ := m.dll.FindProc("FreeCString") if freeProc != nil { defer freeProc.Call(uintptr(unsafe.Pointer(cStr))) } return int(ret), nil } // 定义请求结构体 type OpenCSVRequest struct { FilePath string `json:"filePath"` Delimiter string `json:"delimiter"` // 可以是逗号、分号等字符 HasHeader bool `json:"hasHeader"` } // 定义响应结构体 type OpenCSVResponse struct { Success bool `json:"success"` Message string `json:"message"` Handle int64 `json:"handle,omitempty"` Error string `json:"error,omitempty"` } func handleOpenCSVFile(w http.ResponseWriter, r *http.Request) { // 设置响应头 w.Header().Set("Content-Type", "application/json; charset=utf-8") // 只允许 POST 请求 if r.Method != http.MethodPost { response := OpenCSVResponse{ Success: false, Message: "只支持POST请求", } w.WriteHeader(http.StatusMethodNotAllowed) json.NewEncoder(w).Encode(response) return } // 1.初始化DLL管理器 dll, err := InitCsvDLL() if err != nil { response := OpenCSVResponse{ Success: false, Message: "初始化DLL失败", Error: err.Error(), } w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(response) return } // 2.读取请求体 body, err := io.ReadAll(r.Body) if err != nil { response := OpenCSVResponse{ Success: false, Message: "读取请求体失败", Error: err.Error(), } w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(response) return } defer r.Body.Close() // 3.解析JSON请求 var req OpenCSVRequest if err := json.Unmarshal(body, &req); err != nil { response := OpenCSVResponse{ Success: false, Message: "JSON解析失败", Error: err.Error(), } w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(response) return } // 4.验证必填参数 if req.FilePath == "" { response := OpenCSVResponse{ Success: false, Message: "filePath参数不能为空", } w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(response) return } // 5. 处理分隔符参数 delimiter := ',' if req.Delimiter != "" { // 确保分隔符是单个字符 if len(req.Delimiter) == 1 { delimiter = rune(req.Delimiter[0]) } else { // 尝试解析常见分隔符的字符串表示 switch req.Delimiter { case "comma", ",": delimiter = ',' case "semicolon", ";": delimiter = ';' case "tab", "\t": delimiter = '\t' case "pipe", "|": delimiter = '|' default: response := OpenCSVResponse{ Success: false, Message: "无效的分隔符,请使用单个字符或预定义的分隔符名称", } w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(response) return } } } // 6. 调用DLL函数 handle, err := dll.OpenCSVFile(req.FilePath, byte(delimiter), req.HasHeader) if err != nil { response := OpenCSVResponse{ Success: false, Message: "打开CSV文件失败", Error: err.Error(), } w.WriteHeader(http.StatusInternalServerError) json.NewEncoder(w).Encode(response) return } // 7. 返回成功响应 response := OpenCSVResponse{ Success: true, Message: "CSV文件打开成功", Handle: handle, } w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(response) } func main() { dll, err := InitCsvDLL() if err != nil { } file, err := dll.CreateOpenCSVFile("csv/taskLog.csv", ',', true) if err != nil { } newRow := []string{"9787115524539", "100.00", "1", "上传成功", ""} safe, err := dll.UpdateCSVRowSafe(file.Data.HandleID, 9, newRow) if err != nil { } marshal, _ := json.Marshal(safe) fmt.Println(string(marshal)) //http.HandleFunc("/csv/openCSVFile", handleOpenCSVFile) //port := "8080" //server := &http.Server{ // Addr: ":" + port, // Handler: nil, //} // //// 4. 优雅关闭设置 //done := make(chan bool, 1) //quit := make(chan os.Signal, 1) //signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) // //// 5. 优雅关闭协程 //go func() { // <-quit // fmt.Println("\n服务器正在关闭...") // // ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // defer cancel() // // if err := server.Shutdown(ctx); err != nil { // fmt.Printf("强制关闭服务器: %v\n", err) // } // close(done) //}() // //// 启动服务器 //if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { // fmt.Printf("服务器启动失败: %s\n", err) //} //// 7. 等待关闭完成 //<-done //fmt.Println("服务器已关闭") } // 解码从DLL读取的数据 func decodeRowData(buffer []byte, maxBytes int) [][]string { var rows [][]string var currentRow []string offset := 0 for offset < maxBytes { if offset+4 > maxBytes { break } // 读取单元格长度 cellLen := int(uint32(buffer[offset]) | uint32(buffer[offset+1])<<8 | uint32(buffer[offset+2])<<16 | uint32(buffer[offset+3])<<24) offset += 4 if cellLen == 0 { // 行结束 if len(currentRow) > 0 { rows = append(rows, currentRow) currentRow = nil } continue } if offset+cellLen > maxBytes { break } // 读取单元格数据 cell := string(buffer[offset : offset+cellLen]) offset += cellLen currentRow = append(currentRow, cell) } return rows }