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

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

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.

  1. func sort() {
  2. ff, _ := os.OpenFile(file, os.O_RDWR, 0666)
  3. f := bufio.NewReader(ff)
  4. for {
  5. read_line, _ := f.ReadString('\n')
  6. fmt.Print(read_line)
  7. if read_line == "" {
  8. break
  9. }
  10. }
  11. ff.Close()
  12. }

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:

  1. 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:

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

Thank you in advance for any suggestions!

答案1

得分: 4

例如,

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "sort"
  7. )
  8. func readLines(file string) (lines []string, err os.Error) {
  9. f, err := os.Open(file)
  10. if err != nil {
  11. return nil, err
  12. }
  13. defer f.Close()
  14. r := bufio.NewReader(f)
  15. for {
  16. const delim = '\n'
  17. line, err := r.ReadString(delim)
  18. if err == nil || len(line) > 0 {
  19. if err != nil {
  20. line += string(delim)
  21. }
  22. lines = append(lines, line)
  23. }
  24. if err != nil {
  25. if err == os.EOF {
  26. break
  27. }
  28. return nil, err
  29. }
  30. }
  31. return lines, nil
  32. }
  33. func writeLines(file string, lines []string) (err os.Error) {
  34. f, err := os.Create(file)
  35. if err != nil {
  36. return err
  37. }
  38. defer f.Close()
  39. w := bufio.NewWriter(f)
  40. defer w.Flush()
  41. for _, line := range lines {
  42. _, err := w.WriteString(line)
  43. if err != nil {
  44. return err
  45. }
  46. }
  47. return nil
  48. }
  49. func main() {
  50. file := `lines.txt`
  51. lines, err := readLines(file)
  52. if err != nil {
  53. fmt.Println(err)
  54. os.Exit(1)
  55. }
  56. sort.Strings(lines)
  57. err = writeLines(file, lines)
  58. if err != nil {
  59. fmt.Println(err)
  60. os.Exit(1)
  61. }
  62. }
英文:

For example,

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. "sort"
  7. )
  8. func readLines(file string) (lines []string, err os.Error) {
  9. f, err := os.Open(file)
  10. if err != nil {
  11. return nil, err
  12. }
  13. defer f.Close()
  14. r := bufio.NewReader(f)
  15. for {
  16. const delim = '\n'
  17. line, err := r.ReadString(delim)
  18. if err == nil || len(line) > 0 {
  19. if err != nil {
  20. line += string(delim)
  21. }
  22. lines = append(lines, line)
  23. }
  24. if err != nil {
  25. if err == os.EOF {
  26. break
  27. }
  28. return nil, err
  29. }
  30. }
  31. return lines, nil
  32. }
  33. func writeLines(file string, lines []string) (err os.Error) {
  34. f, err := os.Create(file)
  35. if err != nil {
  36. return err
  37. }
  38. defer f.Close()
  39. w := bufio.NewWriter(f)
  40. defer w.Flush()
  41. for _, line := range lines {
  42. _, err := w.WriteString(line)
  43. if err != nil {
  44. return err
  45. }
  46. }
  47. return nil
  48. }
  49. func main() {
  50. file := `lines.txt`
  51. lines, err := readLines(file)
  52. if err != nil {
  53. fmt.Println(err)
  54. os.Exit(1)
  55. }
  56. sort.Strings(lines)
  57. err = writeLines(file, lines)
  58. if err != nil {
  59. fmt.Println(err)
  60. os.Exit(1)
  61. }
  62. }

答案2

得分: 2

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

  1. import (
  2. "bytes"
  3. "io/ioutil"
  4. "sort"
  5. )
  6. // 允许[][]byte实现sort.Interface接口
  7. type lexicographically [][]byte
  8. // bytes.Compare按字典顺序(按字母顺序)比较字节切片
  9. func (l lexicographically) Less(i, j int) bool { return bytes.Compare(l[i], l[j]) < 0 }
  10. func (l lexicographically) Len() int { return len(l) }
  11. func (l lexicographically) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
  12. func SortFile(name string) error {
  13. content, err := ioutil.ReadFile(name)
  14. if err != nil {
  15. return err
  16. }
  17. lines := bytes.Split(content, []byte{'\n'})
  18. sort.Sort(lexicographically(lines))
  19. content = bytes.Join(lines, []byte{'\n'})
  20. return ioutil.WriteFile(name, content, 0644)
  21. }
英文:

This is a pretty simple way of doing it.

  1. import (
  2. &quot;bytes&quot;
  3. &quot;io/ioutil&quot;
  4. &quot;sort&quot;
  5. )
  6. // allow [][]byte to implement the sort.Interface interface
  7. type lexicographically [][]byte
  8. // bytes.Compare compares the byte slices lexicographically (alphabetically)
  9. func (l lexicographically) Less(i, j int) bool { return bytes.Compare(l[i], l[j]) &lt; 0 }
  10. func (l lexicographically) Len() int { return len(l) }
  11. func (l lexicographically) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
  12. func SortFile(name string) error {
  13. content, err := ioutil.ReadFile(name)
  14. if err != nil {
  15. return err
  16. }
  17. lines := bytes.Split(content, []byte{&#39;\n&#39;})
  18. sort.Sort(lexicographically(lines))
  19. content = bytes.Join(lines, []byte{&#39;\n&#39;})
  20. return ioutil.WriteFile(name, content, 0644)
  21. }

答案3

得分: 1

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

  1. package main
  2. import (
  3. "os"
  4. "bufio"
  5. "fmt"
  6. "sort"
  7. )
  8. // 将文件读入字符串切片
  9. func slurp(f string) (lines []string, e os.Error) {
  10. var fd *os.File
  11. var line string
  12. var bufRd *bufio.Reader
  13. var keepReading bool = true
  14. fd, e = os.Open(f)
  15. if e != nil {
  16. return nil, e
  17. }
  18. defer fd.Close()
  19. bufRd = bufio.NewReader(fd)
  20. for keepReading {
  21. line, e = bufRd.ReadString('\n')
  22. switch e {
  23. case nil:
  24. lines = append(lines, line)
  25. case os.EOF:
  26. lines = append(lines, line)
  27. keepReading = false
  28. default:
  29. return lines, e
  30. }
  31. }
  32. return lines, nil
  33. }
  34. // 测试
  35. func main() {
  36. if len(os.Args) > 1 {
  37. lines, e := slurp(os.Args[1])
  38. if e != nil {
  39. fmt.Fprintf(os.Stderr, "%s\n", e)
  40. os.Exit(1)
  41. }
  42. fmt.Println("\n----- 未排序 -----\n")
  43. for _, line := range lines {
  44. fmt.Printf("%s", line)
  45. }
  46. fmt.Println("\n----- 已排序 -----\n")
  47. sort.Strings(lines)
  48. for _, line := range lines {
  49. fmt.Printf("%s", line)
  50. }
  51. }
  52. }

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

英文:

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

  1. package main
  2. import (
  3. &quot;os&quot;
  4. &quot;bufio&quot;
  5. &quot;fmt&quot;
  6. &quot;sort&quot;
  7. )
  8. // slurp file into slice of lines/strings
  9. func slurp(f string) (lines []string, e os.Error) {
  10. var fd *os.File
  11. var line string
  12. var bufRd *bufio.Reader
  13. var keepReading bool = true
  14. fd, e = os.Open(f)
  15. if e != nil {
  16. return nil, e
  17. }
  18. defer fd.Close()
  19. bufRd = bufio.NewReader(fd)
  20. for keepReading {
  21. line, e = bufRd.ReadString(&#39;\n&#39;)
  22. switch e {
  23. case nil:
  24. lines = append(lines, line)
  25. case os.EOF:
  26. lines = append(lines, line)
  27. keepReading = false
  28. default:
  29. return lines, e
  30. }
  31. }
  32. return lines, nil
  33. }
  34. // test stuff out..
  35. func main() {
  36. if len(os.Args) &gt; 1 {
  37. lines, e := slurp(os.Args[1])
  38. if e != nil {
  39. fmt.Fprintf(os.Stderr,&quot;%s\n&quot;, e)
  40. os.Exit(1)
  41. }
  42. fmt.Println(&quot;\n----- unsorted -----\n&quot;)
  43. for _, line := range lines {
  44. fmt.Printf(&quot;%s&quot;, line)
  45. }
  46. fmt.Println(&quot;\n----- sorted -----\n&quot;)
  47. sort.Strings(lines)
  48. for _, line := range lines {
  49. fmt.Printf(&quot;%s&quot;, line)
  50. }
  51. }
  52. }

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

答案4

得分: -3

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

  1. package main
  2. import (
  3. "os"
  4. "os/exec"
  5. )
  6. func main() {
  7. file := "file.txt"
  8. command := []string{"sort", file, "-o", file}
  9. cmd := exec.Command(command[0], command[1:]...)
  10. cmd.Stdout = os.Stdout
  11. cmd.Stderr = os.Stderr
  12. if err := cmd.Run(); err != nil {
  13. panic(err)
  14. }
  15. }

你有什么想法?

英文:

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:

  1. package main
  2. import (
  3. &quot;os&quot;
  4. &quot;os/exec&quot;
  5. )
  6. func main() {
  7. file := &quot;file.txt&quot;
  8. command := []string{&quot;sort&quot;, file, &quot;-o&quot;, file}
  9. cmd := exec.Command(command[0], command[1:]...)
  10. cmd.Stdout = os.Stdout
  11. cmd.Stderr = os.Stderr
  12. if err := cmd.Run(); err != nil {
  13. panic(err)
  14. }
  15. }

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:

确定