Golang中如何正确存储文本?

Golang中如何正确存储文本? 大家好,

我是Go语言的新手,想编写一个非常简单的工具。至少我原本以为这会很简单。

这个程序的功能只是将一些文本(我通过命令行输入)保存到文本文件中。目前虽然能运行,但遇到了一些问题。以下是代码:

package main

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"

	aurora "github.com/logrusorgru/aurora"
)

func save(text *[]byte) error {
	filename := "data/test.txt"

	return ioutil.WriteFile(filename, *text, 0600)
}

func main() {
	var input string
	var b []byte
	scanner := bufio.NewScanner(os.Stdin)

	for {
		fmt.Print(aurora.Magenta(">> "))
		scanner.Scan()
		input = scanner.Text()

		if input == "fin" {
			err := save(&b)
			if err != nil {
				fmt.Println(err.Error())
			}
			return
		}

		b = append(b[:], scanner.Bytes()...)
		b = append(b[:], []byte("\n")...)
	}
}

正如所说,目前它可以保存文件。在Visual Studio Code中打开文件时,显示效果符合预期。但在editor.exe中打开时,换行符消失了,所有内容都显示在一行。在记事本中打开时,换行符存在,但变音符号显示不正确。

我对字符编码一无所知,所以这让我非常困惑。有没有一种方法可以保存文本文件,使得所有文本编辑器都能正确显示这些文件?


更多关于Golang中如何正确存储文本?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

感谢大家提供这些信息!

更多关于Golang中如何正确存储文本?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你忽略了即使在Windows系统中,终端也不一定使用UTF编码。

从标准输入读取只会得到系统提供的字节数据,不会自动转换为UTF8格式。

感谢您的帮助。我决定不再使用写字板(就像每个理智的人一样)。我还将 \n 替换为 \r\n,现在它工作得很好。

最佳选择是坚持使用Go默认使用的UTF-8和Unicode编码,并选用更优秀的Windows软件。

然而,许多旧版Windows软件会要求文本文件采用ISO-8859-1(拉丁1)编码。以下是一篇关于字符编码转换的文章:

http://technosophos.com/2016/03/09/go-quickly-converting-character-encodings.html

某些Windows软件无法处理UTF-8编码,因此需要将文件保存为UTF-16格式才能支持表情符号等功能。以下是关于Go如何处理这种情况的相关信息:

https://ipfs.io/ipfs/QmfYeDhGH9bZzihBUDEQbCbTc5k5FZKURMUoUvfmc27BwL/encoding/utf-16_and_go.html

jmbm 提问: 有没有一种方法可以保存文本文件,让每个文本编辑器都能正确显示这些文件?

是的,而且你的做法是正确的。但是你想用来打开文件的那些编辑器需要能够配置输入编码。纯文本文件本身无法指定编码。

jmbm 提问: 当我在记事本中打开它时,换行符存在,但变音符号显示不正确。

那么你需要将其设置为使用与写入文件时相同的编码。它应该与你的终端使用的编码相同。

jmbm 提问: 但当我在 editor.exe 中打开它时,换行符消失了,所有内容都在一行中。

换行符仍然存在,但 editor.exe 没有显示它们。editor.exe 确实需要 Windows 换行符才能实际显示换行。Windows 换行符是 "\r\n"

jmbm 提问: 我对字符编码一无所知

我可能比你知道的也多不了多少,但有一个经验法则:

如果编码不同,输出也会不同。

在Go语言中,文本文件的正确存储涉及字符编码和换行符处理。您遇到的问题主要是由于Windows和Unix系统对换行符的处理差异以及字符编码不一致导致的。

以下是改进后的代码示例,使用UTF-8编码和Windows兼容的换行符:

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	aurora "github.com/logrusorgru/aurora"
)

func save(text string) error {
	filename := "data/test.txt"
	
	// 使用UTF-8编码和Windows换行符
	content := strings.ReplaceAll(text, "\n", "\r\n")
	
	return os.WriteFile(filename, []byte(content), 0600)
}

func main() {
	var input string
	var lines []string
	scanner := bufio.NewScanner(os.Stdin)

	for {
		fmt.Print(aurora.Magenta(">> "))
		scanner.Scan()
		input = scanner.Text()

		if input == "fin" {
			fullText := strings.Join(lines, "\n")
			err := save(fullText)
			if err != nil {
				fmt.Println(err.Error())
			}
			return
		}

		lines = append(lines, input)
	}
}

主要改进点:

  1. 换行符处理:使用\r\n(Windows换行符)替代单纯的\n
  2. 字符编码:Go默认使用UTF-8编码,确保特殊字符正确显示
  3. 字符串处理:直接处理字符串而非字节切片,避免编码问题

对于更通用的解决方案,可以考虑检测操作系统并相应调整换行符:

func save(text string) error {
	filename := "data/test.txt"
	
	var content string
	if strings.Contains(runtime.GOOS, "windows") {
		content = strings.ReplaceAll(text, "\n", "\r\n")
	} else {
		content = text
	}
	
	return os.WriteFile(filename, []byte(content), 0600)
}

这样生成的文本文件应该在大多数编辑器中都能正确显示换行和特殊字符。

回到顶部