Golang学习(二十五)文件操作

文件在程序中是以流的形式来操作的

 

 在GO语言中有个OS包是专门用来对文件做操作的,打开官方文档

Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国

 

找到type file 结构体,这个结构体下定义了大量针对文件操作的方法

 

一、读取文件

1、打开、关闭文件

#打开文件
func Open(name string) (file *File, err error)


#关闭文件
func (f *File) Close() error

 案例

package main

import (
	"fmt"
	"os"
)

func  main()  {
	file ,err:= os.Open("/root/11.txt")
	//概念说明  file的叫法
	//1、 file 叫 文件对象
	//2、 file 叫 文件句柄
	//3、 file 叫 文件指针
	//这些都是一个意思
	if err != nil {
		//如果err值不为空说明打开失败了
		fmt.Println("打开文件失败")
	}
	fmt.Printf("%v",file)  //指针类型


	err = file.Close()
	if err != nil {
		//如果err值不为空说明打开失败了
		fmt.Println("关闭失败失败",err)
	}
}

如果没有打开的返回值

#打开文件失败 
open /root/111.txt: The system cannot find the file specified.


#没有打开,无法关闭
<nil>关闭失败失败 invalid argument 

2、读取文件内容并显示在终端

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func  main()  {
	file ,err:= os.Open("E:/tar/11.txt")
	if err != nil {
		fmt.Println("打开文件失败")
	}

	defer file.Close()  //当函数退出时,要及时关闭file句柄,否则会有内存泄露



	reader := bufio.NewReader(file)     //func NewReader(rd io.Reader) *Reader
										//NewReader创建一个具有默认大小缓冲区
										//默认缓存区为4096字节,在*Reader中可以查看代码
	                                    //缓冲的好处: 读一部分,处理一部分,用于处理大文件

	for {


		str,err := reader.ReadString('\n')   //读取文件内容,读到一个\n换行就结束

		if err == io.EOF{   //io.EOF表示文件末尾,说明读取文件结束了,break结束就行
			break
		}
		fmt.Print(str)

	}
	fmt.Println("文件读取结束")
}

3、一次性读取文件(不带缓存)

读取整个文件到内存,使用ioutil包,适用于文件较小的场景

package main

import (
	"fmt"
	"io/ioutil"
)

func  main()  {

	file := "E:/tar/11.txt"
	content,err := ioutil.ReadFile(file) //使用ioutil.ReadFile一次将文件读取到内存中
	if err != nil{
		fmt.Println("读取文件错误",err)
	}


	fmt.Print("%v",content) //[]byte
	fmt.Print("%v",string(content))  //因为是切片,不能直接输出,要转换为string类型
}

我们没有显示的Open文件  因此也不需要显示的Close文件
因为文件的Open和Close被封装到ReadFile函数内部

二、创建文件

 创建文件,我们使用OS包中的OpenFile函数,如下图

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)


#参数说明
name string     //将内容写入到那个文件中去
flag int        //文件打开模式
perm FileMode   //文件权限

文件打开模式

const (
    O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
    O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
    O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件
    O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
    O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件
    O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在
    O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/O
    O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件
)

文件权限(主要是linux用)

const (
    // 单字符是被String方法用于格式化的属性缩写。
    ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目录
    ModeAppend                                     // a: 只能写入,且只能写入到末尾
    ModeExclusive                                  // l: 用于执行
    ModeTemporary                                  // T: 临时文件(非备份文件)
    ModeSymlink                                    // L: 符号链接(不是快捷方式文件)
    ModeDevice                                     // D: 设备
    ModeNamedPipe                                  // p: 命名管道(FIFO)
    ModeSocket                                     // S: Unix域socket
    ModeSetuid                                     // u: 表示文件具有其创建者用户id权限
    ModeSetgid                                     // g: 表示文件具有其创建者组id的权限
    ModeCharDevice                                 // c: 字符设备,需已设置ModeDevice
    ModeSticky                                     // t: 只有root/创建者能删除/移动文件
    // 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
    ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
    ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
)

1、创建文件 写入数据

package main

import (
	"bufio"
	"fmt"
	"os"
)

func  main()  {

	filePath := "e:/tar/abc.txt"     //设置创建的文件的路径

	file,err := os.OpenFile(filePath,os.O_WRONLY | os.O_CREATE,0666)
	                               //设置创建的这个文件的模式
	                               //O_WRONLY  只读打开文件
	                               //O_CREATE 如果没有该文件则进行创建
	                               //0666     给linux操作系统用的,windows无效

	if err != nil{               //判断是否打开操作成功
		fmt.Println(err)
		return
	}
	defer file.Close()     //及时关闭file句柄,防止内存泄露




	str := "hello Gardon\r\n"  //准备要写入的数据
	                           //  \n表示换行 ,有一些编辑器只认\r  这里为了方便都写上


	writer := bufio.NewWriter(file)   //因为写入数据不固定,我们建立缓存区

	for i :=0 ; i < 5 ; i++{
		writer.WriteString(str)  //写入数据到缓存
	}

	writer.Flush()   //因为writer是带缓存的,当上面使用了writer.WriteString并没有写入到磁盘
	                 //而是写入了缓存区,我们需要调用Flush()这个方法将缓存的数据写入到磁盘中去
}

2、打开已存在的文件--覆盖原先的数据--写入新数据

package main

import (
	"bufio"
	"fmt"
	"os"
)

func  main()  {
	filePath := "e:/tar/abc.txt"  //指定已经存在的文件

	file,err := os.OpenFile(filePath,os.O_WRONLY | os.O_TRUNC,0666)   //修改模式,变更为写入模式O_WRONLY和清除模式O_TRUNC
	if err != nil{
		fmt.Println(err)
		return
	}
	defer file.Close()



	str := "你好\r\n"  //修改字符

	writer := bufio.NewWriter(file)
	for i :=0 ; i < 10 ; i++{   //修改输入次数,我们这里输入10此您好
		writer.WriteString(str)
	}
	writer.Flush()
}

 

3、打开存在的文件追加文本(比如日志)

package main

import (
	"bufio"
	"fmt"
	"os"
)

func  main()  {

	filePath := "e:/tar/abc.txt"
	file,err := os.OpenFile(filePath,os.O_WRONLY | os.O_APPEND,0666)   //修改模式O_APPEND  追加数据和写入搭配
	if err != nil{
		fmt.Println(err)
		return
	}
	defer file.Close()



	str := "ABC\r\n"   //修改字符

	writer := bufio.NewWriter(file)
	for i :=0 ; i < 1 ; i++{   //修改输入次数
		writer.WriteString(str)
	}

	writer.Flush()
}

 

5、打开一个文件将原来的内容读取输出然后追加5句hello 北京

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func  main()  {

	filePath := "e:/tar/abc.txt"
	file,err := os.OpenFile(filePath,os.O_RDWR | os.O_APPEND,0666)   //修改模式  O_RDWR读写模式
	if err != nil{
		fmt.Println(err)
		return
	}
	defer file.Close()

	reader := bufio.NewReader(file)   //大量的读写操作都需要做缓存区
	for {
		str , err := reader.ReadString('\n') //上面案例有,读取整个文件的信息
		if err == io.EOF{      //读取到文件末尾后退出
			break
		}
		fmt.Println(str)    //将读取到的每一行数据打印到终端
	}


	str := "hello 北京\r\n"         //修改新增的字符

	writer := bufio.NewWriter(file)      //以缓存区模式去写入数据
	for i :=0 ; i < 5 ; i++{   //修改输入次数
		writer.WriteString(str)
	}
	writer.Flush()
}

6、文本内容转移

package main

import (
	"fmt"
	"io/ioutil"
)

func  main()  {
	//将"e:/tar/abc.txt" 文件导入到D:/kkk.txt
	//1 将"e:/tar/abc.txt"读取到内存
	//2 将读取到的内容写入到D:/kkk.txt

	file1Path := "e:/tar/abc.txt"
	file2Path := "D:/kkk.txt"


	data,err := ioutil.ReadFile(file1Path)    //一次性读取文件
	if err != nil{
		fmt.Printf("read file err=%v",err)
		return
	}

	err = ioutil.WriteFile(file2Path,data,0666)  //通过ioutil.WriteFile将data数据写入到路径中
	                                                   //写入的文件如果不存在,则会自动创建
	if err != nil{
		fmt.Printf("write file error=%v",err)
	}
}

7、判断文件是否存在

通过os.Stat 检索文件

package main

import (
	"fmt"
	"os"
)


func PathExists(path string)(bool,error){
	_, err := os.Stat(path)
	if err == nil{        //文件或目录存在
		return true,nil
	}

	if os.IsNotExist(err){  //如果os.lsNotExist(err)为true,说明文件不存在,返回false,和空
		return false,nil
	}

	return false,err  //如果上面都不满足,则输出原本的错误和信息
}


func  main()  {
	file1Path := "e:/tar/abc.txt"

	it,err := PathExists(file1Path)
	if it{
		fmt.Println("该文件/目录存在")
	}else {
		fmt.Println("该文件/目录不存在",err)
	}
}

 8、拷贝文件

通过IO包进行文件拷贝,支出拷贝大文件

//将一张图片拷贝到另一个目录下 io包
func Copy(dst Writer, src Reader) (written int64, err error)

//传参
Writer     //目标文件路径
Reader     //要拷贝的文件路径


//返回值
written   //拷贝文件的字节大小
err       //拷贝文件的错误信息

 案例

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

//我们这边写一个函数,接收要拷贝的路径,
func CopyFile(dstFileName string,srcFileName string)(written int64, err error){
	srcfile,err := os.Open(srcFileName)
	if err != nil{
		fmt.Println("文件打开错误",err)
	}
	defer srcfile.Close()
	reader := bufio.NewReader(srcfile)  //将这个文件放到缓存区 读取模式  src


	//我们拷贝过去的位置,这个文件不一定存在,我们就给他创建一下
	dstfile,err := os.OpenFile(dstFileName,os.O_WRONLY | os.O_CREATE, 0666)
	if err != nil{
		fmt.Printf("open file err=%v",err)
		return
	}
	defer dstfile.Close()
	writer := bufio.NewWriter(dstfile)     //给这个新建的文件以缓存模式打开  dest




	//拷贝源文件到目标文件
	return io.Copy(writer,reader)                //通过上面的IO包的Copy模块将数据拷贝过去
}

func main(){
	//将e:/tar/1.png 到d:/abc.png

	//调用CopyFile 完成拷贝
	srcFile := "e:/tar/1.png"  //图片、视频、音乐等都可以用这种方法拷贝
	dstFile := "d:/abc.png"
	_,err := CopyFile(dstFile,srcFile)
	if err == nil{
		fmt.Println("拷贝完成")
	}else{
		fmt.Println("拷贝错误")
	}

}

9、统计文件字符

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

//定义一个结构体,用于保存结果
type CharCount struct{
	ChCount int //记录英文的个数
	NumCount int  //记录数字的个数
	SpaceCount int // 记录空格个数
	OtherCount int // 用于记录其他字符
}

func main(){
	fileName := "e:/tar/abc.txt"
	file,err := os.Open(fileName)
	if err != nil {
		fmt.Println("open file error",err)
	}
	defer file.Close()


	var count CharCount      //声明结构体,用于统计各个字符的数量
	reader := bufio.NewReader(file)    //建立缓存区

	for {
		str,err := reader.ReadString('\n')    //遍历读取每一行数据
		if err == io.EOF{
			break
		}


		for _, v := range str{    //将每一行数据for-range遍历每个字符
			switch  {
			case v >= 'a' && v <= 'z' :       //比较ASCLL码,因为他是一个byte数组,会打印一些100、97等数字
				fallthrough                   //穿透处理,如果v在a到z之前会++,如果在A到Z直接也++
			case v >= 'A' && v <= 'Z':
				count.ChCount++
			case v == ' ' || v== '\t':      //如果是空格或者制表符的话,就在结构体+1
				count.SpaceCount++
			case v >= '0' && v <= '9':
				count.NumCount++
			default:
				count.OtherCount++
			}
		}
	}
	fmt.Printf("字符的个数%v 数字的个数%v  空格的个数%v 其他字符%v",count.ChCount,count.NumCount,count.SpaceCount,count.OtherCount)
}

 返回

字符的个数28 数字的个数0  空格的个数5 其他字符62
进程 已完成,退出代码为 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值