Go红队开发—文件操作

ops/2025/3/5 8:53:39/

文章目录

  • 文件操作
    • 创建目录
    • 创建文件
    • 获取File信息
    • 文件重命名
    • 删除文件
    • 打开关闭文件
    • 判断文件是否存在
    • 判断文件是否有读取权限
    • 复制文件
    • Read读取
    • ReadFull读取
    • ReadAtLeast读取
    • ReadAll读取
    • bufio读取
    • Write写入
    • WriteFile快速写入
    • 临时文件目录
    • 下载文件
    • 文件指针操作
    • 修改文件权限/拥有者/时间戳
    • 知识细节补充
      • OS.OpenFile
      • bufio
      • os.Stat
      • os.fileInfo
      • 文件权限

文件操作

由于在上一期编解码中对文件有操作需求,所以这一期补上文件操作功能.
依旧是直接放代码,加速学习进度,代码拿着就用即可,都是内置的功能函数。

PS:一些函数参数或者功能解释都放在代码注释里面了

创建目录

// 创建目录func createDir() {err := os.Mkdir("test_dir", os.ModePerm)if err != nil {fmt.Println("创建目录失败")return}fmt.Println("创建目录成功")}

创建文件

// 创建文件func createFile(filename string) {newfile, err := os.Create(filename)defer newfile.Close()if err != nil {fmt.Println("创建文件失败:", err)return}fmt.Println("创建文件成功:", newfile.Name())}

获取File信息

文件与目录都能判断

func getFileInfo() {//path := "test_dir"path := "test.txt"fileInfo, err := os.Stat(path)if err != nil {fmt.Println(err)return}fmt.Println("文件名:", fileInfo.Name())fmt.Println("文件大小:", fileInfo.Size())fmt.Println("文件权限:", fileInfo.Mode())fmt.Println("最后一次修改时间:", fileInfo.ModTime())fmt.Println("是否为目录: ", fileInfo.IsDir())//fmt.Println("系统接口类型: %T", fileInfo.Sys())//fmt.Println("系统信息: %+v", fileInfo.Sys())}

文件重命名

// 文件重命名func renameFile() {oldFileName := "text.txt"newFileName := "newtest.txt"err := os.Rename(oldFileName, newFileName)if err != nil {fmt.Println("重命名出错:", err)return}}

删除文件

// 删除文件func removeFile(fileaName string) {err := os.Remove(fileaName)if err != nil {fmt.Println("删除失败:", err)return}fmt.Println(fileaName, "删除成功")}

打开关闭文件

// 打开关闭文件// 介绍原始open打开文件与OpenFile可以提供更多的选项打开文件func open_close_file() {fmt.Println("os.Open打开文件")file, err := os.Open("test.txt")defer file.Close() //延迟关闭文件,建议打开文件后都习惯性写一个if err != nil {fmt.Println("os.Open打开文件失败:", err)return}fmt.Println("os.Open文件打开成功")//---------------------------------------------fmt.Println("os.OpenFile打开文件")file, err = os.OpenFile("test.txt", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("os.OpenFile打开文件失败:", err)return}fmt.Println("os.OpenFile打开文件成功")}

判断文件是否存在

// 判断文件是否存在func isExistFile(fileName string) {_, err := os.Stat(fileName)if err != nil {//因为报出错误可能有很多种原因,想要知道是不是文件不存在导致的err还需要验证if os.IsNotExist(err) {fmt.Println("确认这个错误是文件不存在导致的:", err)}}}

判断文件是否有读取权限

// 判断文件是否有读写权限func isPermission() {file, err := os.OpenFile("test.txt", os.O_RDONLY, 0666) //直接给O_WRONLY标志,可以判断是否有写权限defer file.Close()if err != nil {if os.IsPermission(err) {fmt.Println("没有读取权限:", err)}}fmt.Println("可读")file, err = os.OpenFile("test.txt", os.O_WRONLY, 0666) //直接给O_WRONLY标志,可以判断是否有写权限defer file.Close()if err != nil {if os.IsPermission(err) {fmt.Println("没有写权限", err)}}fmt.Println("可写")}

复制文件

// 文件复制func copyFile() {//打开一个你要复制的文件src_file, src_err := os.Open("test.txt")defer src_file.Close()if src_err != nil {fmt.Println("文件打开失败:", src_err)}//创建一个新文件用来复制内容到这里(其实可以用存在的文件继续打开也行,主要是用file句柄而已)des_file, des_err := os.Create("newtest.txt")defer des_file.Close()if des_err != nil {fmt.Println("文件创建失败", des_err)}//复制内容到新文件中bytesWritten, err := io.Copy(des_file, src_file) //bytesWritten是计算复制的长度if err != nil {fmt.Println("复制失败:", err)}fmt.Println("写入了:", bytesWritten)// 将文件内容flush到硬盘中,这操作对于我们现在来说是不必要的,// 因为在大多数情况下,程序正常退出时,数据会被操作系统自动刷新到磁盘。// 当我们在不断地写入内容的时候可能就需要不定期的进行flusherr = des_file.Sync()}

Read读取

// ---------------------------------------------------// 读取文件内容// ---------------------------------------------------// Read读取文件内容,返回读取的长度和内容,如果读取的长度小于切片的长度,说明文件读取完了func readFile() {//打开文件file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("打开文件失败:", err)return}bytes_content := make([]byte, 10)           //Read就是传进内容到这个切片空间中contentlen, err := file.Read(bytes_content) //返回的是读取的长度if err != nil {fmt.Println("读取文件失败:", err)return}fmt.Printf("读取长度:%d\n", contentlen)fmt.Println("读取内容:", string(bytes_content))}

ReadFull读取

// ReadFull读取文件内容,返回读取的长度和内容,如果读取的长度小于切片的长度会返回错误func readFullFile() {//打开文件file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("打开文件失败:", err)return}//ReadFull就是传进内容到这个bytes_content切片空间中,如果给的空间大于读取的内容就会报错,小于的的话给多少读多少bytes_content := make([]byte, 2)contentlen, err := io.ReadFull(file, bytes_content) //返回的是读取的长度if err != nil {fmt.Println("读取文件失败:", err)return}fmt.Printf("读取长度:%d\n", contentlen)fmt.Println("读取内容:", string(bytes_content))}

ReadAtLeast读取

// ReadAtLeast至少读取xx bytes文件内容func readAtLeastFile() {//打开文件file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("打开文件失败:", err)return}bytes_content := make([]byte, 512) //Read就是传进内容到这个切片空间中// io.ReadAtLeast()在拿不到最小的字节内容的时候会返回错误,// 如果你不return回去,// 他会把已读的文件保留。你依旧能够打印读取到的内容//相比ReadFull,ReadAtLeast不会报错,// 只是说最小字节数是至少读取这么多,// 但是依旧会往后读取,报错会留下已读取的内容minBytes := 10contentlen, err := io.ReadAtLeast(file, bytes_content, minBytes) //返回的是读取的长度if err != nil {fmt.Println("读取文件失败:", err)//return   //取消return,依旧能打印读取到的内容}fmt.Printf("读取长度:%d\n", contentlen)fmt.Println("读取内容:", string(bytes_content))}

ReadAll读取

// ReadAll读取文件所有内容func readAllFile() {//打开文件file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("打开文件失败:", err)return}// io.ReadAll()会读取所有的文件内容,返回的是读取的长度content, err := io.ReadAll(file) //返回的是读取的长度if err != nil {fmt.Println("读取文件失败:", err)return}fmt.Println("读取内容:", string(content))}

bufio读取

以下是 bufio.Scanner 中几种常用分割符的具体说明和示例:


bufio.ScanWords

  • 分割符: 空格( )或连续的空白字符(包括空格、制表符 \t、换行符 \n 等)。
  • 行为: 每次扫描一个单词(以空白字符分隔的字符串)。
  • 示例:
    scanner.Split(bufio.ScanWords)
    
    输入:
    "Hello   World\nGo Programming"
    
    输出:
    "Hello"
    "World"
    "Go"
    "Programming"
    

bufio.ScanLines

  • 分割符: 换行符(\n)。
  • 行为: 每次扫描一行(以换行符分隔的字符串)。
  • 示例:
    scanner.Split(bufio.ScanLines)
    
    输入:
    "Hello\nWorld\nGo Programming"
    
    输出:
    "Hello"
    "World"
    "Go Programming"
    

bufio.ScanBytes

  • 分割符: 无(按字节分割)。
  • 行为: 每次扫描一个字节。
  • 示例:
    scanner.Split(bufio.ScanBytes)
    
    输入:
    "Hello"
    
    输出:
    'H'
    'e'
    'l'
    'l'
    'o'
    

bufio.ScanRunes

  • 分割符: 无(按字符分割)。
  • 行为: 每次扫描一个字符(支持多字节字符,如中文)。
  • 示例:
    scanner.Split(bufio.ScanRunes)
    
    输入:
    "你好,世界!"
    
    输出:
    '你'
    '好'
    ','
    '世'
    '界'
    '!'
    

总结

分割函数分割符行为示例输入示例输出
bufio.ScanWords空格( )或连续空白字符每次扫描一个单词"Hello World\nGo""Hello", "World", "Go"
bufio.ScanLines换行符(\n每次扫描一行"Hello\nWorld\nGo""Hello", "World", "Go"
bufio.ScanBytes每次扫描一个字节"Hello"'H', 'e', 'l', 'l', 'o'
bufio.ScanRunes每次扫描一个字符(支持多字节字符)"你好,世界!"'你', '好', ',', '世', '界', '!'

注意事项

  1. bufio.ScanWords:

    • 会忽略连续的空白字符(如多个空格或制表符)。
    • 适合处理以空格分隔的文本。
  2. bufio.ScanLines:

    • 会保留每行的内容(包括行尾的空白字符)。
    • 适合处理逐行文本。
  3. bufio.ScanBytes:

    • 按字节分割,适合处理二进制数据或需要逐字节分析的场景。
  4. bufio.ScanRunes:

    • 按字符分割,支持多字节字符(如中文、日文、韩文等)。
    • 适合处理 Unicode 文本。

示例代码:

// bufio读取文件能够配合scanner一行一行读取,安全开发过程中可能用的最多,因为爆破的需求一般都是一行一行读取func bufioReadFile() {//打开文件file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("打开文件失败:", err)return}//bufio.NewReader()返回一个io.Reader对象,可以用来读取文件内容reader := io.Reader(file)//bufio.NewScanner()返回一个io.Scanner对象,可以用来读取文件内容scanner := bufio.NewScanner(reader)//scanner.Split(bufio.ScanWords) //按照空格分割//scanner.Split(bufio.ScanLines) //按照换行符分割 默认不写就是按照换行符分割//scanner.Split(bufio.ScanBytes) //按照字节分割//scanner.Split(bufio.ScanRunes) //按照字符分割for scanner.Scan() {fmt.Println(scanner.Text())}}

Write写入

// ---------------------------------------------------// 写入文件内容// ---------------------------------------------------func write() {file, err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR|os.O_APPEND,0666,)defer file.Close()if err != nil {fmt.Println("文件打开失败:", err)return}bytesWrittenLen, err := file.Write([]byte("hello hack\n"))if err != nil {fmt.Println("内容写入失败:", err)return}fmt.Printf("写入成功:%d字节长度\n", bytesWrittenLen)}

WriteFile快速写入

// 快速写内容// 用在需要快速简洁写入内容的时候func ioutil_WriteFile() {err := ioutil.WriteFile("test.txt", []byte("hello hack2\n"), 0666)if err != nil {fmt.Println("内容写入失败:", err)return}}

临时文件目录

  // 临时文件和目录,在开发工具的时候可能会用的上func tmpDir_File() {// 第一个参数是空字符串表示TempDir 会使用系统的默认临时目录。// 在 Linux/macOS 上,通常是 /tmp。// 在 Windows 上,通常是 C:\Users\<User>\AppData\Local\Temp。tempDir, err := ioutil.TempDir("", "tmpDirName")if err != nil {fmt.Println("创建失败:", err)return}fmt.Println("目录创建成功:", tempDir)tempFile, err := ioutil.TempFile(tempDir, "temp.txt") //创建文件要给参数:tempDir目录和temp文件名字if err != nil {fmt.Println("文件创建失败:", err)return}fmt.Println("文件创建成功:", tempFile.Name())//虽然说是临时文件也耀手动关闭文件defer tempFile.Close()err = os.Remove(tempFile.Name())if err != nil {fmt.Println("文件删除失败")return}err = os.Remove(tempDir)if err != nil {fmt.Println("目录删除失败")return}}

下载文件

// http get downLoad文件到本地func downLoadFile() {httpFile, err := os.OpenFile("baidu.html",os.O_CREATE|os.O_RDWR,0666,)if err != nil {fmt.Println("文件打开失败")}defer httpFile.Close()url := "http://www.baidu.com"rep, err := http.Get(url)defer rep.Body.Close()written, err := io.Copy(httpFile, rep.Body)if err != nil {fmt.Println("文件复制失败:", err)}fmt.Println("下载成功,文件大小(byte):\n", written)}

文件指针操作

func offsetFile() {//打开文件file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)defer file.Close()if err != nil {fmt.Println("打开文件失败:", err)return}//获取文件的偏移量var (offset int64 = 1whence int   = 1//whence用来计算offset的位置// 0 = 文件开始位置// 1 = 当前位置// 2 = 文件结尾处)newP, err := file.Seek(offset, whence)if err != nil {fmt.Println("获取文件偏移量失败:", err)return}fmt.Println("文件偏移量:", newP)//直接当前位置读取文件内容bytes_content := make([]byte, 10)           //Read就是传进内容到这个切片空间中contentlen, err := file.Read(bytes_content) //返回的是读取的长度if err != nil {fmt.Println("读取文件失败:", err)return}fmt.Printf("读取长度:%d\n", contentlen)fmt.Println("读取内容:", string(bytes_content))}

修改文件权限/拥有者/时间戳

参考文章:https://colobu.com/2016/10/12/go-file-operations/
这篇文章作者写的这真的很好,全是干货。

package mainimport ("log""os""time")func main() {// 使用Linux风格改变文件权限err := os.Chmod("test.txt", 0777)if err != nil {log.Println(err)}// 改变文件所有者err = os.Chown("test.txt", os.Getuid(), os.Getgid())if err != nil {log.Println(err)}// 改变时间戳twoDaysFromNow := time.Now().Add(48 * time.Hour)lastAccessTime := twoDaysFromNowlastModifyTime := twoDaysFromNowerr = os.Chtimes("test.txt", lastAccessTime, lastModifyTime)if err != nil {log.Println(err)}}

知识细节补充

OS.OpenFile

先介绍一下这个openfile功能,之前我是使用os.open来打开文件, 但是只能以只读的方式打开文件,而openfile更通用的文件打开函数,可以指定打开模式(只读、只写、读写等)和文件权限。接下来我都会使用openfile来操作文件,更精细化控制文件。

⽂件打开模式标志,在使用openfile的时候需要以一个怎样的模式打开文件

比如:os.OpenFile("example.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
多个形式可以用|管道符分开,表示可读可写,同时CREATE表示当文件不存在的时候创建,同时APPEND表示追加模式。
更多模式可以看下面介绍

os.O_RDONLY:只读模式打开⽂件。 
os.O_WRONLY:只写模式打开⽂件。 
os.O_RDWR:读写模式打开⽂件。 
os.O_APPEND:追加模式。如果⽂件已存在,数据将写⼊⽂件末尾。 
os.O_CREATE:如果⽂件不存在,则创建⽂件。 
os.O_EXCL:与 os.O_CREATE ⼀起使⽤,⽂件必须不存在。 
os.O_SYNC:同步 I/O,保证写⼊数据和元数据同步到存储设备。
os.O_TRUNC:如果⽂件已存在,打开时将其⻓度截断为零。

细节写在前头:我们读取完或者写入完后,文件指针是不在开头的,如果你读取完就直接写入就是在你读取到的当前位置写入,或者你写入完成后继续读取就是在当前位置读取,可能读取不到你想要的内容,所以file.Seek就很有必要了,或者你重新打开该文件也可以自动将指针指向开头。


演示代码:
打开一个文件写入hello hack,然后读取这个文件内容

  • O_RDWR:可读可写
  • O_CREATE:文件不存在就创建
  • O_APPEND:追加模式
  • 最后的0666是文件操作权限,这里就涉及到linux的文件权限问题了(忽略,后面讲)
func write_readTest() {file, err := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)defer file.Close()if err != nil {fmt.Println(err)return}file.WriteString("hello hack") // 写入文件// 读取文件scanner := bufio.NewScanner(file)//读取完文件后,文件指针已经到了文件末尾,需要重新定位到文件开头// 将文件指针重新定位到文件开头file.Seek(0, 0)for scanner.Scan() {fmt.Println(scanner.Text()) //一行一行读取}if err := scanner.Err(); err != nil {fmt.Println("读取文件失败:", err)}}

bufio

我们在编解码的时候就用了这个bufio,我们可以new一个scanner来一行一行读取文件内容,如果你需要更细粒度的控制(如按字节读取),可以使用 bufio.Reader

//常用方法
file, err := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)// 读取文件scanner := bufio.NewScanner(file)for scanner.Scan() {fmt.Println(scanner.Text()) //一行一行读取}if err := scanner.Err(); err != nil {fmt.Println("读取文件失败:", err)}

os.Stat

os.Stat 是 Go 语言中用于获取文件或目录信息的函数。它的作用是返回一个描述文件或目录状态的对象(os.FileInfo

  • 参数 name:

    • 接受一个字符串参数,表示文件或目录的路径。

    • 可以是相对路径(如 "../example.txt 或者目录 ../dirname")或绝对路径(如 "/home/user/example.txt")。

    • 也可以是文件名(如果文件在当前工作目录下)。

  • 返回值:

    • FileInfo: 一个接口类型,包含文件或目录的详细信息。

    • error: 如果操作失败(如文件不存在),返回错误信息。

os.fileInfo

os.FileInfo 是一个接口,包含以下方法:

方法名返回值类型说明
Name() stringstring返回文件或目录的名称(不包括路径)。
Size() int64int64返回文件的字节大小(目录通常返回 0)。
Mode() FileModeFileMode返回文件的权限和模式。
ModTime() time.Timetime.Time返回文件的最后修改时间。
IsDir() boolbool判断是否是目录。
Sys() interface{}interface{}返回底层数据源(通常为 nil)。

文件权限

使用⼋进制数表示⽂件的权限,这里是linux文件权限管理的知识,不懂自查。

os.ModePerm:⽂件的默认权限(0777)

os.ModeDir:表示⼀个⽬录。 
os.ModeAppend:表示⽂件只能追加写⼊。 
os.ModeExclusive:表示⽂件是独占的。 
os.ModeTemporary:表示⽂件是临时⽂件。 
os.ModeSymlink:表示⽂件是⼀个符号链接。 
os.ModeDevice:表示⽂件是⼀个设备⽂件。 
os.ModeNamedPipe:表示⽂件是⼀个命名管道。 
os.ModeSocket:表示⽂件是⼀个 Unix 域套接字。 
os.ModeSetuid:表示⽂件具有 setuid 位。 
os.ModeSetgid:表示⽂件具有 setgid 位。 
os.ModeCharDevice:表示⽂件是⼀个字符设备。 
os.ModeSticky:表示⽂件具有粘滞位。 
os.ModeIrregular:表示⽂件是⼀个不规则⽂件。

参考文章:https://colobu.com/2016/10/12/go-file-operations


http://www.ppmy.cn/ops/163260.html

相关文章

ADC采集模块与MCU内置ADC性能对比

2.5V基准电压源&#xff1a; 1. 精度更高&#xff0c;误差更小 ADR03B 具有 0.1% 或更小的初始精度&#xff0c;而 电阻分压方式的误差主要来自电阻的容差&#xff08;通常 1% 或 0.5%&#xff09;。长期稳定性更好&#xff0c;分压电阻容易受到温度、老化的影响&#xff0c;长…

java入门-方法(超详细)

第一章 方法的介绍和基本使用 1.方法介绍以及简单方法定义&#xff08;无参无返回值&#xff09; 1.问题描述&#xff1a; 之前所有的代码都在main方法中写&#xff0c;如果我们将来将所有功能的代码都放在main方法中&#xff0c;会显得main方法太乱&#xff0c;不好维护 解决…

前端八股——JS+ES6

前端八股&#xff1a;JSES6 说明&#xff1a;个人总结&#xff0c;用于个人复习回顾&#xff0c;将持续改正创作&#xff0c;已在语雀公开&#xff0c;欢迎评论改正。

Datawhale 数学建模导论二 笔记5 多模数据与智能模型

主要涉及到的知识点有&#xff1a; 数字图像处理与计算机视觉 计算语言学与自然语言处理 数字信号处理与智能感知 10.1 数字图像处理与计算机视觉 视觉信息是我们第一种非常规的数据模式&#xff0c;在Python当中可以使用opencv处理数字图像&#xff0c;并提取出视觉特征用…

速率分裂多址(RSMA)详解

1. 引言 随着无线通信技术的不断发展&#xff0c;频谱资源日益紧张&#xff0c;如何提高频谱效率、减少用户间干扰成为研究热点。速率分裂多址&#xff08;Rate-Splitting Multiple Access&#xff0c;RSMA&#xff09;作为一种新兴的非正交多址&#xff08;NOMA&#xff09;技…

【计算机网络】考研复试高频知识点总结

文章目录 一、基础概念1、计算机⽹络的定义2、计算机⽹络的目标3、计算机⽹络的组成4、计算机⽹络的分类5、计算机⽹络的拓扑结构6、计算机⽹络的协议7、计算机⽹络的分层结构8、OSI 参考模型9、TCP/IP 参考模型10、五层协议体系结构 二、物理层1、物理层的功能2、传输媒体3、 …

Netty笔记1:线程模型

Netty笔记1&#xff1a;线程模型 Netty笔记2&#xff1a;零拷贝 Netty笔记3&#xff1a;NIO编程 Netty笔记4&#xff1a;Epoll Netty笔记5&#xff1a;Netty开发实例 Netty笔记6&#xff1a;Netty组件 Netty笔记7&#xff1a;ChannelPromise通知处理 Netty笔记8&#xf…

springboot + mybatis-plus + druid

目录架构 config MyMetaObjectHandler.java package com.example.config;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component;import java.util.Date;Com…