csv.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package utils
  2. import (
  3. "encoding/csv"
  4. "fmt"
  5. "log"
  6. "net"
  7. "os"
  8. "strconv"
  9. "time"
  10. )
  11. const defaultOutput = "result.csv"
  12. var (
  13. MaxDelay = 9999 * time.Millisecond
  14. MinDelay = time.Duration(0)
  15. InputMaxDelay = MaxDelay
  16. InputMinDelay = MinDelay
  17. Output = defaultOutput
  18. PrintNum = 20
  19. )
  20. type PingData struct {
  21. IP *net.IPAddr
  22. Sended int
  23. Received int
  24. Delay time.Duration
  25. }
  26. type CloudflareIPData struct {
  27. *PingData
  28. recvRate float32
  29. DownloadSpeed float64
  30. }
  31. func (cf *CloudflareIPData) getRecvRate() float32 {
  32. if cf.recvRate == 0 {
  33. pingLost := cf.Sended - cf.Received
  34. cf.recvRate = float32(pingLost) / float32(cf.Sended)
  35. }
  36. return cf.recvRate
  37. }
  38. func (cf *CloudflareIPData) toString() []string {
  39. result := make([]string, 6)
  40. result[0] = cf.IP.String()
  41. result[1] = strconv.Itoa(cf.Sended)
  42. result[2] = strconv.Itoa(cf.Received)
  43. result[3] = strconv.FormatFloat(float64(cf.getRecvRate()), 'f', 2, 32)
  44. result[4] = cf.Delay.String()
  45. result[5] = strconv.FormatFloat(cf.DownloadSpeed/1024/1024, 'f', 2, 32)
  46. return result
  47. }
  48. func ExportCsv(data []CloudflareIPData) {
  49. if Output == "" {
  50. Output = defaultOutput
  51. }
  52. fp, err := os.Create(Output)
  53. if err != nil {
  54. log.Fatalf("创建文件[%s]失败:%v", Output, err)
  55. return
  56. }
  57. defer fp.Close()
  58. w := csv.NewWriter(fp) //创建一个新的写入文件流
  59. w.Write([]string{"IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)"})
  60. w.WriteAll(convertToString(data))
  61. w.Flush()
  62. }
  63. func convertToString(data []CloudflareIPData) [][]string {
  64. result := make([][]string, 0)
  65. for _, v := range data {
  66. result = append(result, v.toString())
  67. }
  68. return result
  69. }
  70. type PingDelaySet []CloudflareIPData
  71. func (s PingDelaySet) FilterDelay() (data PingDelaySet) {
  72. if InputMaxDelay >= MaxDelay || InputMinDelay <= MinDelay {
  73. return s
  74. }
  75. for _, v := range s {
  76. if v.Delay > MaxDelay { // 平均延迟上限
  77. break
  78. }
  79. if v.Delay <= MinDelay { // 平均延迟下限
  80. continue
  81. }
  82. data = append(data, v) // 延迟满足条件时,添加到新数组中
  83. }
  84. return
  85. }
  86. func (s PingDelaySet) Len() int {
  87. return len(s)
  88. }
  89. func (s PingDelaySet) Less(i, j int) bool {
  90. iRate, jRate := s[i].getRecvRate(), s[j].getRecvRate()
  91. if iRate != jRate {
  92. return iRate < jRate
  93. }
  94. return s[i].Delay < s[j].Delay
  95. }
  96. func (s PingDelaySet) Swap(i, j int) {
  97. s[i], s[j] = s[j], s[i]
  98. }
  99. // 下载速度排序
  100. type DownloadSpeedSet []CloudflareIPData
  101. func (s DownloadSpeedSet) Len() int {
  102. return len(s)
  103. }
  104. func (s DownloadSpeedSet) Less(i, j int) bool {
  105. return s[i].DownloadSpeed > s[j].DownloadSpeed
  106. }
  107. func (s DownloadSpeedSet) Swap(i, j int) {
  108. s[i], s[j] = s[j], s[i]
  109. }
  110. func (s DownloadSpeedSet) Print(ipv6 bool) {
  111. if len(s) <= 0 { // IP数组长度(IP数量) 大于 0 时继续
  112. fmt.Println("\n[信息] 完整测速结果 IP 数量为 0,跳过输出结果。")
  113. return
  114. }
  115. dateString := convertToString(s) // 转为多维数组 [][]String
  116. if len(dateString) < PrintNum { // 如果IP数组长度(IP数量) 小于 打印次数,则次数改为IP数量
  117. PrintNum = len(dateString)
  118. }
  119. headFormat := "%-16s%-5s%-5s%-5s%-6s%-11s\n"
  120. dataFormat := "%-18s%-8s%-8s%-8s%-15s%-15s\n"
  121. if ipv6 { // IPv6 太长了,所以需要调整一下间隔
  122. headFormat = "%-40s%-5s%-5s%-5s%-6s%-11s\n"
  123. dataFormat = "%-42s%-8s%-8s%-8s%-10s%-15s\n"
  124. }
  125. fmt.Printf(headFormat, "IP 地址", "已发送", "已接收", "丢包率", "平均延迟", "下载速度 (MB/s)")
  126. for i := 0; i < PrintNum; i++ {
  127. fmt.Printf(dataFormat, dateString[i][0], dateString[i][1], dateString[i][2], dateString[i][3], dateString[i][4], dateString[i][5])
  128. }
  129. }