在两个文件中查找相似的单词(字符串)

时间:2011-08-15 01:53:25

标签: java java.util.scanner

我必须验证文件1中的单词1与文件2中的单词2的相似性,依此类推。如果单词1(文件1).equals到单词2(文件2),则文件3将是输出以显示True和False。下面是编码,但是当没有错误但没有输出时我被卡住了。我是JAVA的初学者。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class test2 {

    private static ArrayList<String> load(String f1) throws FileNotFoundException {
        Scanner reader = new Scanner(new File(f1));
        ArrayList<String> out = new ArrayList<String>();
        while (reader.hasNext()) {
            String temp = reader.nextLine();
            String[] sts = temp.split(" ");
            for (int i = 0; i < sts.length; i++) {
                if (sts[i].equals("") && sts[i].equals(" ") && sts[i].equals("\n")) {
                    out.add(sts[i]);
                }
            }
        }
        return out;
    }

    private static void write(ArrayList<String> out, String fname) throws IOException {
        FileWriter writer = new FileWriter(new File("out_test2.txt"));
        for (int i = 0; i < out.size(); i++) {
            writer.write(out.get(i) + "\n");
        }
        writer.close();
    }

    public static void main(String[] args) throws IOException {
        ArrayList<String> file1;
        ArrayList<String> file2;
        ArrayList<String> out = new ArrayList<String>();
        file1 = load("IbanDict.txt");
        file2 = load("AFF_outVal.txt");

        for (int i = 0; i < file1.size(); i++) {
            String word1 = file1.get(i);
            for (int z = 0; z < file2.size(); z++) {
                if (word1.equalsIgnoreCase(file2.get(z))) {
                    boolean already = false;
                    for (int q = 0; q < out.size(); q++) {
                        if (out.get(q).equalsIgnoreCase(file1.get(i))) {
                            already = true;
                        }
                    }
                    if (already == false) {
                        out.add(file1.get(i));
                    }
                }
            }
        }
        write(out, "out_test2.txt");
    }

}

4 个答案:

答案 0 :(得分:2)

首先,Scanner将为您标记字符串。无需使用String.split方法读取行和标记;参考here

其次,看起来你有一个逻辑错误:

for (int i = 0; i < sts.length; i++) {
    if (sts[i].equals("") && sts[i].equals(" ")
            && sts[i].equals("\n"))
       out.add(sts[i]);
}

(假设我明白你要做什么)它应该是:

for (int i = 0; i < sts.length; i++) {
    if (!(sts[i].equals("") && sts[i].equals(" ") && sts[i]
           .equals("\n")))
       out.add(sts[i]);
}

这就是你没有看到任何输出的原因。

注意:这种匹配方式容易出错且远非最佳(线性);使用专门的文本解析语言(如awk或Python)可能会取得更大的成功(假设您没有绑定到Java)。如果你坚持使用Java,那么另一种实现可能是扩展FilterReader/Writer类,如图所示here

答案 1 :(得分:2)

以下是我对你的问题的建议

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

  private static final Pattern WORD_PATTERN = Pattern.compile("[\\w']+");

  private static Map<String, Integer> load(final String f1) throws FileNotFoundException {
    Scanner reader = new Scanner(new File(f1));
    Map<String, Integer> out = new HashMap<String, Integer>();
    while (reader.hasNext()) {
      String tempLine = reader.nextLine();
      if (tempLine != null && tempLine.trim().length() > 0) {
        Matcher matcher = WORD_PATTERN.matcher(tempLine);
        while (matcher.find()) {
          out.put(matcher.group().toLowerCase(), 0);
        }
      }
    }

    return out;
  }

  private static void write(final Map<String, Integer> out, final String fname) throws IOException {
    FileWriter writer = new FileWriter(new File(fname));
    for (Map.Entry<String, Integer> word : out.entrySet()) {
      if (word.getValue() == 1) {
        writer.write(word.getKey() + "\n");
      }
    }
    writer.close();
  }

  public static void main(final String[] args) throws IOException {
    Map<String, Integer> file1 = load("file1.txt");
    Map<String, Integer> file2 = load("file2.txt");

    // below for loop will run just one time, so it is much faster
    for (Map.Entry<String, Integer> file1Word : file1.entrySet()) {
      if (file2.containsKey(file1Word.getKey())) {
        file1.put(file1Word.getKey(), 1);
        file2.put(file1Word.getKey(), 1);
      }
    }

    write(file1, "test1.txt");
    write(file2, "test2.txt");
  }

}

答案 2 :(得分:1)

我看到了一些问题。一个是空间的冗余分裂wulfgar.pro指出。

另一个问题是Scanner将包含标点符号,因此如果file2是“你很开心”,file1“我很开心和悲伤”将找不到“快乐”。

我还将其更改为使用集合,因为您似乎并不担心单词匹配的次数。然后使用for-each循环进行迭代(你使用泛型,所以你应该能够为每个循环做一遍)。

所以我在load方法中重写了while循环:

private static final Pattern PUNCTUATION_PATTERN = Pattern.compile("[\\w']+");

private static Set<String> load(String f1) throws FileNotFoundException {
    Scanner reader = new Scanner(new File(f1));
    Set<String> out = new HashSet<String>();
    while (reader.hasNext()) {
        String tempLine = reader.nextLine();
        if (tempLine != null
                && tempLine.trim().length() > 0) {
            Matcher matcher = PUNCTUATION_PATTERN.matcher(tempLine);
            while (matcher.find()) {
                out.add(tempLine.substring(matcher.start(), matcher.end()));
            }
        }
    }
    return out;
}

main方法中的for循环可以简化为:

public static void main(String[] args) throws IOException {
    Set<String> out = new HashSet<String>();
    Set<String> file1 = load("IbanDict.txt");
    Set<String> file2 = load("AFF_outVal.txt");

    for (String word1 : file1) {
        for (String word2 : file2) {
            if (word1.equalsIgnoreCase(word2)) {
                boolean already = false;
                for (String outStr : out) {
                    if (outStr.equalsIgnoreCase(word1)) {
                        already = true;
                    }
                }
                if (!already) {
                    out.add(word1);
                }
            }
        }
    }
    write(out, "out_test2.txt");
}

并将write方法更改为迭代,并使用File.separator与操作系统无关:

private static void write(Iterable<String> out, String fname) throws IOException {
    OutputStreamWriter writer = new FileWriter(new File(fname));
    for (String s : out) {
        writer.write(s + File.separator);
    }
    writer.close();
}

答案 3 :(得分:0)

所以基本上你想要检查文件1中是否还存在文件2中的单词。如果是,则打印为true,如果不打印则为false。

最简单的方法是制作文件1中所有单词的可搜索数据集。对于文件2中的每个单词,您可以检查数据集是否包含单词。

下面的代码什么也没做。它在sts中创建文件中所有单词的数组,然后检查单词是什么,空格和换行符。如果是这样,你将它添加到ArrayList。一个词永远不会是所有这些东西,因此永远不会添加任何一个词。

Scanner reader = new Scanner(new File(f1));
ArrayList<String> out = new ArrayList<String>();
while (reader.hasNext()) {
  String temp = reader.nextLine();    
  String[] sts = temp.split(" ");
  for (int i = 0; i < sts.length; i++) {
    if (sts[i].equals("") && sts[i].equals(" ") && sts[i].equals("\n")) {
      out.add(sts[i]);
    }
  }
}

通过在扫描仪中迭代所有标记并将它们添加到arraylist中来修改您的循环以获取所有单词的集合

while (reader.hasNext()) {
 out.add(reader.next());
}

现在您的词典中有所有单词的arraylist,您可以开始检查。

要查看字典中是否包含文件2中的单词,您只需调用

即可
dictionary.contains(file2.get(i))

包含使用ArrayList中所有字符串的equals方法来检查是否匹配。

现在,如果你想逐行进行,你不应该制作2个数据集。你的字典应该是一个数据集,但对于文件2,只使用Scanner对象更容易。

从扫描仪中读取每一行。确保在这里使用hasNextLine()而不是hasNext(),因为hasNextLine()会对itteration进行检查。

line = reader.nextLine();

检查行中的每个标记是否在列表中有匹配并写入true或false +如果是,则为空格

String[] splitLine = line.split(" "); 
for(String token: splitLine){    
  writer.write(dictionary.contains(file2.get(i))+" ");
}

在检查每一行时,您可以在输出文件中写一行,以便行号匹配。

您明确的代码将如下所示:

public class Test{

  private static List<String> loadDictionary(String fileName) throws FileNotFoundException {
    Scanner reader = new Scanner(new File(fileName));
    List<String> out = new ArrayList<String>();
    while (reader.hasNext()) {
      out.add(reader.next());
    }
    reader.close();
    return out;
  }

  public static void main(String[] args) throws IOException {
    List<String> dictionary;
    dictionary = loadDictionary("IbanDict.txt");

    Scanner reader = new Scanner(new File("AFF_outVal.txt"));
    OutputStreamWriter writer = new FileWriter(new File("out_test2.txt"));

    while(reader.hasNextLine()){
      String line = reader.nextLine();
      String[] tokens = line.split(" ");
      for(String token: tokens){
        writer.write(dictionary.contains(token)+" ");
      }
      writer.write(System.getProperty("line.separator"));
    }
    writer.close();
    reader.close();
  }
}