From b88f0117c6a4792902d8eebe82b3c5fda386e6eb Mon Sep 17 00:00:00 2001 From: thadh Date: Mon, 9 Feb 2009 21:33:33 -0800 Subject: [PATCH] go --- AndroidManifest.xml | 15 ++ res/drawable/icon.png | Bin 0 -> 3180 bytes res/layout/main.xml | 11 ++ res/values/strings.xml | 5 + .../hughes/android/dictionary/Dictionary.java | 130 ++++++++++++++++++ src/com/hughes/android/dictionary/Entry.java | 47 +++++++ src/com/hughes/android/dictionary/Index.java | 81 +++++++++++ src/com/hughes/android/dictionary/R.java | 27 ++++ 8 files changed, 316 insertions(+) create mode 100755 AndroidManifest.xml create mode 100755 res/drawable/icon.png create mode 100755 res/layout/main.xml create mode 100755 res/values/strings.xml create mode 100755 src/com/hughes/android/dictionary/Dictionary.java create mode 100755 src/com/hughes/android/dictionary/Entry.java create mode 100755 src/com/hughes/android/dictionary/Index.java create mode 100755 src/com/hughes/android/dictionary/R.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100755 index 0000000..640d31d --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/icon.png b/res/drawable/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..75024841d327c4fbaefef7c8e9c8d0e892895f93 GIT binary patch literal 3180 zcmV-y43qPTP)-8%y z>?Lk&?1bQy00olTw5rOVwrM3QR77j2sF13vY1JS6sbZvxR;?=9{z8-xlkf-)&`7j@ zLPDIDmN(g8j2*{G>^OcucGvIhdUtxhGxyHUj@Mv*5J2jUj_=Ifnc4H5^PR_?jbWN5 zeUXQUzTo5k06yzs=!5%z{F9Jj7?1K{fTfRP;}p;BPws!b?{g2}k>CBkB{CIxbbfw5 zu&}U@aRCDXfOeKMEa3xB{pG?UJCJiQ7-_%)Z`S)Bu!3D(!%^gw)?^i4ZzND z5(~p)Pqpn2e^vmRc|IAcuA-ZF-YARX;}bMCF~RdV4Gs+pnCaHjJMX;HJ`Mx|A^?UlH$P8vbMxY*I4ckEIFH6+3?ya&Vy|ILPE5)y>q`lz z(_B8xIJ@terw_J$tOrz}(uKZ0DladihaP%}Mn*=ckIx$$8|ksf9uwu9W8J!S0tPdr zzOI(?^78D@alHj9W`m2z6ZWy?t(aVk<50es@0~tF16|#;?eG!uFD%mZ z#`P4b*-V3VTj<2GSHx4#J^Qq=S`UPC{Ql=jJHF3PH~H^w2ExJU@Re6|BvdxuT*%xZB*^{E4!MslIov^*2=VdbYw{>%ralpXsBTJONzHA^PWkyFn>KDF+S*{>I65{i;Ks(rv|-?F(4K05;!qqVhF00Nx$ zk~8}(qlwFkLKy&LVDJ_|m|ufT|5nP)=aFA=D{W&!eNG z@;#V!b$1SU><9PUBi95=OF0HoG%+zzg946vhsUzaSpAi(U13T2?3S4^Ad|rI5NTAH z|5`L4&3_HXO*hFR4sdmKb<1dk*#b8zhQzUe;`Ozhxe&m(hTHp)vU*Y}48?KNfSMNt z!2LhEw{QP}r|1d;&=u8bbtg@-E#<`$MVFMKQ?c4f!Xt5?Rt}uA+T}SqeE6_fS9?Q)a9dl)0xYhr zsI!-oCiwh;2Od!LbH`$u{{R8S;eixWsIahb1Aow?F7ztFC}Sx=HnsuqO}vey5EOp! z!3XWu;Egxlu!GSlPUSRJ+;njQk-&9OC?n09P7tQ;fh@($qd@rde%|4MRNu_ZOh{W= zH)FbSg8-DyG61O?J7gGVP0(MAH8*vZ&q{eSO(UPrrvPN_KvF8Gk&R5J2kib`j~JiN zaM39VmeRIu+vLGIv%sR@JwWN2paWc|N}W0}BQDG=l+kKA*9r@Zcup!j4!^kxN-EC1( zu|i-e@8=!~6iTJCQpi+_qv|eZ0N}jaKQ?Z)umhI|X@Uc~h}&8y4A1nOJ4dCZB~)Hk zh6*VU_jo+ieYQvXoM1_S>gyXQC&zD7LQ@2Qa5_4gjtN6TI*_Ii5bK8zvo){ZwpB{LVHnbk#drsG;?;J-=HKHnC>RV%;hW=qF@Su?o0HS0 z!}Rs9-9cq#rK;01$iq@qRV~U@RaMyv@7lF1&40xqQxVLvehS_QWTDTDl0?RvIliF} zRKeK5T_SpN>v5*lN|O{8di$MsS>B^J-+D*7&UMUhSnLXe$Nu<kc$4Nfg}e9%dpsf1Qi zCwMQ6zzzh8s37^IMOnB$t{q7M|0C>og= zX_Uu4D0XRJfbt6pWVhw>dTkKJtiVZEu7FvWS6sMG3B$oTVDL4Om0}dF?go z=;#nyO-@b;u-x1nDk$*Elgunu&*lNI*XP_5n5w0SDv4_VLZLtW@zEAmqM3t60(f+E zjO^#B>PV`v;9m&`8ot2dLArwa*&9&?H#IdSfj`d{#M=m=M3$6ED|o=?_gVL()2I&K zNfp3L86K#u-Lmh>mAKFW*1TrZMhV_D2MzUCJ<`y(TL+*9|D|Kcj&Im=;HHuUy?8C9gBMDVEB?ow6%MZ!L*^=eDCq6&<>2HE zf8{!A+|ejSi4655MzeYIwX~kA@F0T#{|mW54GoV_c||2t!Y`Y6c-JsI>9-ONt2@s@ zpOo6vD21W;mxf+R}d66yeI1D=%ho34pHmAR_f$)J2sRxo0^+sO}~}! zc)T>sAkJ|S93CE)*OAFoaz(}UggOwAf+hf<^oXL*q8osZ3s#uZ<1g5lO?>&DY}Uty z8?T$f6sh{Qo+F(6pKPhyfXz5I}jZp zkfFeRD`-t>KlN|wJ=ZG<0zH&z2SM86rfQ@0)*Z^HESXimU5sY4zPk>{*jitIlmi?4 zN81}nYdd$|NJB%zszWfOT3dl`*a2#|f*aQj4GnQ0)hjQ*Iy<`=T#0J4NoooDEoT}< z%hG>o0QU}#jgS45moBN+A-VF4E!W^)=wS}XJ#Z|>z-Tb-<}t@CpJ4{|n&R9&;_9`)FSlGI1MWHTHIQEy(%kAJo3 z{PFAkju2a;C2Ji>x$&@3+ zzhQQE_WQ}DymRL-R}*|!4ZueY2C;_~Z{(+hmlBEgtql!Py2|5!0t^7z)gsDo S`hb-H0000 + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100755 index 0000000..61f6cd4 --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,5 @@ + + + Hello World, Dictionary + Dictionary + diff --git a/src/com/hughes/android/dictionary/Dictionary.java b/src/com/hughes/android/dictionary/Dictionary.java new file mode 100755 index 0000000..52b46b4 --- /dev/null +++ b/src/com/hughes/android/dictionary/Dictionary.java @@ -0,0 +1,130 @@ +package com.hughes.android.dictionary; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.List; + +import android.app.Activity; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.TextView; + +public class Dictionary extends Activity { + + private String searchText = ""; + + private List entries = new ArrayList(100); + + public static final String INDEX_FORMAT = "%s_index_%d"; + private final File dictionaryFile = new File("/sdcard/dict-de-en.txt"); + private final Index[] indexes = new Index[2]; + private final byte lang = Entry.LANG1; + + private DictionaryListAdapter dictionaryListAdapter = new DictionaryListAdapter(); + + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + Log.d("THAD", "onCreate"); + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + EditText searchText = (EditText) findViewById(R.id.SearchText); + searchText.addTextChangedListener(new DictionaryTextWatcher()); + + ListView searchResults = (ListView) findViewById(R.id.SearchResults); + searchResults.setAdapter(dictionaryListAdapter); + + try { + loadIndex(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + } + + private void loadIndex() throws IOException, ClassNotFoundException { + Log.d("THAD", "enter loadIndex"); + indexes[0] = new Index(String.format(INDEX_FORMAT, dictionaryFile.getAbsolutePath(), Entry.LANG1)); + Log.d("THAD", "exit loadIndex"); + } + + void onSearchTextChange(final String searchText) { + this.searchText = searchText; + final Index.Node node = indexes[lang].lookup(searchText); + + try { + final long length = dictionaryFile.length(); + Log.d("THAD", "Dictionary file length=" + length); + + final RandomAccessFile raf = new RandomAccessFile(dictionaryFile, "r"); + raf.seek(length / 2); +// final InputStreamReader dictionaryReader = new InputStreamReader(new BufferedInputStream(new FileInputStream("/sdcard/dict-de-en.txt"))); +// skip(dictionaryReader, length / 2); + + for (int i = 0; i < entries.length; ++i) { + entries[i] = raf.readLine(); + raf.skipBytes((int) (length / 100000)); + } + + raf.close(); + + } catch (IOException e) { + throw new RuntimeException(e); + } + + dictionaryListAdapter.notifyDataSetChanged(); + } + + private class DictionaryListAdapter extends BaseAdapter { + + public int getCount() { + return 1000000; + + } + + public Object getItem(int position) { + return searchText + position + entries[position % entries.length]; + } + + public long getItemId(int position) { + return position; + } + + public View getView(int position, View convertView, ViewGroup parent) { + TextView result = null; + if (convertView instanceof TextView) { + result = (TextView) convertView; + } else { + result = new TextView(parent.getContext()); + } + result.setText((String) getItem(position)); + return result; + } + + } + + private class DictionaryTextWatcher implements TextWatcher { + public void afterTextChanged(Editable searchText) { + onSearchTextChange(searchText.toString()); + } + + public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, + int arg3) { + } + + public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) { + } + } + +} \ No newline at end of file diff --git a/src/com/hughes/android/dictionary/Entry.java b/src/com/hughes/android/dictionary/Entry.java new file mode 100755 index 0000000..3bb7b67 --- /dev/null +++ b/src/com/hughes/android/dictionary/Entry.java @@ -0,0 +1,47 @@ +package com.hughes.android.dictionary; + +import java.util.regex.Pattern; + +public final class Entry { + + static final byte LANG1 = 0; + static final byte LANG2 = 1; + + static final Pattern lineSplitPattern = Pattern.compile("\\s+::\\s+"); + + String lang1 = ""; + String lang2 = ""; + + boolean parseFromLine(final String line) { + final String[] parts = lineSplitPattern.split(line); + if (parts.length != 2) { + System.err.println("Entry:" + "Invalid line: " + line); + return false; + } + lang1 = parts[0]; + lang2 = parts[1]; + return true; + } + + String getAllText(final byte lang) { + if (lang == LANG1) { + return lang1; + } + assert lang == LANG2; + return lang2; + } + + String getIndexableText(final byte lang) { + String text = getAllText(lang); + text = text.replaceAll("[\"\\.!?,]", ""); + text = text.replaceAll("\\{[^}]+\\}", ""); + return text; + } + + public String normalizeToken(final String token, final byte lang) { + return token.toLowerCase().replaceAll("ß", "ss").replaceAll("ä", "ae") + .replaceAll("ö", "oe").replaceAll("ü", "ue") + .replaceAll("[^A-Za-z]", ""); + } + +} diff --git a/src/com/hughes/android/dictionary/Index.java b/src/com/hughes/android/dictionary/Index.java new file mode 100755 index 0000000..89024ff --- /dev/null +++ b/src/com/hughes/android/dictionary/Index.java @@ -0,0 +1,81 @@ +package com.hughes.android.dictionary; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Map; +import java.util.TreeMap; + +import com.hughes.util.LRUCacheMap; + + +public final class Index { + + final String filename; + final RandomAccessFile file; + + final Node root; + final Map locationToNode = new LRUCacheMap(5000); + + + public Index(final String filename) throws IOException { + this.filename = filename; + file = new RandomAccessFile(filename, "r"); + root = getNode("", 0); + } + + public Node lookup(final String text) throws IOException { + return lookup(text, 0, root); + } + + private Node lookup(final String text, final int pos, final Node n) throws IOException { + if (pos == text.length()) { + return n; + } + for (int i = pos + 1; i <= text.length(); ++i) { + final Integer child = n.children.get(text.substring(pos, i)); + if (child != null) { + return lookup(text, i, getNode(text.substring(0, i), child)); + } + } + return n; + } + + private Node getNode(final String text, final int location) throws IOException { + Node node = locationToNode.get(location); + if (node == null) { + node = new Node(text, location); + locationToNode.put(location, node); + } + return node; + } + + final class Node { + final String text; + final int location; + final TreeMap children; + final int[] offsets; + + Node(final String text, final int location) throws IOException { + this.text = text; + this.location = location; + + file.seek(location); + final int numChildren = file.readInt(); + children = new TreeMap(); + for (int i = 0; i < numChildren; ++i) { + final String chunk = file.readUTF().intern(); + if (chunk.length() == 0) { + throw new IOException("Empty string chunk."); + } + children.put(chunk, file.readInt()); + } + + final int numOffsets = file.readInt(); + offsets = new int[numOffsets]; + for (int i = 0; i < offsets.length; ++i) { + offsets[i] = file.readInt(); + } + } + } + +} diff --git a/src/com/hughes/android/dictionary/R.java b/src/com/hughes/android/dictionary/R.java new file mode 100755 index 0000000..88153f5 --- /dev/null +++ b/src/com/hughes/android/dictionary/R.java @@ -0,0 +1,27 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package com.hughes.android.dictionary; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int icon=0x7f020000; + } + public static final class id { + public static final int SearchResults=0x7f050001; + public static final int SearchText=0x7f050000; + } + public static final class layout { + public static final int main=0x7f030000; + } + public static final class string { + public static final int app_name=0x7f040001; + public static final int hello=0x7f040000; + } +} -- 2.43.0