2014-11-19 2 views
1

Дело:Как читать файл строки за строкой и возвращать сколько байтов было прочитано?

  1. Я хочу, чтобы читать журнал, как «хвост -f» * NIX
  2. , когда я убиваю программу я могу знать, сколько байтов я уже прочитал, и я могу использовать искать
  3. при запуске снова программы будет продолжать читать строки журнала по линии зависят от искать данные на шаге 2

Я хочу, чтобы получить байты, когда я использую bufio.NewScanner как читатель линии для чтения строки

например:

import ... 
func main() { 
    f, err := os.Open("111.txt") 
    if err != nil {   
     log.Fatal(err) 
    } 
    f.Seek(0,os.SEEK_SET) 
    scan := bufio.NewScanner(f) 
    for scan.Scan() { 
     log.Printf(scan.Text()) 
     //what I want is how many bytes at this time when I read a line 
    }//This is a program for read line 

}

ТНХ! ================================= ============================================================ ====================================== @twotwotwo это близко к тому, что я хочу, но я хочу изменить io.Reader на io.ReaderAt, и это то, что я хочу, я пишу демо использовать io.Reader: `

import (
    "os" 
    "log" 
    "io" 
) 
type Reader struct { 
    reader io.Reader 
    count int 
} 
func (r *Reader) Read(b []byte) (int, error) { 
    n, err := r.reader.Read(b) 
    r.count += n 
    return n, err 
} 
func (r *Reader) Count() int { 
    return r.count 
} 
func NewReader(r io.Reader) *Reader { 
    return &Reader{reader: r} 
} 

func ReadLine(r *Reader) (ln int,line []byte,err error) { 
    line = make([]byte,0,4096) 
    for { 
     b := make([]byte,1) 
     n,er := r.Read(b) 
     if er == io.EOF { 
      err = er 
      break 
     } 
     if n > 0{ 
      c := b[0] 
      if c == '\n' { 
       break 
      } 
      line = append(line, c) 
     } 
     if er != nil{ 
      err = er 
     } 
    } 

    ln = r.Count() 
    return ln,line,err 
} 

func main() { 
    f, err := os.Open("111.txt") 
    if err != nil {   
     log.Fatal(err) 
    } 
    fi,_:=os.Stat("111.txt") 
    log.Printf("the file have %v bytes",fi.Size()) 
    co := NewReader(f) 
    for { 
     count,line,er := ReadLine(co) 
     if er == io.EOF { 
      break 
     } 
     log.Printf("now read the line :%v",string(line)) 
     log.Printf("in all we have read %v bytes",count) 


    } 

}` 

эта программа может сказать мне, сколько байт я уже прочитал, но cannt чтения начните из любого места, где я хочу, поэтому я думаю, что если мы используем io.ReaderAt, он может это сделать. еще раз спасибо!

ответ

0

Вы можете рассмотреть другой подход, основанный на os.File.

См ActiveState/tail, что следить за состоянием файла, и использует os.File#Seek() возобновить хвостовой файл внутри определенной точки.

См. tail.go.

+0

thx, я видел его прежде, чем я спросил там, но он не может решить мою проблему. – unicorns

-1

Рассмотрите состав.

Мы знаем, что bufio.NewScanner взаимодействует с его вводом через интерфейс io.Reader. Таким образом, мы можем обернуть io.Reader чем-то еще, что подсчитывает, сколько байтов было прочитано до сих пор.

package main 

import (
    "bufio" 
    "bytes" 
    "io" 
    "log" 
) 

type ReadCounter struct { 
    io.Reader 
    BytesRead int 
} 

func (r *ReadCounter) Read(p []byte) (int, error) { 
    n, err := r.Reader.Read(p) 
    r.BytesRead += n 
    return n, err 
} 

func main() { 
    b := &ReadCounter{Reader: bytes.NewBufferString("hello\nworld\testing\n")} 
    scan := bufio.NewScanner(b) 
    for scan.Scan() { 
     log.Println(scan.Text()) 
     log.Println("Read", b.BytesRead, "bytes so far") 
    } 
} 

Но мы отметим, что bufio.NewScanner в буфер, таким образом, мы можем видеть, что он считывает входные данные в куски. Поэтому для ваших целей это может быть не так полезно, как вы хотите.

Альтернативой является содержание scan.Text() и подсчет длин. Вы можете компенсировать удаление байтов новой строки во внутреннем счете.

+1

Facebook (в частности, команда Parse) написал ['counting.Reader' и' counting.Writer'] (https://gowalker.org/github.com/facebookgo/counting). Похоже, что искателю хотелось бы узнать начальную позицию + байты, написанные (которые не включали бы частичную строку, читаемую при выходе). – twotwotwo

+0

@dyoo спасибо за ответы ур, это похоже на проект facebook, рассказанный twotwotwo. и я обновил вопрос. – unicorns

Смежные вопросы