| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | // Copyright © 2018 Inanc Gumus | 
					
						
							|  |  |  | // Learn Go Programming Course | 
					
						
							|  |  |  | // License: https://creativecommons.org/licenses/by-nc-sa/4.0/ | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // For more tutorials  : https://learngoprogramming.com | 
					
						
							|  |  |  | // In-person training  : https://www.linkedin.com/in/inancgumus/ | 
					
						
							|  |  |  | // Follow me on twitter: https://twitter.com/inancgumus | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	// Stdin, Stdout, and Stderr are *os.File. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// #1: reads from the standard input | 
					
						
							|  |  |  | 	// ------------------------------------------------ | 
					
						
							|  |  |  | 	// if err := read(os.Stdin); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | 	// 	fmt.Fprintln(os.Stderr, err) | 
					
						
							|  |  |  | 	// 	return | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	// } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// #2: writes to the standard output | 
					
						
							|  |  |  | 	// ------------------------------------------------ | 
					
						
							|  |  |  | 	// buf := []byte("hi!\n") | 
					
						
							|  |  |  | 	// if err := write(os.Stdout, buf); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | 	// 	fmt.Fprintln(os.Stderr, err) | 
					
						
							|  |  |  | 	// 	return | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	// } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// #2b: reads the entire file content into memory. | 
					
						
							|  |  |  | 	// ------------------------------------------------ | 
					
						
							|  |  |  | 	// buf, err := ioutil.ReadFile("alice.txt") | 
					
						
							|  |  |  | 	// if err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | 	// 	fmt.Fprintln(os.Stderr, err) | 
					
						
							|  |  |  | 	// 	return | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	// } | 
					
						
							|  |  |  | 	// if err := write(os.Stdout, buf); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | 	// 	fmt.Fprintln(os.Stderr, err) | 
					
						
							|  |  |  | 	// 	return | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	// } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// #3: reads and writes with 32KB of memory | 
					
						
							|  |  |  | 	//     no matter how large the source data is. | 
					
						
							|  |  |  | 	// ------------------------------------------------ | 
					
						
							|  |  |  | 	if err := ioCopy(os.Stdout, os.Stdin); err != nil { | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | 		fmt.Fprintln(os.Stderr, err) | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-04 11:00:53 +03:00
										 |  |  | // ioCopy streams from a file to another file. | 
					
						
							|  |  |  | // we use it to stream from the standard input to ouput. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | func ioCopy(dst, src *os.File) error { | 
					
						
							| 
									
										
										
										
											2019-11-02 11:21:35 +03:00
										 |  |  | 	// Use a fixed-length buffer to efficiently read from src stream in chunks. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	buf := make([]byte, 32768) | 
					
						
							| 
									
										
										
										
											2019-11-02 11:21:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// read over and over again to read all the data. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2019-11-02 11:21:35 +03:00
										 |  |  | 		// read can read only up to the buffer length. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 		nr, er := src.Read(buf) | 
					
						
							| 
									
										
										
										
											2019-11-02 11:21:35 +03:00
										 |  |  | 		// only write data if there is something to write. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 		if nr > 0 { | 
					
						
							|  |  |  | 			_, ew := dst.Write(buf[:nr]) | 
					
						
							|  |  |  | 			if ew != nil { | 
					
						
							|  |  |  | 				return ew | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-02 11:21:35 +03:00
										 |  |  | 		// io.EOF = there is nothing left to read—close the loop. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 		if er == io.EOF { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-11-02 11:21:35 +03:00
										 |  |  | 		// Only return an error if the reading really fails. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | 		if er != nil { | 
					
						
							|  |  |  | 			return er | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | // write example. | 
					
						
							| 
									
										
										
										
											2019-11-01 13:12:03 +03:00
										 |  |  | func write(dst *os.File, buf []byte) error { | 
					
						
							|  |  |  | 	nw, ew := dst.Write(buf) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fmt.Printf("wrote    : %d bytes\n", nw) | 
					
						
							|  |  |  | 	fmt.Printf("write err: %v\n", ew) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ew | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-11-08 10:52:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // read example. | 
					
						
							|  |  |  | func read(src *os.File) error { | 
					
						
							|  |  |  | 	buf := make([]byte, 1024*32) // in the middle. | 
					
						
							|  |  |  | 	// buf := make([]byte, 148157) // defies the purpose of streaming. | 
					
						
							|  |  |  | 	// buf := make([]byte, 8) // too many chunking. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		nr, er := src.Read(buf) | 
					
						
							|  |  |  | 		// fmt.Printf("buf      : %q\n", buf[0:nr]) | 
					
						
							|  |  |  | 		fmt.Printf("read     : %d bytes\n", nr) | 
					
						
							|  |  |  | 		fmt.Printf("read err : %v\n", er) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if er == io.EOF { | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if er != nil { | 
					
						
							|  |  |  | 			return er | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |