2011-08-15 46 views
5

我必須驗證文件1中的字1與文件2中的字2的相似性,等等。如果單詞1(文件1)。等於單詞2(文件2),則文件3將是輸出以顯示真和假。下面是編碼,但當沒有錯誤但沒有輸出時,我卡住了。我是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"); 
    } 

} 
+2

你可以格式化你的代碼的建議好一點?這很難閱讀。另外 - 你有沒有調試通過你的每一個循環,看看每個ArrayList和/或變量持有比較或寫入file3時保持什麼? – Jack

+1

請編輯您的文章並縮進代碼以顯示結構。它目前的狀態是不可讀的。 –

+1

你可能想看看Levenshtein距離。有一些Java庫/算法已經存在。 – Mike

回答

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所示。

+0

實際上,我試圖檢查字典(file1)中是否存在單詞1。因此,我如何改進if語句? – ssaee

+0

沒有真正看待你的解決方案如何工作,我會建議嘗試否定邏輯,即'if(!(sts [i] .equals(「」)&& sts [i] .equals(「」)&& sts [i ] .equals(「\ n」))){...}' – wulfgarpro

+0

是的,有空。意思是if語句必須遵循輸入文件中的格式? – ssaee

1

我看到了一些問題。一個是空間wulfgar.pro指出的冗餘分裂。

另一個問題是,Scanner將包含標點符號,所以file1「我高興而難過」如果file2是「您很高興」,則不會找到「高興」。

我也改變它使用集,因爲你似乎並不擔心一個單詞匹配多少次。然後使用for-each循環進行迭代(您正在使用泛型,所以您應該可以爲每個循環做好準備)。

所以我改寫了while循環在load方法:

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; 
} 

的for循環中main方法然後可以簡化爲:

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(); 
} 
0

因此,基本上你想檢查文件2中是否存在一個單詞。如果是,則打印爲真,如果不打印爲假。

最簡單的方法可能是創建文件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()會檢查你需要的迭代。

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(); 
    } 
} 
2

這是我送給你的porblem

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"); 
    } 

} 
+0

我喜歡'Pattern'類的使用。我建議擴展'FilterReader/Writer'作爲一種促進封裝這種邏輯的方法。 – wulfgarpro