github.com/lingyao2333/mo-zero@v1.4.1/core/filex/file.go (about)

     1  package filex
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  )
     7  
     8  const bufSize = 1024
     9  
    10  // FirstLine returns the first line of the file.
    11  func FirstLine(filename string) (string, error) {
    12  	file, err := os.Open(filename)
    13  	if err != nil {
    14  		return "", err
    15  	}
    16  	defer file.Close()
    17  
    18  	return firstLine(file)
    19  }
    20  
    21  // LastLine returns the last line of the file.
    22  func LastLine(filename string) (string, error) {
    23  	file, err := os.Open(filename)
    24  	if err != nil {
    25  		return "", err
    26  	}
    27  	defer file.Close()
    28  
    29  	return lastLine(filename, file)
    30  }
    31  
    32  func firstLine(file *os.File) (string, error) {
    33  	var first []byte
    34  	var offset int64
    35  	for {
    36  		buf := make([]byte, bufSize)
    37  		n, err := file.ReadAt(buf, offset)
    38  		if err != nil && err != io.EOF {
    39  			return "", err
    40  		}
    41  
    42  		for i := 0; i < n; i++ {
    43  			if buf[i] == '\n' {
    44  				return string(append(first, buf[:i]...)), nil
    45  			}
    46  		}
    47  
    48  		first = append(first, buf[:n]...)
    49  		offset += bufSize
    50  	}
    51  }
    52  
    53  func lastLine(filename string, file *os.File) (string, error) {
    54  	info, err := os.Stat(filename)
    55  	if err != nil {
    56  		return "", err
    57  	}
    58  
    59  	var last []byte
    60  	offset := info.Size()
    61  	for {
    62  		offset -= bufSize
    63  		if offset < 0 {
    64  			offset = 0
    65  		}
    66  		buf := make([]byte, bufSize)
    67  		n, err := file.ReadAt(buf, offset)
    68  		if err != nil && err != io.EOF {
    69  			return "", err
    70  		}
    71  
    72  		if buf[n-1] == '\n' {
    73  			buf = buf[:n-1]
    74  			n--
    75  		} else {
    76  			buf = buf[:n]
    77  		}
    78  		for n--; n >= 0; n-- {
    79  			if buf[n] == '\n' {
    80  				return string(append(buf[n+1:], last...)), nil
    81  			}
    82  		}
    83  
    84  		last = append(buf, last...)
    85  	}
    86  }