亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Golang基于文件魔數判斷文件類型的案例代碼

 更新時間:2023年02月17日 15:20:51   作者:夢想畫家  
這篇文章主要介紹了Golang基于文件魔數判斷文件類型,本文介紹了基于文件魔數判斷文件類型的方法,主要涉及如何ReadSeek讀取文件指定字節(jié)內容,然后介紹文件魔數,最后給出示例基于魔數判斷文件類型,需要的朋友可以參考下

本文介紹基于魔數判斷文件類型,涉及文件查找讀取內容、文件魔數、字節(jié)比較,最后還介紹函數參數的知識。

查找位置

File.Seek()函數可以設置偏移位置,為下一次讀或寫確定偏移量,具體起點有whence確定:0標識相對文件開始位置、1相對當前位置、2相對文件結尾。函數返回新的位置及錯誤。請看下面示例:

package main
 
import (
   "os"
   "fmt"
   "log"
)
 
func main() {
   file, _ :- os.Open("test.txt")
   defer file.Close()
 
   // Offset 表示偏移量
   // Offset 可以為正數或負數
   var offset int64 - 5
 
   // Whence 偏移參考點,具體取值說明
   // 0 - Beginning of file
   // 1 - Current position
   // 2 - End of file
   var whence int - 0
   newPosition, err :- file.Seek(offset, whence)
   if err !- nil {
      log.Fatal(err)
   }
   fmt.Println("Just moved to 5:", newPosition)
 
   // 從當前位置回走2個字節(jié)
   newPosition, err - file.Seek(-2, 1)
   if err !- nil {
      log.Fatal(err)
   }
   fmt.Println("Just moved back two:", newPosition)
 
   // 通過移動零字節(jié)返回當前位置
   currentPosition, err :- file.Seek(0, 1)
   fmt.Println("Current position:", currentPosition)
 
   // 回到文件起始點
   newPosition, err - file.Seek(0, 0)
   if err !- nil {
      log.Fatal(err)
   }
   fmt.Println("Position after seeking 0,0:", newPosition)
}

執(zhí)行程序結果如下:

Just moved to 5: 5
Just moved back two: 3
Current position: 3
Position after seeking 0,0: 0

文件類型

魔數是文件前幾個字節(jié),用于唯一標識文件類型,從而無需關注復雜文件結構就能夠確定文件類型。舉例,jpeg文件總是ffd8 ffe0。下面列舉常見文件類型的魔數:

  • 圖像文件
File typeTypical extensionHex digits xx - variableAscii digits . - not an ascii char
Bitmap format.bmp42 4dBM
FITS format.fits53 49 4d 50 4c 45SIMPLE
GIF format.gif47 49 46 38GIF8
Graphics Kernel System.gks47 4b 53 4dGKSM
IRIS rgb format.rgb01 da
ITC (CMU WM) format.itcf1 00 40 bb
JPEG File Interchange Format.jpgff d8 ff e0
NIFF (Navy TIFF).nif49 49 4e 31IIN1
PM format.pm56 49 45 57VIEW
PNG format.png89 50 4e 47.PNG
Postscript format.[e]ps25 21%!
Sun Rasterfile.ras59 a6 6a 95Y.j.
Targa format.tgaxx xx xx
TIFF format (Motorola - big endian).tif4d 4d 00 2aMM.*
TIFF format (Intel - little endian).tif49 49 2a 00II*.
X11 Bitmap format.xbmxx xx
XCF Gimp file structure.xcf67 69 6d 70 20 78 63 66 20 76gimp xcf
Xfig format.fig23 46 49 47#FIG
XPM format.xpm2f 2a 20 58 50 4d 20 2a 2f/* XPM */
  • 壓縮文件類型
File typeTypical extensionHex digits xx = variableAscii digits . = not an ascii char
Bzip.bz42 5aBZ
Compress.Z1f 9d
gzip format.gz1f 8b
pkzip format.zip50 4b 03 04PK…
  • 歸檔文件類型
File typeTypical extensionHex digits xx = variableAscii digits . = not an ascii char
TAR (pre-POSIX).tarxx xx(a filename)
TAR (POSIX).tar75 73 74 61 72ustar (offset by 257 bytes)
  • 可執(zhí)行文件類型
File typeTypical extensionHex digits xx = variableAscii digits . = not an ascii char
MS-DOS, OS/2 or MS Windows4d 5aMZ
Unix elf7f 45 4c 46.ELF

有了上面的基礎知識,我們就可以讀文件前幾個字節(jié)判斷文件類型。

實現基礎函數

首先定義文件魔數標識變量:

var(
   PDF        = []byte{0x25, 0x50, 0x44, 0x46}
	RAR        = []byte{0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00}
	GZIP       = []byte{0x1F, 0x8B, 0x08}
	ZIP_0      = []byte{0x50, 0x4B, 0x03, 0x04}
	ZIP_1      = []byte{0x50, 0x4B, 0x05, 0x06}
	ZIP_2      = []byte{0x50, 0x4B, 0x07, 0x08}
	WEBP       = []byte{0x52, 0x49, 0x46, 0x46}
   ...
)

下面定義幾個讀文件函數。

首先是從ReadSeeker開始位置起讀取幾個字節(jié)函數:

func readUntil(l int, r io.ReadSeeker) ([]byte, error) {
	buff := make([]byte, l)

	_, err := r.Read(buff)
	if err != nil {
		return nil, err
	}

	r.Seek(0, io.SeekStart)

	return buff, nil
}

基于魔數字節(jié)數組讀文件魔數:

func checkBuffer(r io.ReadSeeker, t []byte) ([]byte, error) {
   // 根據提供參數獲取長度
	l := len(t)

	buff, err := readUntil(l, r)
	if err != nil {
		return make([]byte, 0), err
	}

	return buff, nil
}

基于參數比較文件魔數:

func genericCompareBuffer(r io.ReadSeeker, t []byte) bool {
	buff, err := checkBuffer(r, t)
	if err != nil {
		return false
	}

	valid := bytes.Compare(t, buff)
	return valid == 0
}

比較文件包括多個魔數情況比較:

func genericMultipleCompareBuffer(r io.ReadSeeker, t [][]byte) bool {
	buff, err := checkBuffer(r, t[0])
	if err != nil {
		return false
	}

	for _, v := range t {
		if bytes.Compare(v, buff) == 0 {
			return true
		}
	}

	return false
}

類型判斷函數

有了上面的基礎函數,我們可以提供上層應用接口函數。

首先是常用類型判斷函數,注意這里PNG、JPEG是前面定義的字節(jié)數組變量。

// IsPng function will return true if File is a valid PNG
func IsPng(r io.ReadSeeker) bool {
	return genericCompareBuffer(r, PNG)
}

// IsJpeg function will return true if File is a valid JPEG
func IsJpeg(r io.ReadSeeker) bool {
	return genericCompareBuffer(r, JPEG)
}

// IsPdf function will return true if File is a valid PDF
func IsPdf(r io.ReadSeeker) bool {
	return genericCompareBuffer(r, PDF)
}

// IsGif function will return true if File is a valid GIF
func IsGif(r io.ReadSeeker) bool {
	return genericCompareBuffer(r, GIF)
}

同類文件可能有不同魔數場景:

// IsMpg function will return true if File is a valid MPG
func IsMpg(r io.ReadSeeker) bool {
	return genericMultipleCompareBuffer(r, [][]byte{
		MPG_0,
		MPG_1,
	})
}

最后提供一個同時判斷多種文件類型的函數,利用函數類型參數:

// IsOneOf function will validate File with multiple function
func IsOneOf(r io.ReadSeeker, functions ...function) bool {
	for _, f := range functions {
		valid := f(r)
		if valid {
			return true
		}
	}

	return false
}

測試代碼

下面測試前面定義的函數,函數包括文件名稱參數,判斷該文件類型:

package main

import (
	"fmt"
	"os"
)

func main() {
	args := os.Args

	if len(args) < 2 {
		fmt.Println("required input file")
		os.Exit(1)
	}

   // 打開文件
	inputFileArg := args[1]
	inFile, err := os.Open(inputFileArg)

	if err != nil {
		fmt.Println("error open input file ", err)
		os.Exit(1)
	}

   // 支持錯誤處理的關閉方式
	defer func() { 
      err := inFile.Close() 
      if err != nil {
         fmt.Println("error close input file ", err)
      }
   }()

   // 一次性判斷多種類型,如:是否為圖像文件
	valid := IsOneOf(inFile, filesig.Is3gp, filesig.IsPng, filesig.IsJpeg)
	fmt.Println(valid)

   // 當然也可以判斷單個類型
   valid = filesig.Is3gp(inFile)
	fmt.Println(valid)
}

總結

本文介紹了基于文件魔數判斷文件類型的方法,主要涉及如何ReadSeek讀取文件指定字節(jié)內容,然后介紹文件魔數,最后給出示例基于魔數判斷文件類型。參考代碼:https://github.com/telkomdev/go-filesig

到此這篇關于Golang基于文件魔數判斷文件類型的文章就介紹到這了,更多相關go文件類型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • go依賴注入庫samber/do使用示例講解

    go依賴注入庫samber/do使用示例講解

    這篇文章主要介紹了go依賴注入庫samber/do使用,在本文中,我們學習了如何使用samber/do在?Go?中提供依賴注入,需要的朋友可以參考下
    2024-02-02
  • 一文帶你了解Go語言中接口的使用

    一文帶你了解Go語言中接口的使用

    這篇文章主要和大家分享一下Go語言中的接口的使用,文中的示例代碼講解詳細,對我們學習Go語言有一定的幫助,需要的小伙伴可以參考一下
    2022-12-12
  • Go語言strconv包實現字符串和數值類型的相互轉換

    Go語言strconv包實現字符串和數值類型的相互轉換

    這篇文章主要介紹了Go語言strconv包實現字符串和數值類型的相互轉換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03
  • 如何使用proto組件編譯pb.go文件

    如何使用proto組件編譯pb.go文件

    這篇文章主要介紹了如何使用proto組件編譯pb.go文件的詳細過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • GoLang實現日志收集器流程講解

    GoLang實現日志收集器流程講解

    這篇文章主要介紹了GoLang實現日志收集器流程,看日志是開發(fā)者平時排查BUG所必須的掌握的技能,但是日志冗雜,所以寫個小工具來收集這些日志幫助我們排查BUG,感興趣想要詳細了解可以參考下文
    2023-05-05
  • 關于golang類型推斷和變量重聲明詳解

    關于golang類型推斷和變量重聲明詳解

    在Go語言中,類型推斷可以根據變量的初始化值自動推斷出變量的類型,而不需要顯式地聲明變量類型,變量重聲明可以在同一作用域內重復聲明一個變量,只要其中至少一個是新的變量,本就簡單的給大家介紹一下golang類型推斷和變量重聲明,需要的朋友可以參考下
    2023-08-08
  • go中的protobuf和grpc使用教程

    go中的protobuf和grpc使用教程

    gRPC 是 Google 公司基于 Protobuf 開發(fā)的跨語言的開源 RPC 框架,這篇文章主要介紹了go中的protobuf和grpc使用教程,需要的朋友可以參考下
    2024-08-08
  • golang實現分頁算法實例代碼

    golang實現分頁算法實例代碼

    這篇文章主要給大家介紹了關于golang實現分頁算法的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-09-09
  • go語言操作redis連接池的方法

    go語言操作redis連接池的方法

    這篇文章主要介紹了go語言操作redis連接池的方法,涉及Go語言操作radis的技巧,需要的朋友可以參考下
    2015-03-03
  • Go語言無緩沖的通道的使用

    Go語言無緩沖的通道的使用

    Go語言中無緩沖的通道是指在接收前沒有能力保存任何值的通道,本文主要介紹了Go語言無緩沖的通道的使用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01

最新評論