func headLines(file *hdfs.FileReader, numLines int64) { reader := bufio.NewReader(file) var newlines, offset int64 for newlines < numLines { b, err := reader.ReadByte() if err == io.EOF { offset = -1 break } else if err != nil { fatal(err) } if b == '\n' { newlines++ } offset++ } _, err := file.Seek(0, 0) if err != nil { fatal(err) } if offset < 0 { io.Copy(os.Stdout, file) } else { io.CopyN(os.Stdout, file, offset) } }
func tailLines(file *hdfs.FileReader, numLines int64) { fileSize := file.Stat().Size() searchPoint := file.Stat().Size() - tailSearchSize if searchPoint < 0 { searchPoint = 0 } readSize := tailSearchSize if readSize > fileSize { readSize = fileSize } var printOffset int64 for searchPoint >= 0 { section := bufio.NewReader(io.NewSectionReader(file, searchPoint, readSize)) off := searchPoint newlines := make([]int64, 0, tailSearchSize/64) b, err := section.ReadByte() for err == nil { if b == '\n' && (off+1 != fileSize) { newlines = append(newlines, off) } off++ b, err = section.ReadByte() } if err != nil && err != io.EOF { fatal(err) } foundNewlines := int64(len(newlines)) if foundNewlines >= numLines { printOffset = newlines[foundNewlines-numLines] + 1 break } numLines -= foundNewlines searchPoint -= tailSearchSize } _, err := file.Seek(printOffset, 0) if err != nil { fatal(err) } io.Copy(os.Stdout, file) }