golang中处理文件有不少种方式,下面咱们来看看。python
先来看看如何查看文件属性linux
package main import ( "fmt" "os" ) func main() { //打开文件使用os.Open函数,会返回一个文件句柄和一个error file, err := os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) if err != nil { fmt.Println("文件打开失败:",err) } //调用file.Stat()能够查看文件的信息,这是一个os.FileInfo对象 info, err := file.Stat() //属性以下 /* type FileInfo interface { Name() string // 文件名 Size() int64 // 文件的大小,按字节计算 Mode() FileMode // 文件的模式 ModTime() time.Time // 修改时间 IsDir() bool // 是不是目录 Sys() interface{} // 数据源,通常不用管 } */ fmt.Println(info.Name()) // whiteblum.txt fmt.Println(info.Size()) // 183 //有点相似于linux里面的,第一个-表示文本文件,后面的三个rw-表示可读可写不可执行。 //分别是用户、用户所属组、其余组的权限 fmt.Println(info.Mode()) // -rw-rw-rw- fmt.Println(info.ModTime()) // 2019-08-31 19:52:44.3146692 +0800 CST fmt.Println(info.IsDir()) // false fmt.Println(info.Sys()) // &{32 {2579124676 30760946} {2579124676 30760946} {2579124676 30760946} 0 183} }
读取文件里面的内容ios
package main import ( "fmt" "os" ) func main() { file, err := os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) if err != nil { fmt.Println("文件打开失败:",err) } //忘记说了,文件打开是要关闭的,调用defer函数便可 defer file.Close() //此外file.Name()还能够拿到文件的所在路径,file.Fd()则是拿到文件的描述符 fmt.Println(file.Name()) //D:\komeijisatori\src\day3\whiteblum.txt fmt.Println(file.Fd()) // 216 //读取文件内容能够调用file.Read()方法,接收一个字节数组,返回一个int和error buf := make([]byte, 12) //此时文件的内容都会读到buf里面,n则是写入了多少个字节,n不会超过字节数组buf的长度 n, err := file.Read(buf) //将写入的内容读取出来 fmt.Println(string(buf[:n])) //白色相簿 }
咱们注意到:当前只是读取了12个字节,并无所有读取完。这是由于咱们的buf长度只有12,咱们能够将容量变得更大一些,可是到底要弄多大呢?这是一个未知数。弄小了一次读不完,要是弄大了,会浪费。所以最好的办法,不要一次就读完,而是循环读取,这样不就行了吗?通常的话,咱们都将buf的长度设置为1024个字节,但因为个人文件比较小,因此就设置为12个字节
golang
package main import ( "fmt" "io" "os" ) func main() { file, err := os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) if err != nil { fmt.Println("文件打开失败:",err) } defer file.Close() buf := make([]byte, 12) // 存放文件内容的缓存,至关于中转站 data := make([]byte, 0) // 用来存放文件内容,buf读取的内容都会写到data里面去 for { //无限循环,不断读取 n, err := file.Read(buf) // 何时文件读完呢?若是文件读完的话,那么err不为nil,而是io.EOF // 因此咱们能够进行判断 if err != nil { //若是err != nil说明出错了,但若是还等于io.EOF的话,说明读完了,由于文件读完,err也不为nil。直接break if err == io.EOF{ break } else { //若是错误不是io.EOF的话,说明就真的在读取中出现了错误,直接panic出来 panic(err) } } //此时文件内容写到buf里面去了,写了多少个呢?写了n个,那么咱们再写到data里面去 data = append(data, buf[: n]...) //咱们来打印一下,每次写了多少个字节 fmt.Printf("写入%d个字节\n", n) /* 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入12个字节 写入6个字节 */ } //写完以后,咱们来打印一下 fmt.Println(string(data)) /* 白色相簿什么的,已经无所谓了。 由于已经再也不有歌,值得去唱了。 传达不了的恋情,已经不须要了。 由于已经再也不有人,值得去爱了。 */ }
那么如何使用os模块来写入文件呢?web
package main import ( "fmt" "os" ) func main() { //既然要写,那么就不能使用Open了,而是使用Create //Create会建立一个文件,若是存在会清空原有的内容 file, err := os.Create(`D:\komeijisatori\src\day3\whiteblum.txt`) if err != nil { fmt.Println("文件建立失败:",err) } defer file.Close() //写入文件能够调用file.WriteString,或者file.Write方法 //前者是写入字符,后者是写入字节。 // 其实WriteString底层是将咱们传入的字符串变成字节数组,而后仍是调用Write方法 //会有两个返回值,一个是咱们写入的个数,一个是error n, err := file.WriteString("这是新写入的内容,原来的内容会丢失") //golang是按照字节算的,一个汉字占三个字节 fmt.Println(n) // 51 //再来读取一下看看,有没有写入 file, err = os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) //直接将数组设置的大一些,一次读取完毕 new_buf := make([]byte, 1024) n, _ = file.Read(new_buf) fmt.Println(string(new_buf[: n])) // 这是新写入的内容,原来的内容会丢失 }
其实不管是Open仍是Create,底层都是调用了OpenFile数组
package main import ( "fmt" "os" ) func main() { // OpenFile接收三个参数 // 1.文件名 // 2.文件的模式,支持以下 /* os.O_RDONLY: 以只读的方式打开 os.O_WRONLY: 以只写的方式打开 os.O_RDWR : 以读写的方式打开 os.O_NONBLOCK: 打开时不阻塞 os.O_APPEND: 以追加的方式打开 os.O_CREAT: 建立并打开一个新文件 os.O_TRUNC: 打开一个文件并截断它的长度为零(必须有写权限) os.O_EXCL: 若是指定的文件存在,返回错误 os.O_SHLOCK: 自动获取共享锁 os.O_EXLOCK: 自动获取独立锁 os.O_DIRECT: 消除或减小缓存效果 os.O_FSYNC : 同步写入 os.O_NOFOLLOW: 不追踪软连接 */ // 3.权限,通常设置为0666,这在linux下有用,Windows下面没太大卵用 // 以只写的方式打开,而且写入的时候,是以追加的形式写入 file, _ := os.OpenFile(`D:\komeijisatori\src\day3\whiteblum.txt`,os.O_WRONLY|os.O_APPEND, 0666) _, _ = file.Write([]byte("\n这是新的内容,可是原来的内容还在")) //写入以后,咱们再以只读方式打开 file, _ = os.OpenFile(`D:\komeijisatori\src\day3\whiteblum.txt`,os.O_RDONLY, 0666) buf := make([]byte, 1024) n, _ := file.Read(buf) fmt.Println(string(buf[: n])) /* 这是新写入的内容,原来的内容会丢失 这是新的内容,可是原来的内容还在 */ }
可是一般咱们直接使用Open和Create函数
缓存
bufio至关因而在os.OpenFile获得的文件句柄之上进行一层封装,bufio,从名字上也能看出来是带缓存的io。websocket
package main import ( "bufio" "fmt" "io" "os" ) func main() { file, _ := os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) //使用bufio.NewReader进行一层包装 reader := bufio.NewReader(file) //首先这个reader,能够像file同样,使用Read方法 //然而reader还但是按照指定字符来读,好比我想一行一行读,就能够指定换行符来读 for{ //返回string和error s, err := reader.ReadString('\n') //表示每读到\n就中止 //这里使用print,由于文件自己有换行符,println自带换行,因此使用print fmt.Print("读取一行:", s) /* 读取一行:白色相簿什么的,已经无所谓了。 读取一行:由于已经再也不有歌,值得去唱了。 读取一行:传达不了的恋情,已经不须要了。 读取一行:由于已经再也不有人,值得去爱了。 */ if err != nil { if err == io.EOF{ break } else { panic(err) } } } }
package main import ( "bufio" "bytes" "fmt" "os" ) func main() { file, _ := os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) //除了NewReader,还有一个NewScanner scanner := bufio.NewScanner(file) for scanner.Scan(){ //能够看到咱们使用println打印,行与行之间没有空隙,说明scanner.Text()没有把换行符读进去。 fmt.Println(scanner.Text()) /* 白色相簿什么的,已经无所谓了。 由于已经再也不有歌,值得去唱了。 传达不了的恋情,已经不须要了。 由于已经再也不有人,值得去爱了。 */ } //可是这都是一行一行读的,咱们能够写到缓存里面去 //这个缓存使用bytes.Buffer{}来建立 buf := bytes.Buffer{} file, _ = os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) scanner = bufio.NewScanner(file) for scanner.Scan(){ //直接调用buf.WriteString便可 buf.WriteString(scanner.Text()) // 固然还可使用buf.Write写入字节,同时也可使用scanner.Bytes()获得字节。buf.Write(scanner.Bytes()) } //能够调用buf.Bytes()拿到字节 //也能够调用buf.String()拿到String fmt.Println(buf.String()) // 白色相簿什么的,已经无所谓了。由于已经再也不有歌,值得去唱了。传达不了的恋情,已经不须要了。由于已经再也不有人,值得去爱了。 //由于没有读取换行符,因此是连在一块儿的 //这里再提一下bytes.Buffer{},这是一个很是方便的字节缓存。用来组合字符串很是方便 buffer := bytes.Buffer{} buffer.WriteString("哈哈") buffer.WriteString("呱呱") buffer.Write([]byte("嘻嘻")) fmt.Println(buffer.String()) // 哈哈呱呱嘻嘻 fmt.Println(buffer.Bytes()) // [229 147 136 229 147 136 229 145 177 229 145 177 229 152 187 229 152 187] //固然buffer也有ReadString,和Read方法 s, _ := buffer.ReadString('\n') fmt.Println(s) // 哈哈呱呱嘻嘻 buffer.WriteString("你胸大,你先说") b := make([]byte, 1024) n, _ := buffer.Read(b) fmt.Println(string(b[: n])) // 你胸大,你先说 }
ioutil是一个很是强大模块app
package main import ( "fmt" "io/ioutil" "os" ) func main() { file, _ := os.Open(`D:\komeijisatori\src\day3\whiteblum.txt`) // 直接将file丢进去,能够读取所有内容 s, _ := ioutil.ReadAll(file) fmt.Println(string(s)) /* 白色相簿什么的,已经无所谓了。 由于已经再也不有歌,值得去唱了。 传达不了的恋情,已经不须要了。 由于已经再也不有人,值得去爱了。 */ // 是否是很方便呢?其实还有更方便的 //调用ReadFile,传入文件名直接获得字节数组和error。固然底层是使用了os.Open和ioutil.ReadAll s, _ = ioutil.ReadFile(`D:\komeijisatori\src\day3\whiteblum.txt`) fmt.Println(string(s)) /* 白色相簿什么的,已经无所谓了。 由于已经再也不有歌,值得去唱了。 传达不了的恋情,已经不须要了。 由于已经再也不有人,值得去爱了。 */ }
固然ioutil开能够写入文件
curl
package main import ( "bytes" "fmt" "io/ioutil" ) func main() { buf := bytes.Buffer{} buf.WriteString("明明是我先来的\n") buf.WriteString("为何会变成这样呢\n") buf.WriteString("何でそんなに慣れてんだよ\n") buf.WriteString("雪菜と何度もキースしたんだよ") //传入filename,content,权限 _ = ioutil.WriteFile(`D:\komeijisatori\src\day3\whiteblum.txt`, buf.Bytes(), 0666) //读取出来看看 s, _ := ioutil.ReadFile(`D:\komeijisatori\src\day3\whiteblum.txt`) fmt.Println(string(s)) /* 明明是我先来的 为何会变成这样呢 何でそんなに慣れてんだよ 雪菜と何度もキースしたんだよ */ }
以前说ioutil很强大,是由于还有别的用处,好比读取目录
package main import ( "fmt" "io/ioutil" ) func main() { files, _ := ioutil.ReadDir(`C:\python37\Lib\site-packages\tornado`) //返回一个[]os.FileInfo和error for _, file := range files{ if !file.IsDir(){ fmt.Println(file.Name()) /* __init__.py _locale_data.py auth.py autoreload.py concurrent.py curl_httpclient.py escape.py gen.py http1connection.py httpclient.py httpserver.py httputil.py ioloop.py iostream.py locale.py locks.py log.py netutil.py options.py process.py py.typed queues.py routing.py simple_httpclient.py speedups.cp37-win_amd64.pyd tcpclient.py tcpserver.py template.py testing.py util.py web.py websocket.py wsgi.py */ } } }