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

huangapple go评论82阅读模式
英文:

Read in lines in a text file, sort, then overwrite file

问题

我正在尝试编写一个Go函数,它将读取文本文件中的行,对它们进行排序(按字母顺序),然后将它们覆盖回文件。目前,我能够基本上模拟cat命令,但似乎无法操作read_line中元素的内容。

当我使用ReadString时,如何将每行存储到一个切片中(或者是否有更好的方法来存储它们以便我可以操作它们)?然后,我将以类似于以下方式使用sort包:

sorted := sort.Strings(lines)

然后,为了写入文件,我正在使用类似于以下的方法,尽管我还没有包含它,因为我还没有让“sort”工作:

io.WriteString(ff, (lines + "\n"))

提前感谢您的建议!

英文:

I am trying to write a go function that will read in lines in a text file, sort them (alphabetize), and overwrite them back to the file. Right now, I am able to essentially emulate cat, but I can't seem to be able to manipulate the contents of the elements in read_line.

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()
}

when i use ReadString, how can i store each line into a slice (or is there a better way to store them so i can manipulate them)? Then I would use the sort package in a manner similar to this:

sorted := sort.Strings(lines) 

then, to write to the file, i am using something similar to the following, although i have not included it because i have not yet gotten "sort" to work:

io.WriteString(ff, (lines + "\n"))

Thank you in advance for any suggestions!

答案1

得分: 4

例如,

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)
	}
}
英文:

For example,

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)
	}
}

答案2

得分: 2

这是一个相当简单的方法。

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

// 允许[][]byte实现sort.Interface接口
type lexicographically [][]byte

// bytes.Compare按字典顺序(按字母顺序)比较字节切片
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)
}
英文:

This is a pretty simple way of doing it.

import (
	&quot;bytes&quot;
	&quot;io/ioutil&quot;
	&quot;sort&quot;
)

// 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]) &lt; 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{&#39;\n&#39;})
	sort.Sort(lexicographically(lines))

	content = bytes.Join(lines, []byte{&#39;\n&#39;})
	return ioutil.WriteFile(name, content, 0644)
}

答案3

得分: 1

由于您即将对行进行排序,因此您基本上需要读取整个文件。您可以使用io/ioutil.ReadAll将文件读入内存,也可以编写一个小的读取函数。一旦您获得了文件的行,可以使用sort.Strings进行排序。我将添加一个可能过于冗长的版本,希望能够说明如何完成排序。我还建议阅读这篇关于Go的排序包如何工作的优秀解释:Go的排序包

package main

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

// 将文件读入字符串切片
func slurp(f string) (lines []string, e os.Error) {

    var fd *os.File
    var line string
    var bufRd *bufio.Reader
    var keepReading bool = true

    fd, e = os.Open(f)

    if e != nil {
        return nil, e
    }

    defer fd.Close()

    bufRd = bufio.NewReader(fd)

    for keepReading {
        line, e = bufRd.ReadString('\n')
        switch e {
        case nil:
            lines = append(lines, line)
        case os.EOF:
            lines = append(lines, line)
            keepReading = false
        default:
            return lines, e
        }
    }

    return lines, nil
}

// 测试
func main() {

    if len(os.Args) > 1 {

        lines, e := slurp(os.Args[1])

        if e != nil {
            fmt.Fprintf(os.Stderr, "%s\n", e)
            os.Exit(1)
        }

        fmt.Println("\n----- 未排序 -----\n")

        for _, line := range lines {
            fmt.Printf("%s", line)
        }

        fmt.Println("\n----- 已排序 -----\n")

        sort.Strings(lines)

        for _, line := range lines {
            fmt.Printf("%s", line)
        }
    }
}

请注意,排序是原地进行的,因此不会返回任何内容。

英文:

since you are about to sort the lines, you pretty much need to read the entire file. you can either slurp the file with io/ioutil.ReadAll or you can just write a small slurp function. once you have the lines of the file, sorting them can be done with a call to sort.Strings. i'll add a perhaps overly verbose version which hopefully illustrates how it can be done. i also recomment reading this excellent explanation on how go's sort package works: Go's sort package

package main
import (
&quot;os&quot;
&quot;bufio&quot;
&quot;fmt&quot;
&quot;sort&quot;
)
// slurp file into slice of lines/strings
func slurp(f string) (lines []string, e os.Error) {
var fd *os.File
var line string
var bufRd *bufio.Reader
var keepReading bool = true
fd, e = os.Open(f)
if e != nil {
return nil, e
}
defer fd.Close()
bufRd = bufio.NewReader(fd)
for keepReading {
line, e = bufRd.ReadString(&#39;\n&#39;)
switch e {
case nil:
lines = append(lines, line)
case os.EOF:
lines = append(lines, line)
keepReading = false
default:
return lines, e
}
}
return lines, nil
}
// test stuff out..
func main() {
if len(os.Args) &gt; 1 {
lines, e := slurp(os.Args[1])
if e != nil {
fmt.Fprintf(os.Stderr,&quot;%s\n&quot;, e)
os.Exit(1)
}
fmt.Println(&quot;\n----- unsorted -----\n&quot;)
for _, line := range lines {
fmt.Printf(&quot;%s&quot;, line)
}
fmt.Println(&quot;\n----- sorted -----\n&quot;)
sort.Strings(lines)
for _, line := range lines {
fmt.Printf(&quot;%s&quot;, line)
}
}
}

note that the sort is in-place, so it does not return anything

答案4

得分: -3

只是想知道使用Unix的sort在这个目的上有多方便。我知道在许多部署场景中,这段代码无法工作,但我认为值得提及作为一个选项:

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)
	}
}

你有什么想法?

英文:

Just wondering how convenient is using Unix's sort for this purpose. I know it's not possible to have this code working in many deployment scenarios, but I see it worth it to mention as an option:

package main
import (
&quot;os&quot;
&quot;os/exec&quot;
)
func main() {
file := &quot;file.txt&quot;
command := []string{&quot;sort&quot;, file, &quot;-o&quot;, file}
cmd := exec.Command(command[0], command[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
panic(err)
}
}

Thoughts?

huangapple
  • 本文由 发表于 2011年9月15日 07:53:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/7424340.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定