go语言学习【十一】


一、文件基本介绍

  • 文件是数据源(保存数据的地方)的一种。
  • 文件在程序中是以流的形式来操作的。
  • 流:数据在数据源(文件)和程序(内存)之间经历的路径。
  • 输入流:读文件;输出流:写文件。
  • os.File封装所有文件相关操作,File是一个结构体。

二、读文件常用操作

//读取和关闭文件
package main

import(
	"fmt"
	"os"
)
func main() {
	//打开文件
	file,err := os.Open("e:/test.txt") //打开E盘里的test文件
	if err !=nil {
		fmt.Println("open file err = ",err) //如果err!=nil,意味着没打开文件
	}

	//输出文件,查看内容
	fmt.Printf("file=%v",file)

	//关闭文件
	err = file.Close()
	if err !=nil {
		fmt.Println("close file err = ",err) 
	}
}

file=&{0xc00011a780} //表明文件返回一个指针

1.读取下面test.txt文件内容并显示在终端(带缓冲区的方法)【使用os.Open, file.Close, bufio.NewReader(), reader.ReadString 函数和方法】
在这里插入图片描述

package main

import(
	"fmt"
	"os"
	"bufio"
	"io"
)
func main() {
	//打开文件
	file,err := os.Open("e:/test.txt") 
	if err !=nil {
		fmt.Println("open file err = ",err) 
	}
	defer file.Close() //当函数退出时,可以及时关闭file句柄,防止内存泄漏

	//创建一个 *Reader,带缓冲,默认缓冲区为4096
	reader := bufio.NewReader(file) //返回 *Reader
	//循环读取文件内容
	for {
		str, err := reader.ReadString('\n') //读到一个换行就结束一次
		//输出内容
		fmt.Print(str)
		if err == io.EOF { //io.EOF表示文件的末尾
			break
		}
	}
}

输出结果:
在这里插入图片描述
2.对于如上述文件内存不大的情况,可以使用ioutil一次将整个文件读入到内存中。【相关方法和函数:ioutil.ReadFile】

package main

import(
	"fmt"
	"io/ioutil"
)
func main() {
	//使用 ioutil.ReadFile 一次性将文件读取到位
	file := "e:/test.txt"
	content,err := ioutil.ReadFile(file)
	if err!=nil {
		fmt.Printf("read file err=%v",err)
	}
	fmt.Printf("%v",string(content))
	//因为没有显式的Open文件,因此也不需要显式的Close文件
	//文件的Open和Close被封装到 ReadFile 内部
}
//与上一个方法输出结果一致

三、写文件常用操作

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

第二个参数(文件打开模式)的几种方式:
在这里插入图片描述
第三个参数(FileMode)代表文件的模式和权限位。在window系统无效。

写文件基本应用实例:
1.创建一个新文件,写入内容五句“hello golang”

package main

import(
	"fmt"
	"bufio"
	"os"
)
func main() {
	filePath := "e:/abc.txt"
	file,err := os.OpenFile(filePath,os.O_WRONLY|os.O_CREATE,0666)
	if err != nil {
		fmt.Printf("open file err=%v\n",err)
		return
	}

	//及时关闭file句柄
	defer file.Close()

	str := "hello,Golang!\n" 
	//写入时使用带缓冲的 *Writer
	writer := bufio.NewWriter(file)
	for i :=0;i<5;i++ {
		writer.WriteString(str)
	}
	//因为writer是带缓存的,在调用WriteString方法时,内容是先写入到缓存的
	//因此需要调用 Flush 方法将缓冲的数据写入磁盘
	//否则文件中会没有数据
	writer.Flush()
}

在这里插入图片描述
2.打开一个存在的文件,将原来的内容覆盖成新的10句内容“have a good day!”

package main

import(
	"fmt"
	"bufio"
	"os"
)
func main() {
	filePath := "e:/abc.txt"
	file,err := os.OpenFile(filePath,os.O_WRONLY|os.O_TRUNC,0666) //清空文件
	if err != nil {
		fmt.Printf("open file err=%v\n",err)
		return
	}

	//及时关闭file句柄
	defer file.Close()

	str := "have a good day!\n"
	//写入时使用带缓冲的 *Writer
	writer := bufio.NewWriter(file)
	for i :=0;i<10;i++ {
		writer.WriteString(str)
	}
	
	writer.Flush()
}

在这里插入图片描述
3.打开一个存在的文件,在原来的内容上追加内容“ABXCDEFGHIJKLMN”

package main

import(
	"fmt"
	"bufio"
	"os"
)
func main() {
	filePath := "e:/abc.txt"
	file,err := os.OpenFile(filePath,os.O_WRONLY|os.O_APPEND,0666) //清空文件
	if err != nil {
		fmt.Printf("open file err=%v\n",err)
		return
	}

	//及时关闭file句柄
	defer file.Close()

	str := "ABXCDEFGHIJKLMN\n"
	//写入时使用带缓冲的 *Writer
	writer := bufio.NewWriter(file)
	writer.WriteString(str)	
	writer.Flush()
}

在这里插入图片描述
4.将 e:/abc.txt 文件内容导入到 e:/aaa.txt

package main

import(
	"fmt"
	"io/ioutil"
)
func main() {
	//1.首先将 e:/abc.txt 内容读取到内存
	//2.将读取到的内存写入 e:/aaa.txt

	file1Path := "e:/abc.txt"
	file2Path := "e:/aaa.txt"

	data,err := ioutil.ReadFile(file1Path)
	if err != nil {
		//说明读取文件有错误
		fmt.Printf("read file err=%v\n",err)
		return
	}

	err2 := ioutil.WriteFile(file2Path,data,0666)
	if err2 != nil {
		fmt.Printf("write file err=%v\n",err)
	}
	
}

四、判断文件或目录存在

golang判断文件或文件夹是否存在的方法为使用os.Stat()函数返回的错误值进行判断;
1)如果返回的错误为nil,说明文件或文件夹存在。
2)如果返回的错误类型使用os.lsNotExist()判断为true,说明文件或文件夹不存在。
3)如果返回的错误为其它类型,则不确定是否在存在。

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

五、拷贝文件

使用下述函数进行拷贝
func Copy( dst Writer, src Reader) (written int64,err error)

package main

import(
	"fmt"
	"bufio"
	"os"
	"io"
)
//编写函数,接收两个文件路径
func CopyFile(dstFileName string,srcFileName string)(written int64,err error) {
	srcFile,err := os.Open(srcFileName)
	if err != nil {
		fmt.Printf("open file err=%v",err)
	}
	defer srcFile.Close()
	//通过srcFile,获取到Reader
	reader := bufio.NewReader(srcFile)

	//使用OpenFile方式打开目标文件 dstFile
	dstFile,err := os.OpenFile(dstFileName,os.O_WRONLY|os.O_CREATE,0666)
	if err != nil {
		fmt.Printf("open file err=%v",err)
		return
	}
	//通过dstFile,获取到 Writer
	writer := bufio.NewWriter(dstFile)
	defer dstFile.Close()

	return io.Copy(writer,reader)

}
func main() {
	//将 d:/run.jpg 文件拷贝到 e:/ccc.jpg
	srcFile := "d:/run.jpg"
	dstFile := "e:/ccc.jpg"
	_,err := CopyFile(dstFile,srcFile)
	if err == nil {
		fmt.Println("拷贝完成")
	} else {
		fmt.Printf("拷贝错误,err=%v",err)
	}
}

输出结果:

拷贝完成

使用这种拷贝方式,调用的函数中有缓冲功能,可以拷贝大文件。

六、文件编程应用实例

统计一个test文件中含有的英文、数字、空格及其它字符数量。
在这里插入图片描述

package main

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

//定义一个结构体,用于保存统计结果
type CharCount struct {
	ChCount int //记录英文个数
	NumCount int //记录数字个数
	SpaceCount int //记录空格个数
	OtherCount int //记录其它字符个数
}
func main() {
	//1.打开文件,创一个 *Reader
	//2.每读取一行,就去统计该行有多少个 英文、数字、空格和其它字符
	//3.将结果保存到一个结构体中

	fileName := "e:/test.txt"
	file,err := os.Open(fileName)
	if err != nil {
		fmt.Printf("open file err=%v\n",err)
		return
	}
	defer file.Close()
	//定义结构体实例
	var count CharCount

	reder := bufio.NewReader(file)
	//循环读取文件内容
	for{
		str,err := reder.ReadString('\n')
		//遍历str,进行统计
		for _,v := range str {
			switch {
			case v>='a'&& v<='z':
				fallthrough //穿透
			case v>='A'&& v<='Z':
				count.ChCount++
			case v>='0'&&v<='9':
				count.NumCount++
			case v==' '|| v=='\t':
				count.SpaceCount++
			default:
				count.OtherCount++
			}
		}
		if err == io.EOF {
			break
		}
	}
	fmt.Printf("字符个数=%v 数字个数=%v 空格个数=%v 其它字符个数=%v",
	count.ChCount,count.NumCount,count.SpaceCount,count.OtherCount)

}

输出结果:

字符个数=24 数字个数=23 空格个数=15 其它字符个数=22
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值