Golang解析文本文件的实用教程

Golang解析文本文件的实用教程 我是Go编程的新手。

通过观看Rob Pike讲述Go语言的诞生故事以及包含Ken Thompson参与的Go讨论,我相信我对他们期望Go语言用于哪些目的有了一个很好的概览。Go既是一种编译为本地机器代码的低级语言,也是一种服务器端生产环境项目语言。在C语言语法难以理解的地方,Go语法被简化了(我推测是相对于C而言),以便于理解。

我从这项研究中得出的结论是,Go基于C语言的力量,简化了语法,并包含了有利于许多开发者工作的“服务器机房”环境的特性。就像是C和Erlang结婚后生了一个叫Go的孩子。

我想学习如何处理文件:打开、读取、关闭。

这是一个来自《Clojure in a Nutshell》演讲的例子。

从古登堡计划下载一本书作为文本文件 将书转换为字符串 提供一个仅包含单词字符(包括所有格中的撇号)的结果 返回书中的前20个单词 20个最常用的单词 20个最长的单词 最长的回文词

当这个程序在非英语文本上运行时,其功能会如何?你期望得到什么结果?


更多关于Golang解析文本文件的实用教程的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

首先,请查看:

pkg.go.dev

http package - net/http - Go Packages

Package http provides HTTP client and server implementations.

使用 strings.Split 进行简单的实现,你可以走得很远:

func main() {
	// 下载一本书
	res, err := http.Get("https://www.gutenberg.org/cache/epub/1513/pg1513.txt")
	if err != nil {
		log.Fatal(err)
	}
	// 读取响应体
	body, err := io.ReadAll(res.Body)
	if err != nil {
		log.Fatal(err)
	}
	res.Body.Close()
	// 转换为字符串
	converted := string(body)
	// 基于换行符分割以获取书中的所有行
	lines := strings.Split(converted, "\n")
	// 跟踪最长的单词。
	longest := ""
	for _, line := range lines {
		allWords := strings.Split(line, " ")
		for _, v := range allWords {
			if len(v) > len(longest) {
				longest = v
			}
		}
	}

	fmt.Println("Longest word:", longest)
}

请注意,这完全未经测试,旨在作为一个起点让你开始。它的效率也相当低。所以,一旦你开始使用这个,请查看以下扫描器的示例。扫描行:

pkg.go.dev

bufio package - bufio - Go Packages

Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.

以及如何扫描单词:

pkg.go.dev

bufio package - bufio - Go Packages

Package bufio implements buffered I/O. It wraps an io.Reader or io.Writer object, creating another object (Reader or Writer) that also implements the interface but provides buffering and some help for textual I/O.

因此,你可以执行获取操作,然后在将行/单词扫描到字符串时进行处理,而不是将整个内容转换为字符串再使用 strings.Split(再次强调——这是一种内存密集型的方法)。在这种情况下效率重要吗?可能不重要——但如果你遇到内存问题,可以尝试使用扫描器。无论如何,希望这能引导你走上正确的道路!

更多关于Golang解析文本文件的实用教程的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go语言解析文本文件的实用实现

以下是一个完整的Go程序,演示如何解析文本文件并完成您要求的所有分析任务:

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"sort"
	"strings"
	"unicode"
)

// 单词统计结构
type WordCount struct {
	Word  string
	Count int
}

// 按长度排序的结构
type ByLength []string

func (s ByLength) Len() int           { return len(s) }
func (s ByLength) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
func (s ByLength) Less(i, j int) bool { return len(s[i]) > len(s[j]) }

func main() {
	// 1. 打开文件
	file, err := os.Open("book.txt")
	if err != nil {
		log.Fatal("无法打开文件:", err)
	}
	defer file.Close() // 确保文件关闭

	// 2. 读取文件内容
	content, err := io.ReadAll(file)
	if err != nil {
		log.Fatal("读取文件失败:", err)
	}

	// 3. 转换为字符串
	text := string(content)

	// 4. 提取单词(支持Unicode字符)
	words := extractWords(text)

	// 5. 输出前20个单词
	fmt.Println("=== 前20个单词 ===")
	for i := 0; i < min(20, len(words)); i++ {
		fmt.Printf("%d: %s\n", i+1, words[i])
	}
	fmt.Println()

	// 6. 20个最常用的单词
	fmt.Println("=== 20个最常用的单词 ===")
	commonWords := mostCommonWords(words, 20)
	for i, wc := range commonWords {
		fmt.Printf("%d: %s (%d次)\n", i+1, wc.Word, wc.Count)
	}
	fmt.Println()

	// 7. 20个最长的单词
	fmt.Println("=== 20个最长的单词 ===")
	longestWords := longestWords(words, 20)
	for i, word := range longestWords {
		fmt.Printf("%d: %s (%d字符)\n", i+1, word, len([]rune(word)))
	}
	fmt.Println()

	// 8. 最长的回文词
	fmt.Println("=== 最长的回文词 ===")
	longestPalindrome := findLongestPalindrome(words)
	if longestPalindrome != "" {
		fmt.Printf("最长的回文词: %s (%d字符)\n", 
			longestPalindrome, len([]rune(longestPalindrome)))
	} else {
		fmt.Println("未找到回文词")
	}
}

// 提取单词(支持Unicode)
func extractWords(text string) []string {
	// 使用正则表达式匹配单词字符(包括Unicode字母和所有格撇号)
	re := regexp.MustCompile(`[\p{L}']+`)
	matches := re.FindAllString(text, -1)
	
	// 转换为小写并过滤空字符串
	var words []string
	for _, match := range matches {
		word := strings.ToLower(match)
		if word != "" {
			words = append(words, word)
		}
	}
	return words
}

// 统计最常用的单词
func mostCommonWords(words []string, n int) []WordCount {
	wordMap := make(map[string]int)
	
	// 统计词频
	for _, word := range words {
		wordMap[word]++
	}
	
	// 转换为切片并排序
	var wordCounts []WordCount
	for word, count := range wordMap {
		wordCounts = append(wordCounts, WordCount{word, count})
	}
	
	sort.Slice(wordCounts, func(i, j int) bool {
		if wordCounts[i].Count == wordCounts[j].Count {
			return wordCounts[i].Word < wordCounts[j].Word
		}
		return wordCounts[i].Count > wordCounts[j].Count
	})
	
	if len(wordCounts) > n {
		return wordCounts[:n]
	}
	return wordCounts
}

// 获取最长的单词
func longestWords(words []string, n int) []string {
	// 去重
	uniqueWords := make(map[string]bool)
	var uniqueList []string
	for _, word := range words {
		if !uniqueWords[word] {
			uniqueWords[word] = true
			uniqueList = append(uniqueList, word)
		}
	}
	
	// 按长度排序
	sort.Sort(ByLength(uniqueList))
	
	if len(uniqueList) > n {
		return uniqueList[:n]
	}
	return uniqueList
}

// 检查是否为回文
func isPalindrome(s string) bool {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		if runes[i] != runes[j] {
			return false
		}
	}
	return true
}

// 查找最长的回文词
func findLongestPalindrome(words []string) string {
	var longest string
	seen := make(map[string]bool)
	
	for _, word := range words {
		if !seen[word] && isPalindrome(word) {
			seen[word] = true
			if len([]rune(word)) > len([]rune(longest)) {
				longest = word
			}
		}
	}
	return longest
}

// 辅助函数
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

非英语文本处理说明

对于非英语文本,这个程序有以下处理能力:

  1. Unicode支持:使用\p{L}匹配所有Unicode字母字符,可以处理中文、日文、阿拉伯文等
  2. 字符计数:使用[]rune进行字符计数,正确处理多字节字符
  3. 大小写转换strings.ToLower()对Unicode字符有效

非英语文本的预期结果:

  • 中文/日文[\p{L}']+会匹配汉字、假名等字符,但可能将连续字符视为一个"单词"
  • 阿拉伯文/希伯来文:从右向左书写不影响字符匹配,但回文检测可能不准确
  • 带变音符号的语言:如法语、德语,Unicode支持会保留变音符号
  • 连字处理:某些语言的特殊连字可能需要额外处理

改进建议(针对多语言):

// 针对特定语言的分词改进
func extractWordsMultilingual(text string, lang string) []string {
	switch lang {
	case "zh", "ja", "ko":
		// 中日韩文需要更复杂的分词
		re := regexp.MustCompile(`[\p{Han}\p{Hiragana}\p{Katakana}\p{Hangul}]+`)
		return re.FindAllString(text, -1)
	default:
		return extractWords(text)
	}
}

这个程序展示了Go语言处理文件的基本模式:os.Open()io.ReadAll() → 处理 → defer file.Close()。Go的标准库提供了强大的文本处理能力,特别是regexp包对Unicode的良好支持。

回到顶部