Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 读取文本文件中的行,排序,然后覆盖文件_File_Sorting_Go_Lines - Fatal编程技术网

File 读取文本文件中的行,排序,然后覆盖文件

File 读取文本文件中的行,排序,然后覆盖文件,file,sorting,go,lines,File,Sorting,Go,Lines,我正在尝试编写一个go函数,该函数将读取文本文件中的行,对它们进行排序(按字母顺序排列),然后将它们覆盖回文件。现在,我基本上能够模拟cat,但似乎无法在read\u行中操纵元素的内容 func sort() { ff, _ := os.OpenFile(file, os.O_RDWR, 0666) f := bufio.NewReader(ff) for { read_line, _ := f.ReadString('\n') fmt.

我正在尝试编写一个go函数,该函数将读取文本文件中的行,对它们进行排序(按字母顺序排列),然后将它们覆盖回文件。现在,我基本上能够模拟
cat
,但似乎无法在read\u行中操纵元素的内容

func sort() {

    ff, _ := os.OpenFile(file, os.O_RDWR, 0666)
    f := bufio.NewReader(ff)
    for {
        read_line, _ := f.ReadString('\n')
        fmt.Print(read_line)
        if read_line == "" {
            break
        }
    }
    ff.Close()
}
当我使用ReadString时,如何将每一行存储到一个切片中(或者是否有更好的方法来存储它们以便操作它们)?然后,我将以类似以下方式使用排序包:

sorted := sort.Strings(lines) 
然后,为了写入文件,我使用了类似于以下内容的东西,尽管我没有包括它,因为我还没有得到“排序”来工作:


提前感谢您的任何建议

因为要对行进行排序,所以几乎需要读取整个文件。您可以使用
io/ioutil.ReadAll
对文件进行slurp,也可以只编写一个小的slurp函数。获得文件行后,可以通过调用
sort.Strings
对其进行排序。我将添加一个可能过于冗长的版本,希望它能够说明如何做到这一点。我还建议您阅读关于go的sort软件包工作原理的精彩解释:

请注意,排序已就位,因此它不会返回任何内容,例如

package main

import (
    "bufio"
    "fmt"
    "os"
    "sort"
)

func readLines(file string) (lines []string, err os.Error) {
    f, err := os.Open(file)
    if err != nil {
        return nil, err
    }
    defer f.Close()
    r := bufio.NewReader(f)
    for {
        const delim = '\n'
        line, err := r.ReadString(delim)
        if err == nil || len(line) > 0 {
            if err != nil {
                line += string(delim)
            }
            lines = append(lines, line)
        }
        if err != nil {
            if err == os.EOF {
                break
            }
            return nil, err
        }
    }
    return lines, nil
}

func writeLines(file string, lines []string) (err os.Error) {
    f, err := os.Create(file)
    if err != nil {
        return err
    }
    defer f.Close()
    w := bufio.NewWriter(f)
    defer w.Flush()
    for _, line := range lines {
        _, err := w.WriteString(line)
        if err != nil {
            return err
        }
    }
    return nil
}

func main() {
    file := `lines.txt`
    lines, err := readLines(file)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    sort.Strings(lines)
    err = writeLines(file, lines)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

这是一个非常简单的方法

import (
    "bytes"
    "io/ioutil"
    "sort"
)

// allow [][]byte to implement the sort.Interface interface
type lexicographically [][]byte

// bytes.Compare compares the byte slices lexicographically (alphabetically)
func (l lexicographically) Less(i, j int) bool { return bytes.Compare(l[i], l[j]) < 0 }
func (l lexicographically) Len() int           { return len(l) }
func (l lexicographically) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }

func SortFile(name string) error {
    content, err := ioutil.ReadFile(name)
    if err != nil {
        return err
    }

    lines := bytes.Split(content, []byte{'\n'})
    sort.Sort(lexicographically(lines))

    content = bytes.Join(lines, []byte{'\n'})
    return ioutil.WriteFile(name, content, 0644)
}
导入(
“字节”
“io/ioutil”
“排序”
)
//允许[][]字节实现sort.Interface接口
按字典顺序键入[][]字节
//字节。比较按字典顺序(字母顺序)比较字节片
func(l字典)减去(i,j int)bool{返回字节。比较(l[i],l[j])<0}
func(l字典)Len()int{return Len(l)}
func(l字典)交换(i,j int){l[i],l[j]=l[j],l[i]}
func排序文件(名称字符串)错误{
内容,错误:=ioutil.ReadFile(名称)
如果错误!=零{
返回错误
}
行:=字节.Split(内容,[]字节{'\n'})
排序。排序(按字典顺序(行))
content=bytes.Join(行,[]字节{'\n'})
返回ioutil.WriteFile(名称、内容、0644)
}

只是想知道使用Unix的
排序功能来实现这一目的有多方便。我知道这段代码不可能在许多部署场景中工作,但我认为值得一提的是:

package main

import (
    "os"
    "os/exec"
)

func main() {
    file := "file.txt"

    command := []string{"sort", file, "-o", file}

    cmd := exec.Command(command[0], command[1:]...)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    if err := cmd.Run(); err != nil {
        panic(err)
    }
}

想法?

你没有检查
扫描仪。Err
。您不需要重新打开文件,只需调用
file.Truncate(0)
(忽略不使用第二个文件是危险的,因为如果程序停止,它将丢失数据)。并且您不检查
file.Close()
中的错误(在编写文件时可能很重要)。
import (
    "bytes"
    "io/ioutil"
    "sort"
)

// allow [][]byte to implement the sort.Interface interface
type lexicographically [][]byte

// bytes.Compare compares the byte slices lexicographically (alphabetically)
func (l lexicographically) Less(i, j int) bool { return bytes.Compare(l[i], l[j]) < 0 }
func (l lexicographically) Len() int           { return len(l) }
func (l lexicographically) Swap(i, j int)      { l[i], l[j] = l[j], l[i] }

func SortFile(name string) error {
    content, err := ioutil.ReadFile(name)
    if err != nil {
        return err
    }

    lines := bytes.Split(content, []byte{'\n'})
    sort.Sort(lexicographically(lines))

    content = bytes.Join(lines, []byte{'\n'})
    return ioutil.WriteFile(name, content, 0644)
}
package main

import (
    "os"
    "os/exec"
)

func main() {
    file := "file.txt"

    command := []string{"sort", file, "-o", file}

    cmd := exec.Command(command[0], command[1:]...)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    if err := cmd.Run(); err != nil {
        panic(err)
    }
}