2017-03-08 149 views
1

我有一個包含這樣的代碼的XML基.tbx文件:多單詞替換用java

<descripGrp> 
     <descrip type="subjectField">406001</descrip> 
    </descripGrp> 
    <langSet xml:lang="en"> 
     <tig> 
     <term>competence of the Member States</term> 
     <termNote type="termType">fullForm</termNote> 
     <descrip type="reliabilityCode">3</descrip> 
     </tig> 
    </langSet> 
    <langSet xml:lang="pl"> 
     <tig> 
     <term>kompetencje państw członkowskich</term> 
     <termNote type="termType">fullForm</termNote> 
     <descrip type="reliabilityCode">3</descrip> 
     </tig> 
    </langSet> 
    </termEntry> 
    <termEntry id="IATE-290"> 
    <descripGrp> 
     <descrip type="subjectField">406001</descrip> 
    </descripGrp> 

我想搜索和整個內更換(幾乎50 MIB)文件用於從所述碼字段「subjectField」並替換爲正確的文本,例如。政治意識形態爲406001,政治制度爲406002。 我有代碼和相應名稱的表: 406001政治意識形態 406002政治制度 406003政治哲學

有五百強這樣的代碼用手這樣它會採取像永遠。 我不是程序員(我是學生),但我知道一個小小的Java,所以我做了一些小應用程序,我認爲它會幫助我,但結果令人沮喪(幸運的是,我並不氣餒:))

這就是我寫的,結果是它的工作非常緩慢,根本不替代這些代碼。它在15分鐘內處理了文件的1/5(!)。此外,輸出文件中沒有新的行字符,因此整個xml代碼都在一行中。

任何提示我應該走哪條路?

File log= new File("D:\\IATE\\export_EN_PL_2017-03-07_All_Langs.tbx"); // TBX file to be processed 
    File newe = new File("D:\\IATE\\now.txt"); // output file 
    String search = "D:\\IATE\\org.txt"; // file containing codes "40600" etc 
    String replace = "D:\\IATE\\rplc.txt"; // file containing names 

    try { 
     FileReader fr = new FileReader(log); 
     String s; 
     String s1; 
     String s2; 
     String totalStr = ""; 
     String tot1 = ""; 
     String tot2 = ""; 
     FileReader fr1 = new FileReader(search); 
     FileReader fr2 = new FileReader(replace); 
     try (BufferedReader br = new BufferedReader(fr)) { 
      try (BufferedReader br1 = new BufferedReader(fr1)) { 
       try (BufferedReader br2 = new BufferedReader(fr2)) { 
        while ((s = br.readLine()) != null) { 
         totalStr += s; 
          while((s1 = br1.readLine()) != null){ 
           tot1 += s1; 

           while ((s2 = br2.readLine()) != null){ 
            tot2 += s2; 
           } 
          } 
         totalStr = totalStr.replaceAll(tot1, tot2); 

        FileWriter fw = new FileWriter(newe); 

        fw.write(totalStr); 
        fw.write("\n"); 
        fw.close(); 
        } 


       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

} 
+0

你似乎不是必要進行製作方式更多的讀者。你說你有一個表格將代碼分配給一個相應的名字,它是什麼類型的文件,它是如何組織的? –

+0

我有兩個文件,第一個有數字,代碼:org.txt eg。 406003並在另一個名稱中聲明:rplc.txt eg。政治意識形態。這就像一個分成兩個文件的兩列表格。 – Hipacy

+0

使用Java,您至少可以使用Saxon 9(可從Maven和Sourceforge免費獲得)運行XSLT 2.0,所以我會考慮使用XSLT 2.0來執行此操作。這當然不是用字符串處理和簡單文件IO來做到這一點的正確方法。 –

回答

0

它將花費大量的冗餘工作來遍歷2個文件以獲得匹配的值。在替換.tbx文件中的值之前,應該設置屬性文件以讀取。下面是會做一個函數:

public static Properties getProps(String pathToNames, String pathToNumbers){ 

    Properties prop = new Properties(); 

    try{ 
     File names = new File(pathToNames); 
     BufferedReader theNames = new BufferedReader(new InputStreamReader (new FileInputStream(names))); 
     File numbers = new File(pathToNumbers); 
     BufferedReader theNumbers = new BufferedReader(new InputStreamReader (new FileInputStream(numbers))); 

     String name; 
     String number; 
     while(((name = theNames.readLine())!= null)&&((number = theNumbers.readLine())!= null)){ 
      prop.put(number, name); 
     } 
     theNames.close(); 
     theNumbers.close(); 

    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
    return prop; 
} 

假設你使用的是Java 8中,您可以檢查功能正在與此:

thePropertiesFile.forEach((Object key, Object value) ->{ 
    System.out.println(key+ " " +value); 
}); 

現在你可以寫,將正確轉換功能。使用PrintStream來實現所需的輸出功能。

static String workingDir = System.getProperty("user.dir"); 
public static void main(String[] args){ 

    Properties p = getProps(workingDir+"path/to/names.txt",workingDir+"path/to/numbers.txt"); 
    File output = new File(workingDir+"path/to/output.txt"); 

    try { 
     PrintStream ps = new PrintStream(output); 
     BufferedReader tbx = new BufferedReader(new InputStreamReader (new FileInputStream(new File(workingDir+"path/to/the.tbx")))); 
     String currentLine; 
     String theNum; 
     String theName; 
     int c; //temp index 
     int start; 
     int end; 
     while((currentLine = tbx.readLine()) != null){ 
      if(currentLine.contains("subjectField")){ 
       c = currentLine.indexOf("subjectField"); 
       start = currentLine.indexOf(">", c)+1; 
       end = currentLine.indexOf("<", c); 
       theNum = currentLine.substring(start, end); 
       theName = p.getProperty(theNum); 
       currentLine = currentLine.substring(0,start)+theName+currentLine.substring(end); 
      } 
      ps.println(currentLine);    
     } 
     ps.close(); 
     tbx.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

} 

對於不存在的數字,將用空字符串替換它們。您可以根據您的具體使用情況進行更新。

如果theNum包含多個值,分成數組:

theName = ""; 
if(theNum.contains(","){ 
    int[] theNums = theNum.split(",");  
    for (int num : theNums) { 
     theName += p.getProperty(num); 
     theName += ","; 
    } 
    theName = theName.replaceAll(",$", ""); //get rid of trailing comma 
} 
else 
    theName = p.getProperty(theNum); 
+0

非常感謝喬!你的態度似乎更有效率和更聰明:)我不知道PrintStream或Property(我想過使用HashMap)類,它使得寫文件變得如此簡單。我有幾個問題,但我想知道它是如何工作的。此外,該代碼不涵蓋tbx文件中發生的所有可能性。有這樣的東西:「subjectField」> 3606003,5211005,5641它給出了「null」(我知道爲什麼,當然) - 有兩個或多個代碼的字段。我需要再使用一個條件陳述。 – Hipacy

+0

是的,它會是一個更多的條件,'theNum'將包含3606003,5211005,5641在這種情況下,所以只要檢查'如果(theNum.contains(「,」)'然後做適當的邏輯將它分成一個數組或東西 –

+0

不要忘了檢查爲答案,如果這有助於你:) –