2013-07-25 7 views
8

के साथ एक बड़ी फ़ाइल से अंतिम पंक्तियों को कैसे पढ़ा जाए, मैं बड़ी लॉग फ़ाइल से आखिरी दो पंक्तियों को पूरी तरह मेमोरी में लोड किए बिना कैसे पढ़ सकता हूं?प्रत्येक 10 सेकंड

मैं इसे हर 10 सेकेंड (एक जीत मशीन पर) को पढ़ने की जरूरत है ... और मैं पिछले लाइनों को पढ़ने का प्रयास अटक कर रहा हूँ ..

package main 

import (
    "fmt" 
    "time" 
    "os" 
) 

const MYFILE = "logfile.log" 

func main() { 
    c := time.Tick(10 * time.Second) 
    for now := range c { 
     readFile(MYFILE) 
    } 
} 

func readFile(fname string){ 
    file, err:=os.Open(fname) 
    if err!=nil{ 
     panic(err) 
    } 
    buf:=make([]byte, 32) 
    c, err:=file.ReadAt(32, ????) 
    fmt.Printf("%s\n", c) 


} 

लॉग फ़ाइल है कुछ की तरह:

07/25/2013 11:55:42.400, 0.559 
07/25/2013 11:55:52.200, 0.477 
07/25/2013 11:56:02.000, 0.463 
07/25/2013 11:56:11.800, 0.454 
07/25/2013 11:56:21.600, 0.424 
07/25/2013 11:56:31.400, 0.382 
07/25/2013 11:56:41.200, 0.353 
07/25/2013 11:56:51.000, 0.384 
07/25/2013 11:57:00.800, 0.393 
07/25/2013 11:57:10.600, 0.456 

धन्यवाद!

उत्तर

9

आप file.Seek() या file.ReadAt() का उपयोग लगभग अंत तक कर सकते हैं और फिर आगे पढ़ सकते हैं। आप अनुमान लगा सकते हैं कि कहां से शुरू करना है जब तक कि आप 2 लाइन = एक्स बाइट्स को नहीं जानते।

आप os.Stat(name)

यहाँ का उपयोग करके फ़ाइल लंबाई प्राप्त कर सकते हैं ReadAt, स्टेट, और अपने नमूना लॉग फ़ाइल के आधार पर एक उदाहरण है:

package main 

import (
    "fmt" 
    "os" 
    "time" 
) 

const MYFILE = "logfile.log" 

func main() { 
    c := time.Tick(10 * time.Second) 
    for _ = range c { 
     readFile(MYFILE) 
    } 
} 

func readFile(fname string) { 
    file, err := os.Open(fname) 
    if err != nil { 
     panic(err) 
    } 
    defer file.Close() 

    buf := make([]byte, 62) 
    stat, err := os.Stat(fname) 
    start := stat.Size() - 62 
    _, err = file.ReadAt(buf, start) 
    if err == nil { 
     fmt.Printf("%s\n", buf) 
    } 

} 
+0

धन्यवाद @Joshua यह मेरे – Goku

+0

करने के लिए बेहतर दृष्टिकोण था मैं करूंगा file.Seek (62, 2) से इसके बजाय अंत और फिर बस फ़ाइल। आरई वर्तमान स्थिति से विज्ञापन। फ़ाइल.देखो, मुझे संदेह है, तो बहुत सस्ता है ओएस.स्टैट। – alex

+0

@ जोशुआ - एक ऐसी रेखा को पढ़ने के बारे में जिसे हम बाइट आकार से अवगत नहीं हैं? – Mir

3

मुझे लगता है कि File.Seek(0, 2) और File.Read() का एक संयोजन होना चाहिए काम।

Seek कॉल आपको फ़ाइल के अंत तक ले जाता है। पिछली कुछ पंक्तियां प्राप्त करने के लिए ईओएफ से थोड़ा पहले स्थिति में आप Seek कर सकते हैं। फिर आप Read ईओएफ तक और बस 10 सेकंड के लिए अपने goroutine में सो जाओ; अगले Read आपको अधिक डेटा प्राप्त करने का मौका मिला है।

GNU tail's source से आप विचार (और प्रारंभिक रूप से कुछ अंतिम पंक्तियों को दिखाने के लिए स्कैन-बैक लॉजिक) को छीन सकते हैं।

+0

अच्छा! योजना 9 स्रोत थोड़ा कम हैं: http://swtch.com/usr/local/plan9/src/cmd/tail.c – nes1983

1

ठीक है, यह केवल एक कच्चे विचार है और शायद नहीं सबसे अच्छा तरीका है, आप की जाँच करनी चाहिए और, इसे सुधारने लेकिन काम करने के लिए लगता है ...

मुझे आशा है कि अनुभवी जाओ उपयोगकर्ताओं भी योगदान कर सकता है ..

Stat के साथ आप फ़ाइल का आकार प्राप्त कर सकते हैं और इसे से उपयोग के लिए ऑफसेट पाने के साथ ReadAt

func readLastLine(fname string) { 
    file, err := os.Open(fname) 
    if err != nil { 
     panic(err) 
    } 
    defer file.Close() 

    fi, err := file.Stat() 
    if err != nil { 
     fmt.Println(err) 
    } 

    buf := make([]byte, 32) 
    n, err := file.ReadAt(buf, fi.Size()-int64(len(buf))) 
    if err != nil { 
     fmt.Println(err) 
    } 
    buf = buf[:n] 
    fmt.Printf("%s", buf) 

} 
संबंधित मुद्दे