|
| String index out of bounds Fra : Hancater |
Dato : 18-10-02 08:26 |
|
Hej ng.
Jeg sidder og roder med en algoritme til at gennemløbe en String.
Denne String indeholder et XML-dokument, som skal gemmes i en
database. Men inden den kan gemmes skal den fremstå i een lang streng,
uden indrykninger, tab, return og linieskift. Derfor skal vi teste på om der
efter
tegnet '>' er indrykning - altså et 'white space'.
Dette forsøges i nedenstående kode, men jeg får fejlen:
java.lang.StringIndexOutOfBoundsException: String index out of range.....
Her er koden:
public String lavXMLdokument(String xmlDok) {
boolean outputStatus = true;
String udenReturn = "";
String udenLinieSkift = "";
String udenTab = "";
String dokument = "";
StringTokenizer st = new StringTokenizer(xmlDok, "\r");
while (st.hasMoreTokens()) {
udenReturn = udenReturn+st.nextToken();
}
StringTokenizer st2 = new StringTokenizer(udenReturn, "\n");
while (st2.hasMoreTokens()) {
udenLinieSkift = udenLinieSkift+st2.nextToken();
}
StringTokenizer st3 = new StringTokenizer(udenLinieSkift, "\t");
while (st3.hasMoreTokens()) {
udenTab = udenTab+st3.nextToken();
}
for (int i = 0; i < udenTab.length(); i++) {
if (udenTab.charAt(i) == '>')
if (udenTab.charAt(i+1) == ' ')
outputStatus = false;
else if (outputStatus == false)
if (udenTab.charAt(i) == '<')
outputStatus = true;
else if (outputStatus == true)
dokument = dokument+udenTab.charAt(i);
}
return dokument;
}
Håber der er nogle der kan hjælpe med hvad der er galt......
På forhånd tak.
| |
Morten Hougs (18-10-2002)
| Kommentar Fra : Morten Hougs |
Dato : 18-10-02 09:26 |
|
I din "for" lykke checker du på i+1... hvis "i" peger på det sidste element
i "udenTab" strengen, er det nok her det går galt?
Der må stå et linie nummer i din stacktrace - her kan du spore præcis hvor
din StringIndexOutOfBoundsException bliver smidt.
/Morten
> Her er koden:
>
> public String lavXMLdokument(String xmlDok) {
> boolean outputStatus = true;
> String udenReturn = "";
> String udenLinieSkift = "";
> String udenTab = "";
> String dokument = "";
> StringTokenizer st = new StringTokenizer(xmlDok, "\r");
> while (st.hasMoreTokens()) {
> udenReturn = udenReturn+st.nextToken();
> }
> StringTokenizer st2 = new StringTokenizer(udenReturn, "\n");
> while (st2.hasMoreTokens()) {
> udenLinieSkift = udenLinieSkift+st2.nextToken();
> }
>
> StringTokenizer st3 = new StringTokenizer(udenLinieSkift, "\t");
> while (st3.hasMoreTokens()) {
> udenTab = udenTab+st3.nextToken();
> }
>
> for (int i = 0; i < udenTab.length(); i++) {
> if (udenTab.charAt(i) == '>')
> if (udenTab.charAt(i+1) == ' ')
> outputStatus = false;
> else if (outputStatus == false)
> if (udenTab.charAt(i) == '<')
> outputStatus = true;
> else if (outputStatus == true)
> dokument = dokument+udenTab.charAt(i);
> }
> return dokument;
> }
>
>
> Håber der er nogle der kan hjælpe med hvad der er galt......
> På forhånd tak.
>
>
| |
Hancater (18-10-2002)
| Kommentar Fra : Hancater |
Dato : 18-10-02 09:31 |
|
> I din "for" lykke checker du på i+1... hvis "i" peger på det sidste
element
> i "udenTab" strengen, er det nok her det går galt?
> Der må stå et linie nummer i din stacktrace - her kan du spore præcis hvor
> din StringIndexOutOfBoundsException bliver smidt.
>
Ja, det har du nok ret i, lyder logisk.
Men du kan ikke hjælpe med selve algoritmen?
Den vil ikke som jeg......
| |
Mikkel Bundgaard (18-10-2002)
| Kommentar Fra : Mikkel Bundgaard |
Dato : 18-10-02 11:18 |
|
On Fri, 18 Oct 2002 09:26:06 +0200, Hancater wrote:
Undskyld til Hancater for den direkte mail tog fejl af F og R (tredje
gang denne uge)
> Hej ng.
> Jeg sidder og roder med en algoritme til at gennemløbe en String. Denne
> String indeholder et XML-dokument, som skal gemmes i en database. Men
> inden den kan gemmes skal den fremstå i een lang streng, uden
> indrykninger, tab, return og linieskift. Derfor skal vi teste på om der
> efter tegnet '>' er indrykning - altså et 'white space'.
Hvad mener du med indrykning efter tegnet >. Der findes vel kun
indrykning før < ???
<recipe id="117" category="dessert">
<description>Rhubarb Cobbler made with bananas...</description>
<ingredients>
<item>
<amount>2 1/2 cups</amount>
<type>diced rhubarb</type>
</item>
</ingredients>
</recipe>
<SNIP kode>
Det ser ud som om du kun er interesseret i elementerne og ikke deres
indhold. Er det det du ønsker. Skal attributter også udskrives eller hur ?
> Håber der er nogle der kan hjælpe med hvad der er galt...... På forhånd
> tak.
Vi skal nok hælpe, men du skal først forklare _præcist_, hvad du ønsker
Skal outputtet af ovenstående eksempel være:
Rhubarb Cobbler made with bananas... 2 1/2 cups diced rhubarb
Eller
<recipe id="117" category="dessert"><description></description><ingredients>
<item><amount></amount><type></type></item></ingredients></recipe>
Eller noget helt tredje
--
Mikkel Bundgaard
Student at IT University of Copenhagen
http://officehelp.gone.dk
Codito, Ergo Sum
| |
Hancater (18-10-2002)
| Kommentar Fra : Hancater |
Dato : 18-10-02 13:16 |
|
> Undskyld til Hancater for den direkte mail tog fejl af F og R (tredje
> gang denne uge)
> > Hej ng.
> > Jeg sidder og roder med en algoritme til at gennemløbe en String. Denne
> > String indeholder et XML-dokument, som skal gemmes i en database. Men
> > inden den kan gemmes skal den fremstå i een lang streng, uden
> > indrykninger, tab, return og linieskift. Derfor skal vi teste på om der
> > efter tegnet '>' er indrykning - altså et 'white space'.
> Hvad mener du med indrykning efter tegnet >. Der findes vel kun
> indrykning før < ???
>
> <recipe id="117" category="dessert">
> <description>Rhubarb Cobbler made with bananas...</description>
> <ingredients>
> <item>
> <amount>2 1/2 cups</amount>
> <type>diced rhubarb</type>
> </item>
> </ingredients>
> </recipe>
>
> <SNIP kode>
> Det ser ud som om du kun er interesseret i elementerne og ikke deres
> indhold. Er det det du ønsker. Skal attributter også udskrives eller hur ?
>
> > Håber der er nogle der kan hjælpe med hvad der er galt...... På forhånd
> > tak.
> Vi skal nok hælpe, men du skal først forklare _præcist_, hvad du ønsker
>
>
> Skal outputtet af ovenstående eksempel være:
> Rhubarb Cobbler made with bananas... 2 1/2 cups diced rhubarb
>
> Eller
> <recipe id="117"
category="dessert"><description></description><ingredients>
> <item><amount></amount><type></type></item></ingredients></recipe>
>
> Eller noget helt tredje
> --
Tak for dit svar.
Problemet er løst
| |
Jonathan Stein (18-10-2002)
| Kommentar Fra : Jonathan Stein |
Dato : 18-10-02 12:32 |
|
Hancater wrote:
> public String lavXMLdokument(String xmlDok) {
return xmlDok.replaceAll(">[\r\n\t ]*", ">");
}
Kræver minimum version 1.4.
M.v.h.
Jonathan
--
Nyt alternativ til egen server: JSP Enterprise hotel med adgang til
Enterprise Java Beans, egen Java Virtual Machine og egen IP-adresse
(giver mulighed for eget SSL-certifikat).
http://www.jsp-hotel.dk/
| |
Ole Ildsgaard Hougaa~ (18-10-2002)
| Kommentar Fra : Ole Ildsgaard Hougaa~ |
Dato : 18-10-02 13:55 |
|
"Hancater" <nb0b@cvusyd.edu> wrote:
>Hej ng.
>Jeg sidder og roder med en algoritme til at gennemløbe en String.
>Denne String indeholder et XML-dokument, som skal gemmes i en
>database. Men inden den kan gemmes skal den fremstå i een lang streng,
>uden indrykninger, tab, return og linieskift. Derfor skal vi teste på om der
>efter
>tegnet '>' er indrykning - altså et 'white space'.
>Dette forsøges i nedenstående kode, men jeg får fejlen:
>java.lang.StringIndexOutOfBoundsException: String index out of range.....
Du skriver i et andet indlæg at du gerne vil have hjælp med
algoritmen. Jeg skal forsøge mig. Det er lidt langt, men så håber jeg
til gengæld du kan lære af det.
>Her er koden:
<klip>
> StringTokenizer st3 = new StringTokenizer(udenLinieSkift, "\t");
> while (st3.hasMoreTokens()) {
> udenTab = udenTab+st3.nextToken();
> }
Så langt, så godt. Det er ikke verdens mest effektive algoritme, men
det skulle virke. Dine problemer kommer her:
> for (int i = 0; i < udenTab.length(); i++) {
> if (udenTab.charAt(i) == '>')
> if (udenTab.charAt(i+1) == ' ')
> outputStatus = false;
> else if (outputStatus == false)
> if (udenTab.charAt(i) == '<')
> outputStatus = true;
> else if (outputStatus == true)
> dokument = dokument+udenTab.charAt(i);
> }
Det ser ud som du har tænkt sådan her på algoritmen (ret mig hvis jeg
tager fejl):
Efter hvert '>', der efterfølges af et ' ', skal der ikke gemmes
nogen tegn før der kommer et '<'.
Din if-else struktur passer bare ikke helt til den tankegang. Dit
første problem er at dine if-else sætninger ikke er grupperet som du
tror. En else knytter sig altid til den nærmeste if, og derfor burde
indmaden af din for-løkke være indrykket sådan her:
if (udenTab.charAt(i) == '>')
if (udenTab.charAt(i+1) == ' ')
outputStatus = false;
else if (outputStatus == false)
if (udenTab.charAt(i) == '<')
outputStatus = true;
else if (outputStatus == true)
dokument = dokument + udenTab.charAt(i);
Når jeg programmer, sætter jeg *alle* '{' og '}' (pånær dem mellem
"else" og "if" i en "if (...) {...} else if (...) {...}) netop for at
undgå den slags problemer (og for at øge læsevenligheden). Jeg vil
råde dig til at gøre det samme - i hvert fald indtil du kan Java
flydende.
Dit næste problem (efter du har indsat { og }) er at din sidste
else-del kun bliver kørt hvis de andre betingelser er falske. Det
kommer til at betyde at ingen af '>' og meget få af (vist kun den
første) af '<' kommer med i dokument. Hvis vi nu sætter krøllede
parenteser, garderer os mod IndexOutOfBoundException og sætter den
sidste if uden for else-delen, kommer vi tæt på noget der virker:
//ADVARSEL: Virker ikke.
if (udenTab.charAt(i) == '>') {
if (i < udenTab.length() && udenTab.charAt(i+1) == ' ') {
outputStatus = false;
}
} else if (outputStatus == false) {
if (udenTab.charAt(i) == '<') {
outputStatus = true;
}
}
if (outputStatus == true) {
dokument = dokument + udenTab.charAt(i);
}
Men ikke tæt nok. Når vi læser et '>' sætter vi outputStatus til false
før vi tester på outputStatus, så ingen '>' kommer stadig ikke med i
dokumentet. Vi skal ikke sætte outputStatus til false før vi har
outputtet '>'.
Og så er der en af mine kæpheste: Java (og C, C++ og alle de andre)
har en meget fin måde at skrive 'outputStatus == false' og
'outputStatus == true' på, nemlig hhv. '!outputStatus' og
'outputStatus'.
Vi når frem til
if (!outputStatus) {
if (udenTab.charAt(i) == '<') {
outputStatus = true;
}
}
if (outputStatus) {
dokument = dokument + udenTab.charAt(i);
}
if (udenTab.charAt(i) == '>') {
if (i < udenTab.length() && udenTab.charAt(i+1) == ' ') {
outputStatus = false;
}
}
der skulle svare til din algoritme.
Jeg har ikke gjort dig helt arbejdsløs, der er stadig et par ting (i
aftagende prioritet):
1. Din algoritme er rigeligt pladsbesparende :). Der kan godt komme
tekst imellem tags i et XML-dokument og det får du altså også ædt. Jeg
ville foreslå noget i retning af:
Efter hvert '>' skal der ikke gemmes nogen tegn før der kommer et
ikke-' '.
2. dokument = dokument + udenTab.charAt(i) er meget ineffektivt. Det
er generelt ikke en god idé at bygge Strings op vel hjælp af '+'. Brug
en StringBuffer.
3. '\f' er også whitespace.
4. En StringTokenizer kan godt have flere delimiters. Se på hvad en
StringTokenizer(s, "\r\n\f\t") kan gøre for dig.
5. En tilstrækkeligt ondsindet person (mig, for eksempel) kan godt
give eksempler på XML-filer hvor det er for aggresivt at fjerne alle
linieskift uden at sætte andet whitespace ind.
6. Man kan altid finpudse. Der er et par overflødige betingelser og
sådan.
Nu er det vel kun en opgave og ikke et styresystem til den nye Metro,
så du kan jo vurdere hvor meget du vil gøre ved det (det første bør du
nu rette). Hvis du er interesseret, kan jeg lave en implementation som
jeg selv mener har professionel kvalitet. (Andre mener måske noget
andet).
>Håber der er nogle der kan hjælpe med hvad der er galt......
Håber det hjalp.
>På forhånd tak.
Velbekomme.
--
Ole I. Hougaard
oih@get2net.dk
| |
Hancater (21-10-2002)
| Kommentar Fra : Hancater |
Dato : 21-10-02 09:35 |
|
Tak for dit svar.
Der var meget brugbart i det....
Vi har nu fået det til at virke, men som du selv er inde på,
kunne koden være bedre. Rart at få nogle basale ting på plads.
Hvis du har lyst, må du da gerne rode med en 'professionel version',
som vi så måske kan implementere i vores applikation.
| |
|
|