Pitäisi saada iso (satoja megoja) tekstitiedosto (ASCII) indeksoitua. Loytyyko valmista softaa?
Ohjeman pitäisi ignoorata spacet ja pistää löydetyt stringit esiintymisjärjestykseen. Outputin pitäisi näyttää jokseenkin tältä:
auto 41200
että 39840
kissa 23098
mutta 10988
jne...
Taidot ei riitä että tekis itte...
Thanks, Timo
Ohjeman pitäisi ignoorata spacet ja pistää löydetyt stringit esiintymisjärjestykseen. Outputin pitäisi näyttää jokseenkin tältä:
auto 41200
että 39840
kissa 23098
mutta 10988
jne...
Taidot ei riitä että tekis itte...
Thanks, Timo
Vastaukset 11
Vanhimmat
eiköhän tuo mene itsestää useimilla tietokantaohjelmilla. luet sisään aineiston ja sitten luot yhteenvetoraportin?
En tiedä onko valmista, mutta tässä tekemäni Java koodi joka hoitaa asian, en tiedä onko siitä apua:
--- tiedosto alkaa (LaskijaOhjelma.java) ---
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
public class LaskijaOhjelma {
public LaskijaOhjelma() {
}
public static void main(String[] args) throws IOException {
File file = new File(args[0]);
FileInputStream fin = new FileInputStream(file);
SanaLaskuri laskuri = new SanaLaskuri();
char[] merkit = new char[1000];
int pituus = 0;
int merkki = 0;
while (merkki != -1) {
if (Character.isLetter(merkki = fin.read())) {
merkit[pituus ] = (char) Character.toLowerCase(merkki);
} else if (pituus != 0) {
laskuri.lisääSana(new String(merkit, 0, pituus));
pituus = 0;
}
}
fin.close();
ArrayList lista = laskuri.annaSanatJaMäärät();
Collections.sort(lista);
for (SanaJaMäärä sanaJaMäärä: lista)
System.out.println(sanaJaMäärä);
}
}
--- tiedosto loppuu ---
--- tiedosto alkaa (SanaLaskuri.java) ---
import java.util.ArrayList;
import java.util.HashMap;
public class SanaLaskuri {
private HashMap sanat;
public SanaLaskuri() {
sanat = new HashMap();
}
public void lisääSana(String sana) {
SanaJaMäärä sjm = sanat.get(sana);
if (sjm == null) {
sanat.put(sana, new SanaJaMäärä(sana));
} else {
sjm.kavataMäärää();
}
}
public ArrayList annaSanatJaMäärät() {
return new ArrayList(sanat.values());
}
}
--- tiedosto loppuu ---
--- tiedosto alkaa (SanaJaMäärä.java) ---
public class SanaJaMäärä implements Comparable {
private final String sana;
private int määrä;
public SanaJaMäärä(String sana) {
this.sana = sana;
this.määrä = 1;
}
public int kavataMäärää() {
return määrä;
}
public String toString() {
return sana " " määrä;
}
public int compareTo(SanaJaMäärä sanaJaMäärä) {
return sanaJaMäärä.määrä - määrä;
}
}
--- tiedosto loppuu ---
Jos saat käännettyä tuon (vaatii Java 1.5:n), niin saat sen jälkeen tulostettua listan komennolla "java LaskijaOhjelma teso.txt", jossa teso.txt sanoja sisältävän tekstitiedoston nimi. Testasin ohjelmaa 17 Mt tiedoston kanssa, niin sen läpikäynti kesti n. 15s. Tulos oli seuraava:
the 183386
and 91894
of 89362
a 71711
to 71694
i 57578
in 47558
that 42564
it 41969
was 39273
...
montant 1
hinging 1
paukahdus 1
terrorised 1
medicalschrilt 1
moissons 1
blob 1
mieltäni 1
luonaan 1
taivuksissa 1
neitsyen 1
Taisin taas käsittää kysymyksen väärin, (esimerkkisi hämäsi). Edellinen ohjelma laski vain eri sanojen esiintymismäärät ja tulosti ne lopuksi. Tässä olisi nyt varsinaisen indeksoijan lähdekoodi (joka on paljon yksinkertaisempi kuin edellinen ohjelma):
--- tiedosto alkaa (Indeksoija.java) ---
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
public class Indeksoija {
public Indeksoija() {
}
public static void main(String[] args) throws IOException {
File file = new File(args[0]);
FileInputStream fin = new FileInputStream(file);
HashMap sanat = new HashMap();
String index = null;
String sana = null;
char[] merkit = new char[1000];
int pituus = 0;
int merkki = 0;
int indexm = 0;
while (merkki != -1) {
if (Character.isLetter(merkki = fin.read())) {
merkit[pituus ] = (char) Character.toLowerCase(merkki);
} else if (pituus != 0) {
sana = new String(merkit, 0, pituus);
pituus = 0;
if ((index = sanat.get(sana)) == null) {
index = Integer.toString(indexm );
sanat.put(sana, index);
}
System.out.println(sana " " index);
}
}
fin.close();
}
}
--- tiedosto loppuu ---
Tuon voi kääntämisen jälkeen käynnistää komennolla "java Indeksoija testi.txt", jossa testi.txt on indeksoitavan teksti tiedoston nimi. 17 Mt:n tiedoston indeksointiin meni noin 25s. Ohjelma antaa siis seuran kaltaisen tuloksen:
the 0
project 1
gutenberg 2
ebook 3
of 4
the 0
adventures 5
of 4
sherlock 6
holmes 7
by 8
sir 9
arthur 10
conan 11
doyle 12
in 13
our 14
series 15
by 8
sir 9
arthur 10
conan 11
doyle 12
copyright 16
laws 17
are 18
changing 19
all 20
over 21
the 0
world 22
be 23
sure 24
to 25
check 26
the 0
...
Eka koodi on sen joka hoitaa homman jonka halusin.
Kiitos paljon, Timo
Terve,
Yritin kääntää parhaani mukaan, mutta pukkaa virheilmoitusta. Mikäköhän neuvoksi?
Kiitos, Timo
-----------------------------------------------
C:\Program Files\Java\jdk1.5.0_06\Freq anal>..\bin\javac laskijaohjelma.java san
ajamaara.java sanalaskuri.java
laskijaohjelma.java:9: class LaskijaOhjelma is public, should be declared in a f
ile named LaskijaOhjelma.java
public class LaskijaOhjelma {
^
sanajamaara.java:2: class SanaJaMaara is public, should be declared in a file na
med SanaJaMaara.java
public class SanaJaMaara implements Comparable {
^
sanalaskuri.java:6: class SanaLaskuri is public, should be declared in a file na
med SanaLaskuri.java
public class SanaLaskuri {
^
3 errors
------------------------------------------------
luokka LaskijaOhjelma on julkinen, joten se pitäisi määritellä tiedostossa nimeltä LaskijaOhjelma.java
Eli lähdekoodi pitäis olla tiedostossa, jossa tiedoston nimi vastaa juuri tuota luokan nimeä.
Nyt sulla on pienillä kirjaimilla noi luokkien nimet...
Pitää muuten olla javasta versio 1.5.0_6 että voi käyttää noita
HashMap
sulkeita noissa määrittelyissä esim.
ArrayList lista = new ArrayList();
Kuten Piru tuossa yllä neuvoi, niin olet kopioinut tiedostojen nimet väärin. Muuta tiedostojen nimet alla olevan listan mukaisesti, ja yritä kääntää sen jälkeen uudelleen.
laskijaohjelma.java => LaskijaOhjelma.java
sanalaskuri.java => SanaLaskuri.java
sanajamaara.java => SanaJaMäärä.java
Huomaa siis isot ja pienet kirjaimet sekä ääkköset. Kääntämisestä vielä sen verran, että voit kääntää tiedostot komennolla "javac *.java", jollon sun ei tarvitse hakata kaikkien tiedostojen nimiä javac:n parametriksi.
No niin, nyt kääntyy, mutta ajettaessa antaa virheen: C:\Program Files\Java\jdk1.5.0_06\Freq anal>java LaskijaOhjelma eula.txt
Exception in thread "main" java.lang.NoClassDefFoundError: LaskijaOhjelma
Mikäköhän tämän aiheuttaa?
Thanks, Timo
Viittaisi siihen ettei Java ei löydä "LaskijaOhjelma.class" tiedostoa. Tarkista että kyseisen tiedosto on hakemissa. Jos kyseinen tiedosto on kuitenkin hakemistosta, niin tällöin Java ei todennäköisesti yritä etsiä sitä siitä hakemistosta. Kokeile tällöin lisätä CLASSPATH:iin ns. tämä hakemisto (eli "."), alla olevalla komennolla:
SET CLASSPATH=.;%CLASSPATH%
Tai jollei tuo auta, niin kokeile vielä sen jälkeen ottaa koko CLASSPATH:n pois komennolla:
SET CLASSPATH=
Kiitos.
Nyt toimii ja pelittää.
-timo