go语言在.csv文件中加入超链接
#
func main() {
// 打开文件以写入 CSV 数据
file, err := os.Create("output.csv")
if err != nil {
panic(err)
}
defer file.Close()
// 创建 CSV writer
writer := csv.NewWriter(file)
defer writer.Flush()
// 写入 CSV 头部
header := []string{"File Name", "Hyperlink"}
writer.Write(header)
// 模拟一些文件名和相对路径数据
fileData := []struct {
FileName string
RelativePath string
}{
{"video.MP4", "./d/video.MP4"},
// 添加更多文件名和相对路径
}
// 写入文件名和相对路径数据到 CSV 文件
for _, data := range fileData {
// 构建超链接字符串
hyperlinkFormula := `=HYPERLINK("` + data.RelativePath + `", "` + data.FileName + `")`
row := []string{data.FileName, hyperlinkFormula}
writer.Write(row)
}
// 刷新 CSV writer 缓冲区,确保所有数据被写入文件
writer.Flush()
}
通过ffmpeg获取视频文件信息
#
//videopath := api.GetMountPoint() + common.FixPathWithSeparator(v.FullPath, "\\")
//vv, iserr := video.GetVideoInfo.Stat(videopath)
//taskMutex.Lock()
//tasked++
//taskMutex.Unlock()
//if !iserr {
// data.Duration = int(math.Floor(vv.Length)) //秒
// data.FrameRate = int(math.Floor(vv.Fps))
// data.FrameHeight = int(vv.Height)
// data.FrameWidth = int(vv.Width)
// data.Resolution = strconv.Itoa(data.FrameWidth) + " * " + strconv.Itoa(data.FrameHeight)
//}
//data.UserId=
//width, height, duration, _, err := getVideoSize(videopath)
//if err == nil {
// data.Duration, _ = strconv.Atoi(duration) //秒
// //data.FrameRate = int(math.Floor(vv.Fps))
// data.Resolution = strconv.Itoa(width * height)
// data.FrameHeight = height
// data.FrameWidth = width
//}
// import ffmpeg "github.com/u2takey/ffmpeg-go" 发现时间效果差不多 都是底层启动多个exe执行
func getVideoSize(fileName string) (width, height int, duration, rframerate string, err error) {
//log.Println("Getting video size for", fileName)
data, err := ffmpeg.Probe(fileName)
if err != nil {
fmt.Println(err.Error())
return 0, 0, "", "", err
}
//log.Println("got video info", data)
type VideoInfo struct {
Streams []struct {
CodecType string `json:"codec_type"`
Width int
Height int
Duration string
RFrameRate string `json:"r_frame_rate"`
} `json:"streams"`
}
vInfo := &VideoInfo{}
err = json.Unmarshal([]byte(data), vInfo)
if err != nil {
return 0, 0, "", "", err
}
for _, s := range vInfo.Streams {
if s.CodecType == "video" {
return s.Width, s.Height, s.Duration, s.RFrameRate, err
}
}
return 0, 0, "", "", err
}
var GetVideoInfo = new(VideoInfo)
type VideoInfo struct{}
type Video struct {
//Path string
Length float64 // 时长(s)
//Bitrate float64 // 播放速率(kb/s)
//Size int64 // 文件大小(byte)
Width int64 // 视频分辨率宽度
Height int64 // 视频分辨率高度
Fps float64 // 视频帧率(帧/s)
//Vbitrate float64 // 视频比特率(kb/s)
//Abitrate float64 // 音频比特率(kb/s)
//Ahz float64 // 音频采集率(Hz)
}
// Stat 通过调用 ffmpeg命令 使用正则获取视频信息,
// 部分视频无法正常获取时长或比特率等,则使用0表示;
// 如果多个属性无法获取,则可能是正则匹配不全,
// 请手动执行 ffmpeg -i file_path 参照输出信息来确认问题
//var cmd = exec.Command("ffmpeg", "-i", "video_path")
func (video VideoInfo) Stat(video_path string) (v *Video, iserr bool) {
//cmd.Args[2] = video_path
//dir, err := os.Getwd() //获取当前文件路径
//if err != nil {
// fmt.Println(err.Error())
// return
//}
ffmpegPath := filepath.Join(api.GetAppInstallDir(), "\\bin\\ffmpeg\\ffmpeg.exe")
//api.Log.Info("ffmpegPath:", ffmpegPath) //
cmd := exec.Command(ffmpegPath, "-i", video_path)
r, _ := cmd.CombinedOutput()
//if err != nil {
// api.Log.Error(err.Error()) //
// fmt.Println("FFmpeg command execution failed: %s\n", err)
//}
// sample1
// Duration: 00:00:00.00, start: 0.000000, bitrate: N/A
// Stream #0:0: Video: rv40 (RV40 / 0x30345652), yuv420p, 640x480, 25 fps, 25 tbr, 1k tbn, 1k tbc
// Stream #0:1: Audio: cook (cook / 0x6B6F6F63), 44100 Hz, mono, fltp, 64 kb/s
// sample2
// Duration: 00:10:23.13, start: 0.000000, bitrate: 1741 kb/s
// Stream #0:0: Video: h264 (High) (H264 / 0x34363248), yuv420p(progressive), 352x288 [SAR 1:1 DAR 11:9], 1604 kb/s, 30 fps, 30 tbr, 30 tbn, 60 tbc
// Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, stereo, s16p, 128 kb/s
// sample3
// Duration: 00:17:57.43, start: 0.000000, bitrate: 383 kb/s
// Stream regexp.MustCompile(`.*Duration:\s(.*?),.*bitrate:\s(\S+)`)#0:0: Audio: cook (cook / 0x6B6F6F63), 44100 Hz, stereo, fltp, 64 kb/s
// Stream #0:1: Video: rv40 (RV40 / 0x30345652), yuv420p, 640x480, 308 kb/s, 23.98 fps, 23.98 tbr, 1k tbn, 1k tbc
str_r := string([]byte(r))
if video.parse_err(str_r) {
return nil, true
}
length, _ := video.parse_duration(str_r) //length, bitrate
width, height, _, fps := video.parse_video(str_r) //width, height, v_bitrate, fps
//a_hz, a_bitrate := video.parse_audio(str_r)
v = &Video{
//Path: video_path,
Length: length,
//Bitrate: bitrate,
//Size: get_size(video_path),
Width: width,
Height: height,
Fps: fps,
//Vbitrate: v_bitrate,
//Abitrate: a_bitrate,
//Ahz: a_hz,
}
return
}
func (video VideoInfo) get_size(path string) int64 {
file, _ := os.Stat(path)
return file.Size()
}
var reg_err = regexp.MustCompile(`\[in#\d+ @ [0-9a-fA-F]+\] Error opening input: (.+)`)
// 解析err行
func (video VideoInfo) parse_err(str string) bool {
s := reg_err.FindString(str)
if len(s) != 0 {
api.Log.Error(errors.New(s))
return true
}
return false
}
var reg_duration = regexp.MustCompile(`.*Duration:\s(.*?),.*bitrate:\s(\S+)`)
// 解析Duration行
func (video VideoInfo) parse_duration(str string) (float64, float64) {
s := reg_duration.FindStringSubmatch(str)
if len(s) != 3 {
return 0, 0
}
t := strings.Split(s[1], ":")
length := atof64(t[0])*3600 + atof64(t[1])*60 + atof64(t[2])
return length, atof64(s[2])
}
var reg_video = regexp.MustCompile(`Stream.*Video.*\s(\d+)x(\d+)(?:.*?(\S+)\skb/s)?.*?(\S+)\sfps`)
// 解析Video行
func (video VideoInfo) parse_video(str string) (int64, int64, float64, float64) {
s := reg_video.FindStringSubmatch(str)
if len(s) != 5 {
return 0, 0, 0, 0
}
return atoi64(s[1]), atoi64(s[2]), atof64(s[3]), atof64(s[4])
}
var reg_audio = regexp.MustCompile(`Stream.*Audio.*?(\d+)\sHz.*\s(\S+)\skb/s`)
// 解析Audio行
func (video VideoInfo) parse_audio(str string) (float64, float64) {
s := reg_audio.FindStringSubmatch(str)
if len(s) != 3 {
return 0, 0
}
return atof64(s[1]), atof64(s[2])
}
func atoi64(s string) int64 {
i, _ := strconv.ParseInt(s, 10, 64)
return i
}
func atof64(s string) float64 {
i, _ := strconv.ParseFloat(s, 64)
return i
}
防止电脑进入睡眠状态
#
func disableComputerSleep() (err error) {
kernel32, err := syscall.LoadLibrary("kernel32.dll")
if err != nil {
return
}
defer syscall.FreeLibrary(kernel32)
_SetThreadExecutionState, err := syscall.GetProcAddress(kernel32, "SetThreadExecutionState")
if err != nil {
return
}
for {
_, _, callErr := syscall.Syscall(_SetThreadExecutionState, 1, 0x80000000|0x00000002|0x00000001, 0, 0)
if callErr != 0 {
fmt.Println("SetThreadExecutionState error", callErr)
}
time.Sleep(30 * 1000 * time.Millisecond)
}
}
监听进程退出信号
#
func exitSingal() chan os.Signal {
exitSingal := make(chan os.Signal, 1)
signal.Notify(exitSingal, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGINT)
return exitSingal
}
select {
case sin := <-exitSingal():
fmt.Printf("get system singal %s ,exit ", sin.String())
}
获取电脑睡眠状态
#
var (
powerStatusCode uint32 = 0
eventCh = make(chan uint32)
ctx, Chancel = context.WithCancel(context.Background())
libPowrProf = windows.NewLazySystemDLL("powrprof.dll")
powerRegisterSuspendResumeNotification=libPowrProf.NewProc("PowerRegisterSuspendResumeNotification")
powerUnregisterSuspendResumeNotification=libPowrProf.NewProc("PowerUnregisterSuspendResumeNotification")
)
const (
PBT_APMSUSPEND uint32 = 4
PBT_APMRESUMESUSPEND uint32 = 7
PBT_APMRESUMEAUTOMATIC uint32 = 18
)
//入口函数
func ListenSystemSleepEvent() {
NewEventListener(ctx, eventCh)
for {
select {
case powerStatusCode = <-eventCh:
default:
}
}
}
func NewEventListener(haltCtx context.Context, eventCh chan uint32) {
go func() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
const (
_DEVICE_NOTIFY_CALLBACK = 2
)
type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct {
callback uintptr
context uintptr
}
var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr {
eventCh <- changeType
return 0
}
params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{
callback: windows.NewCallback(fn),
}
handle := uintptr(0)
Log.Info("注册电源 暂停/恢复")
powerRegisterSuspendResumeNotification.Call(
_DEVICE_NOTIFY_CALLBACK,
uintptr(unsafe.Pointer(¶ms)),
uintptr(unsafe.Pointer(&handle)),
)
<-haltCtx.Done()
Log.Info("取消注册电源 暂停/恢复")
powerUnregisterSuspendResumeNotification.Call(
uintptr(unsafe.Pointer(&handle)),
)
}()
}
自动填充空格 以格式化输出字符串
#
package main
import (
"bytes"
"encoding/json"
"fmt"
)
func main() {
// 定义一个JSON数据
jsonData := []byte(`{"a":1,"b":2}`)
// 格式化JSON数据
var formattedData bytes.Buffer
err := json.Indent(&formattedData, jsonData, "", " ")
if err != nil {
fmt.Println("Error formatting JSON:", err)
return
}
// 输出格式化后的JSON数据
fmt.Println(formattedData.String())
}
逐行读取文件
#
package main
import (
"bufio"
"fmt"
"log"
"os"
)
func main() {
filePath := "your_file.log"
// 打开文件
file, err := os.Open(filePath)
if err != nil {
log.Fatal(err)
}
defer file.Close()
// 创建一个 Scanner 来逐行读取文件内容
scanner := bufio.NewScanner(file)
// 逐行读取并处理文件内容
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
// 在这里可以对每一行的内容进行处理
// 例如,你可以将每一行的内容存储到切片中,或者进行其他操作
}
// 检查是否有错误发生
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
判断windows系统版本
#
import "github.com/elastic/go-sysinfo"
func TestGetVer(t *testing.T) {
host, err := sysinfo.Host()
if err != nil {
fmt.Println("Error getting host info:", err)
return
}
info := host.Info()
fmt.Println("Operating System:", info.OS.Name)
fmt.Println("Family:", info.OS.Family)
fmt.Println("Version:", info.OS.Version)
fmt.Println("Platform:", info.OS.Platform)
fmt.Println("Kernel Version:", info.KernelVersion)
fmt.Println("Arch:", info.Architecture)
}
Operating System:Windows 7 Home Basic
Family: windows
Uersion: 6.1
Platform: windows
Kernel version:6.1.2601.17514(win7sp1_rtm.101119-1850)
Arch:x86_64
0perating System: windows
Version: Windows 6.1<Build 761>
逐字节读取文件
#
func Test_copy(t *testing.T) {
path1 := "C:\\hlnet\\1-1720405740\\小米行车记录仪MJHSJJLYBY-168862538.E01\\NO NAME\\$未分配簇"
path2, _ := os.Getwd()
path2 = filepath.Join(path2, "$未分配簇3")
time1 := time.Now()
file, err := os.Open(path1)
if err != nil {
fmt.Println(err.Error())
return
}
defer file.Close()
reader := bufio.NewReader(file)
bufferSize := 10240
buffer := make([]byte, bufferSize)
for {
n, err := reader.Read(buffer)
if err != nil {
fmt.Println(err.Error())
if err == io.EOF {
fmt.Println("EOF")
}
break // 文件读取结束或发生错误
}
// 处理读取的数据
zeroBuffer := make([]byte, 1024)
if !bytes.Equal(buffer, zeroBuffer[:n]) {
fmt.Println("zero buffer")
}
}
fmt.Println(time.Now().Sub(time1).Seconds())
}