go语言入门十一 | 青训营笔记

89 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天

总结

  1. 文件

    1. 文件是一个指针类型:file , err := os.Open("/c/golang/fun.go")返回的是一个地址
    2. 文件打开就一定要关上:defer file.close()
  2. os包下的Open和OpenFile

    1. **file, err := os.Open("文件路径"):以只读方式打开文件,file存的是一个地址—指针类型**

    2. **func OpenFile(name string, flag int, perm FileMode) (file *File, err error):以固定的模式打开文件**

      • name 是文件的文件名,如果不是在当前路径下运行需要加上具体路径;

      • flag 是文件的处理参数,为 int 类型,根据系统的不同具体值可能有所不同,但是作用是相同的。以|作为拼接符

        • flag 的所有的常量在使用时加上io.,包括EOF
        **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     // 如果可能,打开时清空文件
        )**
        
      • **FileMode:可以示0666**

  3. 文件读取的三个方法

    1. io包:file.Read(以自定义的切分方式读取文件)

      1. 打开文件 file, err := os.Open("文件路径")
      2. 创建一个切片接收 buf := make([]byte, 1024*2)
      3. 循环读取文件内容:n, err := file.Read(buf)(读到buf中,返回字符个数n)
      4. 输出:fmt.Println(string(buf[:n]))(因为buf是个字节数组,以字节存储,想要正常输出需要string)
      5. 关闭文件 file.Close()
      **func main() {
      	//1.打开
      	file, err := os.Open("./51-main.go")
      	defer file.Close()  //2.一定会执行的文件关闭
      	if err != nil {     //3.判断文件打开是否成功
      		fmt.Println("文件打开失败", err)
      		return
      	}
      	fmt.Println("文件打开成功")
      
      	//4.创建一个切片 用来存储读取的内容
      	buf := make([]byte, 1024*2)
      	//5.循环读取文件内容
      	for {
      		n, err := file.Read(buf)//6.将文件内容读到buf中,返回字符个数n
      		if err != nil {
      			fmt.Println("文件读取失败", err)
      			return
      		}
      		//7.输出文件内容和字符个数
      		fmt.Println(string(buf[:n]))
      		fmt.Println(n)
      		//8.如果读取的内容小于1024字节,就结束循环(顺序不能乱,先输出再判断结束)
      		if n < 1024*2 {
      			break
      		}
      	}
      }**
      
    2. ioutil包:ioutil.ReadFile(使用ioutil一次将文件读取到内存中,返回一个切片)用于文件不大的情况

      1. 读取文件内容 content, err := ioutil.ReadFile("文件路径") (返回的是个字节数组,以字节存储,想要正常输出需要string)

      2. 打印文件内容 fmt.Println(string(content))

      • func ReadFile(filenamestring) ([]byte,error)

        ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为**读取整个文件,**它不会将读取返回的EOF视为应报告的错误。

      **func main(){
          //1.使用ioutil一次性将函数读取到
          file := "/c/golang/aa.go"
          content, err := ioutil.ReadFile(file)
          //2.文件的打开和关闭都被隐藏起来了。所以不需要写打开和关闭
          if err != nil{
              fmt.Printf("file open err= %v",err)
          }
          //3.把读取到的内容显示到终端
          //fmt.Printf("%v",content)  //[]bype,以字节的形式存储
          fmt.Printf("%v",string(content))  //需要转换为string
      }**
      
    3. bufio包:reader.ReadString(”\n”)(每个缓冲区存储的字节是固定的)

      1. 只读方式打开文件 file, err := os.Open("test.txt")

      2. 创建一个 Reader 是带缓冲的 :reader := bufio.NewReader(file)

      3. 循环的调用 reader.ReadString('\n') 读取文件的内容

      4. 关闭文件 defer file.Close()

      • func NewReader(rdio.Reader) *Reader

        NewReader创建一个具有默认大小缓冲、从r读取的*Reader。

      • func (b *Reader) ReadString(delimbyte) (linestring, errerror)

        ReadString读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的字符串。如果ReadString方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadString方法返回的切片不以delim结尾时,会返回一个非nil的错误。

      **func main(){
      		//1.打开文件
          file, err := os.Open("/c/golang/fun.go")
          if err != nil{
              fmt.Println("open file = ",err)
          }
      
          //2.及时关闭文件
          defer file.Close()
      		//3.读取文件时,使用带缓存的*Reader
          reader := bufio.NewReader(file)
      
          //4.循环的读取文件的内容
          for{
              str,err := reader.ReadString('\n')
              //读取到一行就结束,err 错误信息提示
              fmt.Println(str)
      				if err == io.EOF{
                  //io.EOF表示文件的末尾,此时结束读取
                  break
              }
          }
          fmt.Println("文件读取结束...")
      }**
      
  4. 写文件的三个方法(同读类似)

    1. io包:file.Write

    2. ioutil包:ioutil.WriteFile

      • func WriteFile(filenamestring, data []byte, permos.FileMode)error

        函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。

    3. bufio包:reader.WriteString(str)

      • func NewWriter(wio.Writer) *Writer

        NewWriter创建一个具有默认大小缓冲、写入w的*Writer。

      • func (b *Writer) WriteString(sstring) (int,error)

        WriteString写入一个字符串。返回写入的字节数。如果返回值nn < len(s),还会返回一个错误说明原因。

      **func main() {
          //1.创建一个新文件,写入内容 5 句 “<http://c.biancheng.net/golang/”>
          filePath := "e:/code/golang.txt"
      		//2.以固定的处理参数读文件
          file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
          if err != nil {
              fmt.Println("文件打开失败", err)
          }
          //3.及时关闭file句柄
          defer file.Close()
      
          //4.写入文件时,使用带缓存的 *Writer
          write := bufio.NewWriter(file)
          for i := 0; i < 5; i++ {
              write.WriteString("<http://nsddd.top>\n")
          }
          //5.Flush将缓存的文件真正写入到文件中
          write.Flush()
      }**
      
  5. 判断文件或文件夹是否存在:os.Stat()

    1. 如果返回的错误为nil,说明文件或文件夹存在
    2. 如果返回的错误类型为os.lsNotExist()判断为true,说明文件或者文件夹不存在
    3. 如果返回值的错误类型为其他类型,则不确定是否存在
    **func PathExists(path string)(bool,error){  //传送路径path
    	_,err := os.Stat(path)
    	if err == nil {
    	//存在
    		return true,nil
    	}
    	//不存在
    	if os.lsNotExist(err){
    		return false,nil
    	}
    	//未知
    	return false,err    //可能有其他的错误信息
    }**
    
  6. 复制文件—复现完成

    1. 打开源文件 srcFile, err := os.Open("test.txt")

    2. 创建目标文件 dstFile, err := os.Create("test_copy.txt")

    3. *创建一个 Reader 是带缓冲的 reader := bufio.NewReader(srcFile)

    4. *创建一个 Writer 是带缓冲的 writer := bufio.NewWriter(dstFile)

    5. 循环的调用 reader.ReadString('\n') 读取文件的内容

    6. 调用 writer.WriteString(str) 将读取到的内容写入到目标文件中

    7. 调用 writer.Flush() 将缓冲区的内容写入到目标文件中

    8. 关闭文件 defer srcFile.Close()

    9. io包里的Copy

      func Copy(dstWriter, srcReader) (writtenint64, errerror)

      将src的数据拷贝到dst,直到在src上到达EOF或发生错误。返回拷贝的字节数和遇到的第一个错误。对成功的调用,返回值err为nil而非EOF,因为Copy定义为从src读取直到EOF,它不会将读取到EOF视为应报告的错误。如果src实现了WriterTo接口,本函数会调用src.WriteTo(dst)进行拷贝;否则如果dst实现了ReaderFrom接口,本函数会调用dst.ReadFrom(src)进行拷贝。

    **//自己编写一个函数,接收两个文件路径 srcFileName dstFileName
    func CopyFile(dstFileName string, srcFileName string) (written int64, err error) {
    	//1.打开读文件	
    	srcFile, err := os.Open(srcFileName)
    	if err != nil {
    		fmt.Printf("open file err=%v\n", err)
    	}
    	//2.关闭
    	defer srcFile.Close()
    	//3.通过srcfile ,获取到缓冲流 Reader
    	reader := bufio.NewReader(srcFile)
    	//4.打开dstFileName
    	dstFile, err := os.OpenFile(dstFileName, os.O_WRONLY | os.O_CREATE, 0666)
    	if err != nil {
    		fmt.Printf("open file err=%v\n", err)
    		return
    	}
    	//5.通过dstFile, 获取到缓冲流 Writer
    	writer := bufio.NewWriter(dstFile)
    	//6.关闭
    	defer dstFile.Close()
    	//7.省略ReadString、WriteString和Flush,直接使用io自带的Copy
    	return io.Copy(writer, reader)
    }
    
    func main() {
    	//将d:/flower.jpg 文件拷贝到 e:/abc.jpg
    	//调用CopyFile 完成文件拷贝
    	srcFile := "d:/flower.jpg"
    	dstFile := "e:/abc.jpg"
    	_, err := CopyFile(dstFile, srcFile)
    	if err == nil {
    		fmt.Printf("拷贝完成\n")
    	} else {
    		fmt.Printf("拷贝错误 err=%v\n", err)
    	}
    }**
    
  7. 实践:统计一个文本文件中各个字符的个数(结构体,读、写)—复现完成

    switch{}与if的等价性