OSDN Git Service

b4cb48714a33d72ba4cae2b956664226fde4cbe7
[neighbornote/NeighborNote.git] / src / com / swabunga / spell / engine / SpellDictionaryDichoDisk.java
1 /*\r
2 Jazzy - a Java library for Spell Checking\r
3 Copyright (C) 2001 Mindaugas Idzelis\r
4 Full text of license can be found in LICENSE.txt\r
5 \r
6 This library is free software; you can redistribute it and/or\r
7 modify it under the terms of the GNU Lesser General Public\r
8 License as published by the Free Software Foundation; either\r
9 version 2.1 of the License, or (at your option) any later version.\r
10 \r
11 This library is distributed in the hope that it will be useful,\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
14 Lesser General Public License for more details.\r
15 \r
16 You should have received a copy of the GNU Lesser General Public\r
17 License along with this library; if not, write to the Free Software\r
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
19 */\r
20 package com.swabunga.spell.engine;\r
21 \r
22 import java.io.EOFException;\r
23 import java.io.File;\r
24 import java.io.FileNotFoundException;\r
25 import java.io.IOException;\r
26 import java.io.RandomAccessFile;\r
27 import java.util.LinkedList;\r
28 import java.util.List;\r
29 \r
30 /**\r
31  * Another implementation of <code>SpellDictionary</code> that doesn't cache any words in memory. Avoids the huge\r
32  * footprint of <code>SpellDictionaryHashMap</code> at the cost of relatively minor latency. A future version\r
33  * of this class that implements some caching strategies might be a good idea in the future, if there's any\r
34  * demand for it.\r
35  *\r
36  * This implementation requires a special dictionary file, with "code*word" lines sorted by code.\r
37  * It's using a dichotomy algorithm to search for words in the dictionary\r
38  *\r
39  * @author Damien Guillaume\r
40  * @version 0.1\r
41  */\r
42 public class SpellDictionaryDichoDisk extends SpellDictionaryASpell {\r
43 \r
44   /** Holds the dictionary file for reading*/\r
45   private RandomAccessFile dictFile = null;\r
46 \r
47   /** dictionary and phonetic file encoding */\r
48   private String encoding = null;\r
49 \r
50   /**\r
51    * Dictionary convenience Constructor.\r
52    * @param wordList The file containing the words list for the dictionary\r
53    * @throws java.io.FileNotFoundException indicates problems locating the\r
54    * words list file on the system\r
55    * @throws java.io.IOException indicates problems reading the words list\r
56    * file\r
57    */\r
58   public SpellDictionaryDichoDisk(File wordList)\r
59     throws FileNotFoundException, IOException {\r
60     super((File) null);\r
61     dictFile = new RandomAccessFile(wordList, "r");\r
62   }\r
63 \r
64   /**\r
65    * Dictionary convenience Constructor.\r
66    * @param wordList The file containing the words list for the dictionary\r
67    * @param encoding Uses the character set encoding specified\r
68    * @throws java.io.FileNotFoundException indicates problems locating the\r
69    * words list file on the system\r
70    * @throws java.io.IOException indicates problems reading the words list\r
71    * file\r
72    */\r
73   public SpellDictionaryDichoDisk(File wordList, String encoding)\r
74     throws FileNotFoundException, IOException {\r
75     super((File) null);\r
76     this.encoding = encoding;\r
77     dictFile = new RandomAccessFile(wordList, "r");\r
78   }\r
79 \r
80   /**\r
81   * Dictionary constructor that uses an aspell phonetic file to\r
82   * build the transformation table.\r
83   * @param wordList The file containing the words list for the dictionary\r
84   * @param phonetic The file to use for phonetic transformation of the \r
85   * wordlist.\r
86   * @throws java.io.FileNotFoundException indicates problems locating the\r
87   * file on the system\r
88   * @throws java.io.IOException indicates problems reading the words list\r
89   * file\r
90   */\r
91   public SpellDictionaryDichoDisk(File wordList, File phonetic)\r
92     throws FileNotFoundException, IOException {\r
93     super(phonetic);\r
94     dictFile = new RandomAccessFile(wordList, "r");\r
95   }\r
96   \r
97   /**\r
98   * Dictionary constructor that uses an aspell phonetic file to\r
99   * build the transformation table.\r
100   * @param wordList The file containing the words list for the dictionary\r
101   * @param phonetic The file to use for phonetic transformation of the \r
102   * wordlist.\r
103   * @param encoding Uses the character set encoding specified\r
104   * @throws java.io.FileNotFoundException indicates problems locating the\r
105   * file on the system\r
106   * @throws java.io.IOException indicates problems reading the words list\r
107   * file\r
108   */\r
109   public SpellDictionaryDichoDisk(File wordList, File phonetic, String encoding)\r
110     throws FileNotFoundException, IOException {\r
111     super(phonetic, encoding);\r
112     this.encoding = encoding;\r
113     dictFile = new RandomAccessFile(wordList, "r");\r
114   }\r
115   \r
116   /**\r
117    * Add a word permanently to the dictionary (and the dictionary file).\r
118    * <i>not implemented !</i>\r
119    * @param word The word to add.\r
120    */\r
121   public void addWord(String word) {\r
122     System.err.println("error: addWord is not implemented for SpellDictionaryDichoDisk");\r
123   }\r
124 \r
125   /**\r
126     * Search the dictionary file for the words corresponding to the code\r
127     * within positions p1 - p2\r
128     */\r
129    @SuppressWarnings("unchecked")\r
130 private LinkedList dichoFind(String code, long p1, long p2) throws IOException {\r
131      //System.out.println("dichoFind("+code+","+p1+","+p2+")");\r
132      long pm = (p1 + p2) / 2;\r
133     dictFile.seek(pm);\r
134     String l;\r
135     if (encoding == null)\r
136       l = dictFile.readLine();\r
137     else\r
138       l = dictReadLine();\r
139     pm = dictFile.getFilePointer();\r
140     if (encoding == null)\r
141       l = dictFile.readLine();\r
142     else\r
143       l = dictReadLine();\r
144     long pm2 = dictFile.getFilePointer();\r
145     if (pm2 >= p2)\r
146       return(seqFind(code, p1, p2));\r
147     int istar = l.indexOf('*');\r
148     if (istar == -1)\r
149       throw new IOException("bad format: no * !");\r
150     String testcode = l.substring(0, istar);\r
151     int comp = code.compareTo(testcode);\r
152     if (comp < 0)\r
153       return(dichoFind(code, p1, pm-1));\r
154     else if (comp > 0)\r
155       return(dichoFind(code, pm2, p2));\r
156     else {\r
157       LinkedList l1 = dichoFind(code, p1, pm-1);\r
158       LinkedList l2 = dichoFind(code, pm2, p2);\r
159       String word = l.substring(istar+1);\r
160       l1.add(word);\r
161       l1.addAll(l2);\r
162       return(l1);\r
163     }\r
164    }\r
165    \r
166    @SuppressWarnings("unchecked")\r
167 private LinkedList seqFind(String code, long p1, long p2) throws IOException {\r
168      //System.out.println("seqFind("+code+","+p1+","+p2+")");\r
169      LinkedList list = new LinkedList();\r
170     dictFile.seek(p1);\r
171     while (dictFile.getFilePointer() < p2) {\r
172       String l;\r
173       if (encoding == null)\r
174         l = dictFile.readLine();\r
175       else\r
176         l = dictReadLine();\r
177       int istar = l.indexOf('*');\r
178       if (istar == -1)\r
179         throw new IOException("bad format: no * !");\r
180       String testcode = l.substring(0, istar);\r
181       if (testcode.equals(code)) {\r
182         String word = l.substring(istar+1);\r
183         list.add(word);\r
184       }\r
185     }\r
186     return(list);\r
187    }\r
188    \r
189    /**\r
190      * Read a line of dictFile with a specific encoding\r
191      */\r
192    private String dictReadLine() throws IOException {\r
193      int max = 255;\r
194      byte b=0;\r
195     byte[] buf = new byte[max];\r
196     int i=0;\r
197      try {\r
198        for (; b != '\n' && b != '\r' && i<max-1; i++) {\r
199         b = dictFile.readByte();\r
200          buf[i] = b;\r
201       }\r
202     } catch (EOFException ex) {\r
203     }\r
204     if (i == 0)\r
205       return("");\r
206     String s = new String(buf, 0, i-1, encoding);\r
207     return(s);\r
208    }\r
209    \r
210   /**\r
211    * Returns a list of strings (words) for the code.\r
212    * @param code The phonetic code common to the list of words\r
213    * @return A list of words having the same phonetic code\r
214    */\r
215   @Override\r
216 @SuppressWarnings("unchecked")\r
217 public List getWords(String code) {\r
218      //System.out.println("getWords("+code+")");\r
219     LinkedList list;\r
220     try {\r
221       list = dichoFind(code, 0, dictFile.length()-1);\r
222       //System.out.println(list);\r
223     } catch (IOException ex) {\r
224       System.err.println("IOException: " + ex.getMessage());\r
225       list = new LinkedList();\r
226     }\r
227     return list;\r
228   }\r
229 \r
230 }\r
231 \r