funcmain() { // Simple read only open. We will cover actually reading // and writing to files in examples further down the page file, err := os.Open("test.txt") if err != nil { log.Fatal(err) } file.Close()
// OpenFile with more options. Last param is the permission mode // Second param is the attributes when opening file, err = os.OpenFile("test.txt", os.O_APPEND, 0666) if err != nil { log.Fatal(err) } file.Close()
// Use these attributes individually or combined // with an OR for second arg of OpenFile() // e.g. os.O_CREATE|os.O_APPEND // or os.O_CREATE|os.O_TRUNC|os.O_WRONLY
// os.O_RDONLY // Read only // os.O_WRONLY // Write only // os.O_RDWR // Read and write // os.O_APPEND // Append to end of file // os.O_CREATE // Create is none exist // os.O_TRUNC // Truncate file when opening }
funcmain() { // Stat returns file info. It will return // an error if there is no file. fileInfo, err := os.Stat("test.txt") if err != nil { if os.IsNotExist(err) { log.Fatal("File does not exist.") } } log.Printf("File does exist. File information:\n%s", fileInfo) }
funcmain() { // Test write permissions. It is possible the file // does not exist and that will return a different // error that can be checked with os.IsNotExist(err) file, err := os.OpenFile("test.txt", os.O_WRONLY, 0666) if err != nil { if os.IsPermission(err) { log.Println("Error: Write permission denied.") } } file.Close()
// Test read permissions file, err = os.OpenFile("test.txt", os.O_RDONLY, 0666) if err != nil { if os.IsPermission(err) { log.Println("Error: Read permission denied.") } } file.Close() }
funcmain() { // Create a hard link // You will have two file names that point to the same contents // Changing the contents of one will change the other // Deleting/renaming one will not affect the other err := os.Link("original.txt", "original_also.txt") if err != nil { log.Fatal(err) }
fmt.Println("creating sym") // Create a symlink err = os.Symlink("original.txt", "original_sym.txt") if err != nil { log.Fatal(err) }
// Lstat will return file info, but if it is actually // a symlink, it will return info about the symlink. // It will not follow the link and give information // about the real file // Symlinks do not work in Windows fileInfo, err := os.Lstat("original_sym.txt") if err != nil { log.Fatal(err) } fmt.Printf("Link info: %+v", fileInfo)
// Change ownership of a symlink only // and not the file it points to err = os.Lchown("original_sym.txt", os.Getuid(), os.Getgid()) if err != nil { log.Fatal(err) } }
// Offset is how many bytes to move // Offset can be positive or negative var offset int64 = 5
// Whence is the point of reference for offset // 0 = Beginning of file // 1 = Current position // 2 = End of file var whence int = 0 newPosition, err := file.Seek(offset, whence) if err != nil { log.Fatal(err) } fmt.Println("Just moved to 5:", newPosition)
// Go back 2 bytes from current position newPosition, err = file.Seek(-2, 1) if err != nil { log.Fatal(err) } fmt.Println("Just moved back two:", newPosition)
// Find the current position by getting the // return value from Seek after moving 0 bytes currentPosition, err := file.Seek(0, 1) fmt.Println("Current position:", currentPosition)
// Go to beginning of file newPosition, err = file.Seek(0, 0) if err != nil { log.Fatal(err) } fmt.Println("Position after seeking 0,0:", newPosition) }
funcmain() { // Open a new file for writing only file, err := os.OpenFile( "test.txt", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666, ) if err != nil { log.Fatal(err) } defer file.Close()
// Write string to buffer // Also available are WriteRune() and WriteByte() bytesWritten, err = bufferedWriter.WriteString( "Buffered string\n", ) if err != nil { log.Fatal(err) } log.Printf("Bytes written: %d\n", bytesWritten)
// Check how much is stored in buffer waiting unflushedBufferSize := bufferedWriter.Buffered() log.Printf("Bytes buffered: %d\n", unflushedBufferSize)
// See how much buffer is available bytesAvailable := bufferedWriter.Available() if err != nil { log.Fatal(err) } log.Printf("Available buffer: %d\n", bytesAvailable)
// Write memory buffer to disk bufferedWriter.Flush()
// Revert any changes done to buffer that have // not yet been written to file with Flush() // We just flushed, so there are no changes to revert // The writer that you pass as an argument // is where the buffer will output to, if you want // to change to a new writer bufferedWriter.Reset(bufferedWriter)
// See how much buffer is available bytesAvailable = bufferedWriter.Available() if err != nil { log.Fatal(err) } log.Printf("Available buffer: %d\n", bytesAvailable)
// Resize buffer. The first argument is a writer // where the buffer should output to. In this case // we are using the same buffer. If we chose a number // that was smaller than the existing buffer, like 10 // we would not get back a buffer of size 10, we will // get back a buffer the size of the original since // it was already large enough (default 4096) bufferedWriter = bufio.NewWriterSize( bufferedWriter, 8000, )
// Check available buffer size after resizing bytesAvailable = bufferedWriter.Available() if err != nil { log.Fatal(err) } log.Printf("Available buffer: %d\n", bytesAvailable) }
funcmain() { // Open file for reading file, err := os.Open("test.txt") if err != nil { log.Fatal(err) } defer file.Close()
// Read up to len(b) bytes from the File // Zero bytes written means end of file // End of file returns error type io.EOF byteSlice := make([]byte, 16) bytesRead, err := file.Read(byteSlice) if err != nil { log.Fatal(err) } log.Printf("Number of bytes read: %d\n", bytesRead) log.Printf("Data read: %s\n", byteSlice) }
funcmain() { // Open file for reading file, err := os.Open("test.txt") if err != nil { log.Fatal(err) }
// The file.Read() function will happily read a tiny file in to a large // byte slice, but io.ReadFull() will return an // error if the file is smaller than the byte slice. byteSlice := make([]byte, 2) numBytesRead, err := io.ReadFull(file, byteSlice) if err != nil { log.Fatal(err) } log.Printf("Number of bytes read: %d\n", numBytesRead) log.Printf("Data read: %s\n", byteSlice) }
funcmain() { // Open file for reading file, err := os.Open("test.txt") if err != nil { log.Fatal(err) }
byteSlice := make([]byte, 512) minBytes := 8 // io.ReadAtLeast() will return an error if it cannot // find at least minBytes to read. It will read as // many bytes as byteSlice can hold. numBytesRead, err := io.ReadAtLeast(file, byteSlice, minBytes) if err != nil { log.Fatal(err) } log.Printf("Number of bytes read: %d\n", numBytesRead) log.Printf("Data read: %s\n", byteSlice) }
funcmain() { // Open file for reading file, err := os.Open("test.txt") if err != nil { log.Fatal(err) }
// os.File.Read(), io.ReadFull(), and // io.ReadAtLeast() all work with a fixed // byte slice that you make before you read
// ioutil.ReadAll() will read every byte // from the reader (in this case a file), // and return a slice of unknown slice data, err := ioutil.ReadAll(file) if err != nil { log.Fatal(err) }
fmt.Printf("Data as hex: %x\n", data) fmt.Printf("Data as string: %s\n", data) fmt.Println("Number of bytes read:", len(data)) }
2.10 快速读取全部文件到内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
package main
import ( "log" "io/ioutil" )
funcmain() { // Read file to byte slice data, err := ioutil.ReadFile("test.txt") if err != nil { log.Fatal(err) }
funcmain() { // Open file and create a buffered reader on top file, err := os.Open("test.txt") if err != nil { log.Fatal(err) } bufferedReader := bufio.NewReader(file)
// Get bytes without advancing pointer byteSlice := make([]byte, 5) byteSlice, err = bufferedReader.Peek(5) if err != nil { log.Fatal(err) } fmt.Printf("Peeked at 5 bytes: %s\n", byteSlice)
// Ready 1 byte. Error if no byte to read myByte, err := bufferedReader.ReadByte() if err != nil { log.Fatal(err) } fmt.Printf("Read 1 byte: %c\n", myByte)
// Read up to and including delimiter // Returns byte slice dataBytes, err := bufferedReader.ReadBytes('\n') if err != nil { log.Fatal(err) } fmt.Printf("Read bytes: %s\n", dataBytes)
// Read up to and including delimiter // Returns string dataString, err := bufferedReader.ReadString('\n') if err != nil { log.Fatal(err) } fmt.Printf("Read string: %s\n", dataString)
// This example reads a few lines so test.txt // should have a few lines of text to work correct }
funcmain() { // Open file and create scanner on top of it file, err := os.Open("test.txt") if err != nil { log.Fatal(err) } scanner := bufio.NewScanner(file)
// Default scanner is bufio.ScanLines. Lets use ScanWords. // Could also use a custom function of SplitFunc type scanner.Split(bufio.ScanWords)
// Scan for next token. success := scanner.Scan() if success == false { // False on error or EOF. Check error err = scanner.Err() if err == nil { log.Println("Scan completed and reached EOF") } else { log.Fatal(err) } }
// Get data from scan with Bytes() or Text() fmt.Println("First word found:", scanner.Text())
// This example uses zip but standard library // also supports tar archives package main
import ( "archive/zip" "log" "os" )
funcmain() { // Create a file to write the archive buffer to // Could also use an in memory buffer. outFile, err := os.Create("test.zip") if err != nil { log.Fatal(err) } defer outFile.Close()
// Create a zip writer on top of the file writer zipWriter := zip.NewWriter(outFile)
// Add files to archive // We use some hard coded data to demonstrate, // but you could iterate through all the files // in a directory and pass the name and contents // of each file, or you can take data from your // program and write it write in to the archive // without var filesToArchive = []struct { Name, Body string } { {"test.txt", "String contents of file"}, {"test2.txt", "\x61\x62\x63\n"}, }
// Create and write files to the archive, which in turn // are getting written to the underlying writer to the // .zip file we created at the beginning for _, file := range filesToArchive { fileWriter, err := zipWriter.Create(file.Name) if err != nil { log.Fatal(err) } _, err = fileWriter.Write([]byte(file.Body)) if err != nil { log.Fatal(err) } }
// Clean up err = zipWriter.Close() if err != nil { log.Fatal(err) } }
funcmain() { // Create a reader out of the zip archive zipReader, err := zip.OpenReader("test.zip") if err != nil { log.Fatal(err) } defer zipReader.Close()
// Iterate through each file/dir found in for _, file := range zipReader.Reader.File { // Open the file inside the zip archive // like a normal file zippedFile, err := file.Open() if err != nil { log.Fatal(err) } defer zippedFile.Close()
// Specify what the extracted file name should be. // You can specify a full path or a prefix // to move it to a different directory. // In this case, we will extract the file from // the zip to a file of the same name. targetDir := "./" extractedFilePath := filepath.Join( targetDir, file.Name, )
// Extract the item (or create directory) if file.FileInfo().IsDir() { // Create directories to recreate directory // structure inside the zip archive. Also // preserves permissions log.Println("Creating directory:", extractedFilePath) os.MkdirAll(extractedFilePath, file.Mode()) } else { // Extract regular file since not a directory log.Println("Extracting file:", file.Name)
// Open an output file for writing outputFile, err := os.OpenFile( extractedFilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, file.Mode(), ) if err != nil { log.Fatal(err) } defer outputFile.Close()
// "Extract" the file by copying zipped file // contents to the output file _, err = io.Copy(outputFile, zippedFile) if err != nil { log.Fatal(err) } } } }
// This example uses gzip but standard library also // supports zlib, bz2, flate, and lzw package main
import ( "os" "compress/gzip" "log" )
funcmain() { // Create .gz file to write to outputFile, err := os.Create("test.txt.gz") if err != nil { log.Fatal(err) }
// Create a gzip writer on top of file writer gzipWriter := gzip.NewWriter(outputFile) defer gzipWriter.Close()
// When we write to the gzip writer // it will in turn compress the contents // and then write it to the underlying // file writer as well // We don't have to worry about how all // the compression works since we just // use it as a simple writer interface // that we send bytes to _, err = gzipWriter.Write([]byte("Gophers rule!\n")) if err != nil { log.Fatal(err) }
// This example uses gzip but standard library also // supports zlib, bz2, flate, and lzw package main
import ( "compress/gzip" "log" "io" "os" )
funcmain() { // Open gzip file that we want to uncompress // The file is a reader, but we could use any // data source. It is common for web servers // to return gzipped contents to save bandwidth // and in that case the data is not in a file // on the file system but is in a memory buffer gzipFile, err := os.Open("test.txt.gz") if err != nil { log.Fatal(err) }
// Create a gzip reader on top of the file reader // Again, it could be any type reader though gzipReader, err := gzip.NewReader(gzipFile) if err != nil { log.Fatal(err) } defer gzipReader.Close()
// Uncompress to a writer. We'll use a file writer outfileWriter, err := os.Create("unzipped.txt") if err != nil { log.Fatal(err) } defer outfileWriter.Close()
// Copy contents of gzipped file to output file _, err = io.Copy(outfileWriter, gzipReader) if err != nil { log.Fatal(err) } }
funcmain() { // Create a temp dir in the system default temp folder tempDirPath, err := ioutil.TempDir("", "myTempDir") if err != nil { log.Fatal(err) } fmt.Println("Temp dir created:", tempDirPath)
// Create a file in new temp directory tempFile, err := ioutil.TempFile(tempDirPath, "myTempFile.txt") if err != nil { log.Fatal(err) } fmt.Println("Temp file created:", tempFile.Name())
// ... do something with temp file/dir ...
// Close file err = tempFile.Close() if err != nil { log.Fatal(err) }
// Delete the resources we created err = os.Remove(tempFile.Name()) if err != nil { log.Fatal(err) } err = os.Remove(tempDirPath) if err != nil { log.Fatal(err) } }
// Write bytes from HTTP response to file. // response.Body satisfies the reader interface. // newFile satisfies the writer interface. // That allows us to use io.Copy which accepts // any type that implements reader and writer interface numBytesWritten, err := io.Copy(newFile, response.Body) if err != nil { log.Fatal(err) } log.Printf("Downloaded %d byte file.\n", numBytesWritten) }
funcmain() { // Open file for reading file, err := os.Open("test.txt") if err != nil { log.Fatal(err) } defer file.Close()
// Create new hasher, which is a writer interface hasher := md5.New() _, err = io.Copy(hasher, file) if err != nil { log.Fatal(err) }
// Hash and print. Pass nil since // the data is not coming in as a slice argument // but is coming through the writer interface sum := hasher.Sum(nil) fmt.Printf("Md5 checksum: %x\n", sum) }