@smarisov666

Как одновременно прочитать построчно два файла?

Как одновременно прочитать построчно два файла?
Имею такой код, строго прошу не судить, только учусь golang
посмотрел все форумы eu/ru ничего не нашел подходящего
first_file, err := os.Open(config.First_file)
	if err != nil {
		log.Fatalln("error")
		return
	}
	defer first_file.Close()
	first_scanner := bufio.NewScanner(first_file)

	second_file, err := os.Open(config.Second_file)
	if err != nil {
		log.Fatalln("error")
		return
	}
	defer second_file.Close()
	scanner_second := bufio.NewScanner(second_file)

	line_first_file := 1
	line_second_file := 1
	for first_scanner.Scan() {
		for scanner_second.Scan() {
			if strings.Contains(strings.Split(first_scanner.Text(), ":")[1], strings.Split(scanner_second.Text(), ":")[0]) {
				log.Println(first_scanner.Text(), scanner_second.Text())
			}

			line_second_file++
		}
		line_first_file++
	}

	if err := first_scanner.Err(); err != nil {
		log.Fatalln(err)
	}

	if err := scanner_second.Err(); err != nil {
		log.Fatalln(err)
	}
  • Вопрос задан
  • 478 просмотров
Решения вопроса 1
@Wirusnyy-chel
Из комментариев под вопросом:
нужно из файла взять подстроку после : и проверить существует ли подстрока из 1 файла в подстроке файла 2(до :) и если она есть, то записать строку в виде: подстрока из 1 файла: подстрока из 2 файла

размеры файлов до 1гб


Быстрым будет вариант с мапой из ответа выше, но он будет потреблять достаточно много памяти и ищет только прямые вхождения подстроки 1 в подстроке 2.

Предлагаю вариант с меньшим потреблением памяти
file1, err := os.Open(config.First_file)
if err != nil {
  log.Fatalln("error")
}
defer file1.Close()
file1Scanner := bufio.NewScanner(file1)

file2, err := os.Open(config.Second_file)
if err != nil {
  log.Fatalln("error")
}
defer file2.Close()
file2Scanner := bufio.NewScanner(file2)

// находим все доступные подстроки из файла 2
file2SubSrings := make([]string,0)
for file2Scanner.Scan(){
  file2SubSrings = append(file2SubSrings, strings.Split(file2Scanner.Text(), ":")[0])
}

for file1Scanner.Scan() {
  file1SubString := strings.Split(file1Scanner.Text(), ":")[1]
  for _, val := range file2SubStrings{
    if strings.Contains(val, file1SubString) {
      log.Println(file1SubString, ":", val)
      break
    }
}

if err := file1Scanner.Err(); err != nil {
  log.Fatalln(err)
}

if err := file2Scanner.Err(); err != nil {
  log.Fatalln(err)
}


UPD Вариант с параллельностью
func scanFiles(file1, file2 *bufio.Scanner) {
	// находим все доступные подстроки из файла 2
	file2SubStrings := make([]string, 0)
	for file2.Scan() {
		file2SubStrings = append(file2SubStrings, strings.Split(file2.Text(), ":")[0])
	}

	wg := new(sync.WaitGroup)
	valChan := make(chan string)
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go findIntersections(valChan, file2SubStrings, wg)
	}

	for file1.Scan() {
		valChan <- strings.Split(file1.Text(), ":")[1]
	}

	wg.Wait()
}

func findIntersections(values chan string, file2SubStrings []string, wg *sync.WaitGroup) {
	for {
		file1SubString, ok := <-values

		if !ok {
			wg.Done()
			return
		}

		for _, val := range file2SubStrings {
			if strings.Contains(val, file1SubString) {
				log.Println(file1SubString, ":", val)
				break
			}
		}
	}
}


UPD2
строка из файла 2 - 663624e4aae0164132f10f09fdd9fcd2:liberty_
строка из файла 1 - scherbakovatd@example.com:663624e4aae0164132f10f09fdd9fcd2
на выходе должно выйти scherbakovatd@example.com:liberty_

func scanFiles(file1, file2 *bufio.Scanner) {
	scanWg := new(sync.WaitGroup)
	scanWg.Add(2)

	file1SubStrings := make(map[string]string)
	file2SubStrings := make(map[string]string)


	go func() {
		var substr []string
		for file1.Scan() {
			substr = strings.Split(file1.Text(), ":")
			file1SubStrings[substr[1]] = substr[0]
		}
		scanWg.Done()
	}()
	
	go func() {
		var substr []string 
		for file2.Scan() {
			substr = strings.Split(file2.Text(), ":")
			file2SubStrings[substr[0]] = substr[1]
		}	
		scanWg.Done()
	}()
	
	scanWg.Wait()
	
	
	wg := new(sync.WaitGroup)
	valChan := make(chan struct{k,v string})
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go findIntersections(valChan, file2SubStrings, wg)
	}

	for k, v := range file1SubStrings {
		valChan <- struct{ k, v string }{k: k, v: v}
	}

	wg.Wait()
}

func findIntersections(file1Values chan struct{ k,v string}, file2 map[string]string, wg *sync.WaitGroup) {
	for {
		file1, ok := <-file1Values

		if !ok {
			wg.Done()
			return
		}
		
		if file2Value, ok := file2[file1.k];ok {
			log.Println(file1.k, ":", file2Value)
		}
	}
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы