Golang实现两个文本文件的逐行对比

Golang实现两个文本文件的逐行对比 我想知道如何在 Go 语言中实现两个文本(.txt)文件的逐行比较。

例如,file1 的内容: Hello world! Hello Bob! Lorem ipsum

file2 的内容: Hello world! Not matched line Lorem ipsum Not matched line

如你所见,第 1 行和第 3 行是相同的。

结果应该类似于: file1 与 file2 比较:3 行中有 2 行相同。 file2 与 file1 比较:4 行中有 2 行相同。

2 回复

你好 Valentyn!

虽然这不能完全解决你的问题,但下面的代码展示了如何打开一个文件并逐行读取。我不太确定如何同时扫描两个文件,但你可以尝试将每个文件读入一个字符串切片中,每个索引代表一行。

然后,处理这两个 []string 并比较它们的每个索引就会更容易。这种方法效率不高,因为你需要分配两个切片然后遍历它们,但如果它满足你的使用场景,也是可行的。

file, err := os.Open("file1.txt")
if err != nil {
	panic(err)
}

scanner := bufio.NewScanner(file)

var file1Lines []string

for scanner.Scan() {
	currentLineText := scanner.Text()
	file1Lines = append(file1Lines, currentLineText)
}

更多关于Golang实现两个文本文件的逐行对比的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


package main

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

func main() {
	// 读取文件1
	file1, err := os.Open("file1.txt")
	if err != nil {
		fmt.Printf("无法打开file1.txt: %v\n", err)
		return
	}
	defer file1.Close()

	// 读取文件2
	file2, err := os.Open("file2.txt")
	if err != nil {
		fmt.Printf("无法打开file2.txt: %v\n", err)
		return
	}
	defer file2.Close()

	// 创建扫描器
	scanner1 := bufio.NewScanner(file1)
	scanner2 := bufio.NewScanner(file2)

	// 逐行比较
	lineNum := 1
	matchedLines := 0
	totalLines1 := 0
	totalLines2 := 0

	// 同时读取两个文件
	for scanner1.Scan() || scanner2.Scan() {
		line1 := ""
		line2 := ""

		if scanner1.Scan() {
			line1 = scanner1.Text()
			totalLines1++
		}

		if scanner2.Scan() {
			line2 = scanner2.Text()
			totalLines2++
		}

		// 比较当前行
		if line1 == line2 {
			matchedLines++
			fmt.Printf("第 %d 行匹配: %s\n", lineNum, line1)
		} else {
			fmt.Printf("第 %d 行不匹配:\n", lineNum)
			if line1 != "" {
				fmt.Printf("  file1: %s\n", line1)
			}
			if line2 != "" {
				fmt.Printf("  file2: %s\n", line2)
			}
		}

		lineNum++
	}

	// 检查扫描错误
	if err := scanner1.Err(); err != nil {
		fmt.Printf("读取file1.txt时出错: %v\n", err)
	}

	if err := scanner2.Err(); err != nil {
		fmt.Printf("读取file2.txt时出错: %v\n", err)
	}

	// 输出统计结果
	fmt.Printf("\n统计结果:\n")
	fmt.Printf("file1 与 file2 比较:%d 行中有 %d 行相同。\n", totalLines1, matchedLines)
	fmt.Printf("file2 与 file1 比较:%d 行中有 %d 行相同。\n", totalLines2, matchedLines)
}

如果需要更详细的比较,比如找出哪些行不同,可以使用以下增强版本:

package main

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

func compareFiles(file1Path, file2Path string) error {
	// 读取文件1的所有行
	lines1, err := readAllLines(file1Path)
	if err != nil {
		return fmt.Errorf("读取文件1失败: %v", err)
	}

	// 读取文件2的所有行
	lines2, err := readAllLines(file2Path)
	if err != nil {
		return fmt.Errorf("读取文件2失败: %v", err)
	}

	// 找出匹配的行
	matchedCount := 0
	maxLines := max(len(lines1), len(lines2))

	fmt.Println("逐行比较结果:")
	for i := 0; i < maxLines; i++ {
		line1 := ""
		line2 := ""

		if i < len(lines1) {
			line1 = lines1[i]
		}
		if i < len(lines2) {
			line2 = lines2[i]
		}

		if line1 == line2 && line1 != "" {
			matchedCount++
			fmt.Printf("✓ 第 %d 行: %s\n", i+1, line1)
		} else {
			fmt.Printf("✗ 第 %d 行:\n", i+1)
			if line1 != "" {
				fmt.Printf("  file1: %s\n", line1)
			}
			if line2 != "" {
				fmt.Printf("  file2: %s\n", line2)
			}
		}
	}

	// 输出统计信息
	fmt.Printf("\n文件统计:\n")
	fmt.Printf("file1 总行数: %d\n", len(lines1))
	fmt.Printf("file2 总行数: %d\n", len(lines2))
	fmt.Printf("匹配行数: %d\n", matchedCount)
	fmt.Printf("file1 与 file2 比较:%d 行中有 %d 行相同。\n", len(lines1), matchedCount)
	fmt.Printf("file2 与 file1 比较:%d 行中有 %d 行相同。\n", len(lines2), matchedCount)

	return nil
}

func readAllLines(filePath string) ([]string, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var lines []string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return lines, nil
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	if err := compareFiles("file1.txt", "file2.txt"); err != nil {
		fmt.Printf("比较文件时出错: %v\n", err)
	}
}

这两个示例都实现了逐行比较文本文件的功能。第一个版本使用流式处理,适合大文件;第二个版本将文件内容读入内存,提供更详细的比较信息。

回到顶部