Информация о совпадении из 2 файлов на Java - PullRequest
0 голосов
/ 07 мая 2018

Я пытаюсь написать программу, которая проверяет два файла и печатает общее содержимое обоих файлов.

Пример содержимого файла 1:

James 1
Cody 2
John 3

Пример содержимого файла 2:

1 Computer Science
2 Chemistry
3 Physics

Таким образом, конечный вывод, напечатанный на консоли, будет:

James Computer Science
Cody Chemistry
John Physics

Вот что у меня есть в моем коде:

public class Filereader {
    public static void main(String[] args) throws Exception {

    File file = new File("file.txt");
    File file2 = new File("file2.txt");
    BufferedReader reader = new BufferedReader(new FileReader(file));
    BufferedReader reader2 = new BufferedReader(new FileReader(file2));
    String st, st2;
    while ((st = reader.readLine()) != null) { 
         System.out.println(st);
    }
    while ((st2 = reader2.readLine()) != null) {
            System.out.println(st2);
    }
    reader.close();

    reader2.close();

    }
}

У меня проблемы с выяснением того, как сопоставить содержимое файла, и распечатать только имя учащегося и его основные данные, сопоставив идентификатор учащегося в каждом файле. Спасибо за помощь.

Ответы [ 5 ]

0 голосов
/ 07 мая 2018

Если вы измените порядок так, чтобы номер был первым в обоих файлах, вы можете прочитать оба файла в HashMap, а затем создать набор общих ключей. Затем переберите набор общих ключей и извлеките связанное значение из каждого Hashmap для печати:

Мое решение многословно, но я написал это так, чтобы вы могли точно видеть, что происходит.

import java.util.Set;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.io.File;
import java.util.Scanner;

class J {

  public static Map<String, String> fileToMap(File file) throws Exception {

    // TODO - Make sure the file exists before opening it

    // Scans the input file
    Scanner scanner          = new Scanner(file);

    // Create the map
    Map<String, String> map = new HashMap<>();

    String   line;
    String   name;
    String  code;
    String[] parts = new String[2];

    // Scan line by line
    while (scanner.hasNextLine()) {

      // Get next line
      line = scanner.nextLine();

      // TODO - Make sure the string has at least 1 space

      // Split line by index of first space found
      parts = line.split(" ", line.indexOf(' ') - 1);

      // Get the class code and string val
      code = parts[0];
      name = parts[1];

      // Insert into map
      map.put(code, name);
    }

    // Close input stream
    scanner.close();

    // Give the map back
    return map;
  }

  public static Set<String> commonKeys(Map<String, String> nameMap,
                                       Map<String, String> classMap) {

    Set<String> commonSet = new HashSet<>();

    // Get a set of keys for both maps
    Set<String> nameSet  = nameMap.keySet();
    Set<String> classSet = classMap.keySet();

    // Loop through one set
    for (String key : nameSet) {

      // Make sure the other set has it
      if (classSet.contains(key)) {

        commonSet.add(key);
      }
    }

    return commonSet;
  }

  public static Map<String, String> joinByKey(Map<String, String> namesMap,
                                              Map<String, String> classMap,
                                              Set<String> commonKeys) {

    Map<String, String> map = new HashMap<String, String>();

    // Loop through common keys
    for (String key : commonKeys) {

      // TODO - check for nulls if get() returns nothing

      // Fetch the associated value from each map
      map.put(namesMap.get(key), classMap.get(key));
    }

    return map;
  }

  public static void main(String[] args) throws Exception {

    // Surround in try catch
    File names   = new File("names.txt");
    File classes = new File("classes.txt");

    Map<String, String> nameMap  = fileToMap(names);
    Map<String, String> classMap = fileToMap(classes);
    Set<String> commonKeys       = commonKeys(nameMap, classMap);

    Map<String, String> nameToClass = joinByKey(nameMap, classMap, commonKeys);

    System.out.println(nameToClass);

  }
}

names.txt

1 James
2 Cody
3 John
5 Max

classes.txt

1 Computer Science
2 Chemistry
3 Physics
4 Biology

Выход:

{Cody=Chemistry, James=Computer, John=Physics}

Примечания:

  1. Я добавил ключи в classes.txt и names.txt, которые нарочно не совпадали, поэтому вы видите, что они не отображаются в выходных данных. Это потому, что ключ никогда не попадает в набор commonKeys. Таким образом, они никогда не вставляются в объединенную карту.

  2. Вы можете перебрать HashMap, если хотите, чтобы я звонил map.entrySet()

0 голосов
/ 07 мая 2018

Вы можете использовать другие ответы и создать объект для каждого файла, например таблицы в базах данных.

public class Person{
   Long id;
   String name;
   //getters and setters
}
public class Course{
   Long id;
   String name;
   //getters and setters
}

Их у вас больше контроль с вашими столбцами, и это просто в использовании. Кроме того, вы будете использовать ArrayList<Person> и ArrayList<Course>, и ваши отношения могут быть переменной внутри ваших объектов, таких как courseId в Person классе или что-то еще.

if(person.getcourseId() == course.getId()){
   ...
}

В качестве совпадения для первого числа файлов используется person.getId() == course.getId(). Ps: не используйте split(" ") в вашем случае, потому что вы можете иметь другие объекты с двумя значениями, т.е. 1 Computer Science.

0 голосов
/ 07 мая 2018

То, что вы хотите, это организовать данные вашего текстового файла в карту, а затем объединить их данные.Это будет работать, даже если ваши данные смешаны, а не в порядке.

public class Filereader {
    public static void main(String[] args) throws Exception {

    File file = new File("file.txt");
    File file2 = new File("file2.txt");
    BufferedReader reader = new BufferedReader(new FileReader(file));
    BufferedReader reader2 = new BufferedReader(new FileReader(file2));
    String st, st2;

    Map<Integer, String> nameMap = new LinkedHashMap<>();
    Map<Integer, String> majorMap = new LinkedHashMap<>();

    while ((st = reader.readLine()) != null) { 
         System.out.println(st);
         String[] parts = st.split(" "); // Here you got ["James", "1"]
         String name = parts[0];
         Integer id = Integer.parseInt(parts[1]);
         nameMap.put(id, name);
    }
    while ((st2 = reader2.readLine()) != null) {
         System.out.println(st2);
         String[] parts = st2.split(" ");
         String name = parts[1];
         Integer id = Integer.parseInt(parts[0]);
         majorMap.put(id, name);
    }
    reader.close();
    reader2.close();

    // Combine and print
    nameMap.keySet().stream().forEach(id -> {
      System.out.println(nameMap.get(id) + " " + majorMap.get(id));
    })

    }
}
0 голосов
/ 07 мая 2018

Объединение файлов NIO и Stream API немного проще:

public static void main(String[] args) throws Exception {
    Map<String, List<String[]>> f1 = Files
            .lines(Paths.get("file1"))
            .map(line -> line.split(" "))
            .collect(Collectors.groupingBy(arr -> arr[1]));
    Map<String, List<String[]>> f2 = Files
            .lines(Paths.get("file2"))
            .map(line -> line.split(" "))
            .collect(Collectors.groupingBy(arr -> arr[0]));

    Stream.concat(f1.keySet().stream(), f2.keySet().stream())
        .distinct()
        .map(key -> f1.get(key).get(0)[0] + " " + f2.get(key).get(0)[1])
        .forEach(System.out::println);
}

Как легко заметить в коде, существуют предположения о допустимости данных и согласованности между этими двумя файлами. Если это не так, вам может понадобиться сначала запустить фильтр, чтобы исключить записи, отсутствующие в обоих файлах:

Stream.concat(f1.keySet().stream(), f2.keySet().stream())
    .filter(key -> f1.containsKey(key) && f2.containsKey(key))
    .distinct()
    ...
0 голосов
/ 07 мая 2018

Вы должны читать эти файлы одновременно в последовательности. Это легко сделать с помощью одного оператора while.

while ((st = reader.readLine()) != null && (st2 = reader2.readLine()) != null) {
    // print both st and st2
}

То, как ваш код написан сейчас, он читает по одному файлу за раз, печатая данные на консоль из каждого отдельного файла. Если вы хотите объединить результаты вместе, вы должны объединить вывод файлов в один цикл.


Принимая во внимание, что вы также можете иметь файл нечетного размера в одном пакете, но у вас есть числа для корреляции, или числа могут приходить в непоследовательном порядке, вы можете сохранить эти результаты в данных вместо структуры, как List, так как вы знаете конкретный индекс каждого из этих значений и знаете, где они должны вписываться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...