|
1 | 1 | package main |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "bufio" |
4 | 5 | "io" |
5 | 6 | "log" |
6 | 7 | "os" |
7 | 8 | ) |
8 | 9 |
|
| 10 | +// ctrlDReader wraps a reader and detects Ctrl+D (ASCII 4) as EOT/EOF |
| 11 | +type ctrlDReader struct { |
| 12 | + r io.Reader |
| 13 | +} |
| 14 | + |
| 15 | +func (c *ctrlDReader) Read(p []byte) (n int, err error) { |
| 16 | + n, err = c.r.Read(p) |
| 17 | + |
| 18 | + // Check for Ctrl+D (ASCII 4) |
| 19 | + for i := 0; i < n; i++ { |
| 20 | + if p[i] == 4 { |
| 21 | + // If we found Ctrl+D, return data up to that point and signal EOF |
| 22 | + return i, io.EOF |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + return n, err |
| 27 | +} |
| 28 | + |
9 | 29 | func main() { |
| 30 | + stdout := os.Stdout |
| 31 | + |
10 | 32 | if len(os.Args) == 1 { |
11 | | - _, err := io.Copy(os.Stdout, os.Stdin) |
12 | | - if err != nil { |
| 33 | + // Create a reader that detects Ctrl+D as EOF |
| 34 | + stdin := &ctrlDReader{r: os.Stdin} |
| 35 | + reader := bufio.NewReader(stdin) |
| 36 | + |
| 37 | + // Copy stdin contents to stdout |
| 38 | + _, err := io.Copy(stdout, reader) |
| 39 | + if err != nil && err != io.EOF { |
13 | 40 | log.Fatal(err) |
14 | 41 | } |
15 | 42 | } else { |
16 | 43 | for _, fname := range os.Args[1:] { |
| 44 | + // Open file in binary mode |
17 | 45 | fh, err := os.Open(fname) |
18 | 46 | if err != nil { |
19 | 47 | log.Fatal(err) |
20 | 48 | } |
21 | 49 |
|
22 | | - _, err = io.Copy(os.Stdout, fh) |
23 | | - if err != nil { |
| 50 | + // Use buffered I/O for better performance |
| 51 | + reader := bufio.NewReader(fh) |
| 52 | + |
| 53 | + // Copy file contents preserving all bytes |
| 54 | + _, err = io.Copy(stdout, reader) |
| 55 | + if err != nil && err != io.EOF { |
24 | 56 | log.Fatal(err) |
25 | 57 | } |
| 58 | + |
| 59 | + fh.Close() |
26 | 60 | } |
27 | 61 | } |
28 | 62 | } |
0 commit comments