2015-06-19 111 views
1

我試圖彈出文件的第一行,從而逐一減少文件行。 我去除第一線實現如下從Golang的文本文件中刪除第一行

type FS struct { 
    ... 
    File  *os.File 
} 

//File creation ok... 


func (fs *Fs) pop() []byte { 
    var buf []string 
    scanner := bufio.NewScanner(fs.File) 
    //Reading lines 
    for scanner.Scan() { 
     line := scanner.Text() 
     buf = append(buf, line) 
    } 
    //Writing from second line on the same file 
    for s := 1; s < len(buf); s++ { 
     fs.File.WriteString(fmt.Println(buf[s])) 
    } 
    //Commit changes 
    fs.File.Sync() 
    fs.File.Close() 

    return []byte(buf[0]) 
} 

我得到預期的字符串,但永遠不會改變的文件返回[]字節。 我在這裏錯過了什麼?

+3

首先,不要忽略錯誤。其次,你不是在你認爲自己的位置寫信給該文件。 – JimB

+0

嗨吉姆,謝謝你,我可能錯過了'fs.File.Seek(0,0)',但我仍然不會出現任何錯誤... –

+3

你忽略了由'File.WriteString返回的錯誤'。 (另外,'ScanLines'函數去掉換行符,但是如果文件沒有改變,你還沒有寫信給它) – JimB

回答

2

例如,

package main 

import (
    "bytes" 
    "fmt" 
    "io" 
    "os" 
) 

func popLine(f *os.File) ([]byte, error) { 
    fi, err := f.Stat() 
    if err != nil { 
     return nil, err 
    } 
    buf := bytes.NewBuffer(make([]byte, 0, fi.Size())) 

    _, err = f.Seek(0, os.SEEK_SET) 
    if err != nil { 
     return nil, err 
    } 
    _, err = io.Copy(buf, f) 
    if err != nil { 
     return nil, err 
    } 
    line, err := buf.ReadString('\n') 
    if err != nil && err != io.EOF { 
     return nil, err 
    } 

    _, err = f.Seek(0, os.SEEK_SET) 
    if err != nil { 
     return nil, err 
    } 
    nw, err := io.Copy(f, buf) 
    if err != nil { 
     return nil, err 
    } 
    err = f.Truncate(nw) 
    if err != nil { 
     return nil, err 
    } 
    err = f.Sync() 
    if err != nil { 
     return nil, err 
    } 

    _, err = f.Seek(0, os.SEEK_SET) 
    if err != nil { 
     return nil, err 
    } 
    return []byte(line), nil 
} 

func main() { 
    fname := `popline.txt` 
    f, err := os.OpenFile(fname, os.O_RDWR|os.O_CREATE, 0666) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    defer f.Close() 
    line, err := popLine(f) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Println("pop:", string(line)) 
} 
 
$ cat popline.txt 
Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
Ut enim ad minim veniam, 
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
Excepteur sint occaecat cupidatat non proident, 
sunt in culpa qui officia deserunt mollit anim id est laborum. 

$ go run popline.go 
pop: Lorem ipsum dolor sit amet, consectetur adipiscing elit, 

$ cat popline.txt 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
Ut enim ad minim veniam, 
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
Excepteur sint occaecat cupidatat non proident, 
sunt in culpa qui officia deserunt mollit anim id est laborum. 

$ 
+0

嗨,彼得,上面的代碼正在做我期望的,謝謝!閱讀和測試這個我相信我誤解了os.Seek和os.Truncate的文檔。我曾嘗試使用truncate的另一個版本,但無法使其工作。再次感謝您指點我正確的方向:) –