/ Forside / Teknologi / Udvikling / Java / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Java
#NavnPoint
molokyle 3688
Klaudi 855
strarup 740
Forvirret 660
gøgeungen 500
Teil 373
Stouenberg 360
vnc 360
pmbruun 341
10  mccracken 320
[Eng] Jar-files and pictures; network; App~
Fra : Martin Schou


Dato : 11-04-02 10:29

Pardon the cross-post, and I'm very sorry if I've posted to a wrong group,
but I'm going nuts here!

I'm having two very persistant problems with an applet I'm working on, and I
have a feeling, that they're related.

What I'm using:

JRE:
- Internet Explorer 5.0, JRE 1.1 by Microsoft
- Opera 6.01, JRE 1.4.0 by Sun

JDK:
- Sun JDK 1.4.0
- Compiling for 1.1 with:
javac -target 1.1 class.java

IDE:
- NetBeans IDE 3.3.1

Jar:
- Created jar-file with NetBeans; compiling jar-file in NetBeans


Rough description of applets function:

Log on to telnet-type server, query for values, show values on screen with
relevant images (loaded from jar-file), change values on screen, send
changes to telnet-type server.

No need to get into the nitty gritty details

I have two problems:

1) Loading images from the jar-file
2) Talking to the telnet-type server

=============================================================
Problem number 1:
- Loading images from the jar-file.


On startup, the browser downloads the 50 kbyte jar-file (duh!).
Let's call the applets main-class "MainAppletClass"

MainAppletClass.init() looks like this (relevant items only):
{
Originator = getClass();
Tk = Toolkit.getDefaultToolkit();
/*setSize( 700, 550 );*///Frame
initImages();
}

initImages()
{
MainPanel.picture1 = defineImage( "picture1.gif" );
/*[...]*/
}

Image defineImage( String Location )
{
Image imageToManipulate = loadImage( imageDirectory + Location );
return imageToManipulate;
}


This method is the problem. I have two different ways of using it, and it
gives two different results in Opera, but both works fine in Internet
Explorer.

I started out with this piece of code:

public Image loadImage( String adresse )
{
URL url = null;
Image tempImage = null;
try
{
InputStream in = Originator.getResourceAsStream( adresse );
if (in == null)
{
System.out.println( "Intet billede: " + adresse );
System.out.println( "\n\r" );
return null;
}
byte[] buffer = new byte[in.available()];
in.read(buffer);
System.out.println( adresse + " - " + buffer.length + "\n\r");
tempImage = Tk.createImage( buffer );
}
catch (IOException e)
{
e.printStackTrace();
}
catch( NullPointerException E )
{
E.printStackTrace();
}
catch( Exception E )
{
System.out.println( adresse );
E.printStackTrace();
}
return tempImage;
}

This resulted in the following images:

picture01.gif - real size: 953 bytes. (Shown)
picture02.gif - real size: 953 bytes. (Shown)
picture03.gif - real size: 6915 bytes. (Not shown)
picture04.gif - real size: 1035 bytes. (Shown)
picture05.gif - real size: 1041 bytes. (Shown)
picture06.gif - real size: 1042 bytes. (Shown)
picture07.gif - real size: 888 bytes. (Shown with serious errors)
picture08.gif - real size: 888 bytes. (Shown with serious errors)
picture09.gif - real size: 992 bytes. (Shown)
picture10.gif - real size: 974 bytes. (Shown)
picture11.gif - real size: 977 bytes. (Shown)
picture12.gif - real size: 958 bytes. (Shown)
picture13.gif - real size: 1054 bytes. (Shown with serious errors)
picture14.gif - real size: 1079 bytes. (Shown with serious errors)
picture15.gif - real size: 1028 bytes. (Shown with serious errors)
picture16.gif - real size: 1057 bytes. (Shown with serious errors)
picture17.gif - real size: 1051 bytes. (Shown with serious errors)
picture18.gif - real size: 1082 bytes. (Shown with serious errors)
picture19.gif - real size: 1030 bytes. (Shown with serious errors)
picture20.gif - real size: 1057 bytes. (Shown with serious errors)
picture21.gif - real size: 952 bytes. (Shown)
picture22.gif - real size: 926 bytes. (Shown)
picture23.gif - real size: 952 bytes. (Shown)

Seeing that some images didn't get shown properly, I _thought_ my problem
was one of timing, so I changed my tactic a bit and decided to keep reading
from the InputStream until it was empty. The following piece of code does
that:

public Image loadImage( String adresse )
{
URL url = null;
Image tempImage = null;
try
{
InputStream in = Originator.getResourceAsStream( adresse );
if (in == null)
{
return null;
}
byte[] buffer = new byte[0];
byte[] tempArray = new byte[0];
int offset = 0;
while( (tempArray = new byte[in.available()]).length > 0 )
{
in.read(tempArray);
byte[] tempBuffer = buffer;
buffer = new byte[tempBuffer.length + tempArray.length];
for( int index = 0 ; index < tempBuffer.length ; index++ )
{
buffer[index] = tempBuffer[index];
}

for( int index = 0 ; index < tempArray.length ; index++ )
{
buffer[index + tempBuffer.length] = tempArray[index];
}
Thread.sleep( 100 );
}
tempImage = Tk.createImage( buffer );
}
catch (IOException e)
{
e.printStackTrace();
}
catch( NullPointerException E )
{
E.printStackTrace();
}
catch( Exception E )
{
E.printStackTrace();
}
return tempImage;
}

Here's an output of the file sizes of the images I use, and how big Opera
thinks they are (this result doesn't change):

picture01.gif - real size: 953 bytes. Loaded as: 1906 bytes (2x) (Shown)
picture02.gif - real size: 953 bytes. Loaded as: 1906 bytes (2x) (Shown)
picture03.gif - real size: 6915 bytes. Loaded as: 103725 bytes (15x) (Not
shown)
picture04.gif - real size: 1035 bytes. Loaded as: 2070 bytes (2x) (Shown)
picture05.gif - real size: 1041 bytes. Loaded as: 2082 bytes (2x) (Shown)
picture06.gif - real size: 1042 bytes. Loaded as: 2084 bytes (2x) (Shown)
picture07.gif - real size: 888 bytes. Loaded as: 2664 bytes (3x) (Shown
with serious errors)
picture08.gif - real size: 888 bytes. Loaded as: 2664 bytes (3x) (Shown
with serious errors)
picture09.gif - real size: 992 bytes. Loaded as: 1984 bytes (2x) (Shown)
picture10.gif - real size: 974 bytes. Loaded as: 1948 bytes (2x) (Shown)
picture11.gif - real size: 977 bytes. Loaded as: 1954 bytes (2x) (Shown)
picture12.gif - real size: 958 bytes. Loaded as: 1916 bytes (2x) (Shown)
picture13.gif - real size: 1054 bytes. Loaded as: 3162 bytes (3x) (Shown
with serious errors)
picture14.gif - real size: 1079 bytes. Loaded as: 3237 bytes (3x) (Shown
with serious errors)
picture15.gif - real size: 1028 bytes. Loaded as: 3084 bytes (3x) (Shown
with serious errors)
picture16.gif - real size: 1057 bytes. Loaded as: 3171 bytes (3x) (Shown
with serious errors)
picture17.gif - real size: 1051 bytes. Loaded as: 3153 bytes (3x) (Shown
with serious errors)
picture18.gif - real size: 1082 bytes. Loaded as: 3246 bytes (3x) (Shown
with serious errors)
picture19.gif - real size: 1030 bytes. Loaded as: 3090 bytes (3x) (Shown
with serious errors)
picture20.gif - real size: 1057 bytes. Loaded as: 3171 bytes (3x) (Shown
with serious errors)
picture21.gif - real size: 952 bytes. Loaded as: 1904 bytes (2x) (Shown)
picture22.gif - real size: 926 bytes. Loaded as: 1852 bytes (2x) (Shown)
picture23.gif - real size: 952 bytes. Loaded as: 1904 bytes (2x) (Shown)


If you're confused, don't worry - so am I, and I'm supposed to know how this
works, since I wrote it ...


=============================================================

Problem number 2:
- Talking to the telnet-type server



Here Opera passes with flying colours, and Internet Explorer is driving me
nuts.

The sequence for logging in goes like any regular telnet server:

---------------------

Connect.

Receive: "TELDATA/2.0 server ready."
Receive: "Login:"

Send: [username]
Receive: "Password:"

Send: [password]
Receive: "Hello."

---------------------

Like I said, Opera does this without a hitch, but Internet Explorer stumbles
before it gets out the gate:

Operas output goes like this (I put in the byte-variables for reference):

---------------------

Connect

"TELDATA/2.0 server ready."
[84][69][76][68][65][84][65][47][50][46][48][32][115][101][114][118][101][11
4][32][114][101][97][100][121][46][13][10]

"Login:" [76][111][103][105][110][58][13][10]

Send login

"Password:" [80][97][115][115][119][111][114][100][58][13][10]

Send password

"Hello." [72][101][108][108][111][46][13][10]

---------------------


Internet Explorer does this:

---------------------

Connect

"TELDATA/2.0 server ready."
[84][69][76][68][65][84][65][47][50][46][48][32][115][101][114][118][101][11
4][32][114][101][97][100][121][46][13][10]
"Login:" [76][111][103][105][110][58][13][10]

Send login

Recieve data:

[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][
0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]

Ad infinitum.

---------------------

This is obviously not what is supposed to happen.

My Connector-class looks like this (I'm just posting the relevant methods):



public void Send( String Message, boolean EndLine )
{
byte[] message = Message.getBytes();
try
{
DataOut.writeBytes( Message );
if ( EndLine )
{
SendEndLine();
}
}
catch( Exception E )
{
E.printStackTrace();
}
}

public void SendEndLine()
{
try
{
byte cariageReturn = new String( "\r" ).getBytes()[0];
byte lineFeed = new String( "\n" ).getBytes()[0];
DataOut.writeByte( cariageReturn );
DataOut.writeByte( lineFeed );
}
catch( Exception E )
{
Error( "Error in ConnectionClass.SendEndLine(): " +
E.getMessage() );
}
}

public byte[] ReadAvailable()
{
byte[] tempByteArray = null;
try
{
int numberOfBytes = DataIn.available();
tempByteArray = new byte[ numberOfBytes ];
DataIn.read( tempByteArray, 0, numberOfBytes );
}
catch( IOException E )
{
Error( E.getMessage() );
Sleep( 100 );
return tempByteArray;
}


In my data-model I simply call the ReadAvailable()-method and query the size
of the byte array:


public void ConnectMåler()
{
String tempStorage = "";
byte[] tempArray = new byte[0];
Måler = new Connector();
Måler.Connect( Host, 24 );
/* At this point in time, I don't have to worry about getting mixed
signals, so I can just "fast forward" until the inputstream is empty */

while( Måler.ReadAvailable().length > 0 )
{
Måler.Sleep( 10 );
}

tempStorage = "";
Måler.Send( "login", true );//not true login
/* Still "fast forwarding" */

while( Måler.ReadAvailable().length > 0 )
{
Måler.Sleep( 10 );
}

tempStorage = "";
Måler.Send( "password", true );//not true password, but I _AM_ stupid
enough to use it
/* Still "fast forwarding" */

while( Måler.ReadAvailable().length > 0 )
{
Måler.Sleep( 10 );
}
tempStorage = "";
tempStorage = null;

/* I'm now connected to my server, and can go about my business as
usual. */
}


=============================================================

Still here? Wow.

Anyways, to cut a long story short (woops, too late for that), I could
REALLY use your help. If you don't know what's wrong, but think you know,
where I can read about it, please point it out to me. I do have the
documentation for both JDK 1.1 and 1.4.0; I have tried using google, but it
didn't do me much good; I have also tried out javasoft, also with no luck.
If you want me to look at some of those pages, please tell me exactly what
article(s), don't bother telling me to go to http://www.javasoft.com or Suns
knowledgebase, or that Google is my friend, because frankly, friends help
you move, real friends help you move bodies, but Google haven't helped me
move anything except a bookmark to my favorite search engine.


Sincerely, desperately and all out crazy

Martin Schou

Denmark



 
 
Jon Skeet (11-04-2002)
Kommentar
Fra : Jon Skeet


Dato : 11-04-02 11:28

Martin Schou <Martin.Schou@Grue-Hornstrup.dk> wrote:
> Pardon the cross-post, and I'm very sorry if I've posted to a wrong group,
> but I'm going nuts here!

I've removed comp.lang.java, as that isn't a valid newsgroup and hasn't
been for years.

> I'm having two very persistant problems with an applet I'm working on, and I
> have a feeling, that they're related.
> initImages()
> {
> MainPanel.picture1 = defineImage( "picture1.gif" );

Yuk - use accessor methods rather making the variable available here.

> byte[] buffer = new byte[in.available()];
> in.read(buffer);

Both of these lines are bad. Firstly, you don't know that in.available()
is going to return the whole file, and secondly, in.read() isn't
guaranteed to read for a whole buffer. You're ignoring its return value.

See IOUtil at http://www.pobox.com/~skeet/java/skeetutil for some code
to read a stream completely.

Note that you're also not closing the input stream. That should be done
within a finally block.

> System.out.println( adresse + " - " + buffer.length + "\n\r");
> tempImage = Tk.createImage( buffer );
> }
> catch (IOException e)
> {
> e.printStackTrace();
> }
> catch( NullPointerException E )
> {
> E.printStackTrace();
> }

You should try to pick a naming convention and stick to it. I suggest
using Sun's - so all of the variables and methods should start with a
lower-case letter.

Catching NullPointerException is very rarely a good idea

> public void Send( String Message, boolean EndLine )
> {
> byte[] message = Message.getBytes();

Never use String.getBytes() - use String.getBytes (String), ie
specifying an encoding. Use the same encoding as the server will
understand.

> catch( Exception E )
> {
> E.printStackTrace();
> }
> }

Catching bare Exception is almost never a good thing to do - if you want
to catch everything, use Throwable. If you don't, catch specific
exceptions.

> public void SendEndLine()
> {
> try
> {
> byte cariageReturn = new String( "\r" ).getBytes()[0];

new String (String) is almost never required, and certainly isn't
required here. Why not just use DataOut.writeByte ('\r'); in the first
place though?

> public byte[] ReadAvailable()
> {
> byte[] tempByteArray = null;
> try
> {
> int numberOfBytes = DataIn.available();
> tempByteArray = new byte[ numberOfBytes ];
> DataIn.read( tempByteArray, 0, numberOfBytes );
> }
> catch( IOException E )
> {
> Error( E.getMessage() );
> Sleep( 100 );
> return tempByteArray;
> }

Aside from the problems I mentioned earlier, why do you have a call to
sleep here?

> public void ConnectMåler()
> {
> String tempStorage = "";

You never seem to use this variable.

> tempStorage = "";
> Måler.Send( "login", true );//not true login
> /* Still "fast forwarding" */
>
> while( Måler.ReadAvailable().length > 0 )
> {
> Måler.Sleep( 10 );
> }

Why are you ignoring what's coming back?

> tempStorage = "";
> tempStorage = null;

These two lines are unnecessary, even if tempStorage was being used
somewhere.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too

Martin Schou (11-04-2002)
Kommentar
Fra : Martin Schou


Dato : 11-04-02 12:21

Well, most of this is prototyping - basicaly learning by doing, so don't
worry - I have no intentions of doing stuff like "talk to strangers" etc.
Most of this stuff was basicaly made to function with pictures stored on the
webserver, but that won't work, when they're stored in a jar-file, so I just
made the variables public instead of using set/get

Basically this goes for just about every "no no" you mention, including the
lack of a code-standard.

There's no need to nitpick on those, since basicaly everything will be
rewritten using "good" code.

Anyways, on to the good stuff

"Jon Skeet" <skeet@pobox.com> skrev i en meddelelse
news:MPG.171f759e31230a3398af97@dnews.peramon.com...
> Martin Schou <Martin.Schou@Grue-Hornstrup.dk> wrote:

> > byte[] buffer = new byte[in.available()];
> > in.read(buffer);
>
> Both of these lines are bad. Firstly, you don't know that in.available()
> is going to return the whole file, and secondly, in.read() isn't
> guaranteed to read for a whole buffer. You're ignoring its return value.
>
> See IOUtil at http://www.pobox.com/~skeet/java/skeetutil for some code
> to read a stream completely.
>
> Note that you're also not closing the input stream. That should be done
> within a finally block.

Hmm, hadn't really thought about that. I'll give that a try, 'cause it
sounds plausible

> > catch( NullPointerException E )
> > {
> > E.printStackTrace();
> > }
>
> Catching NullPointerException is very rarely a good idea

When trying to prototype my way through a problem, it probably is; I need to
know _why_ the NullPointer is thrown, so that I can avoid it. Ie, when an
Image fails to load, and I return it to another class, if I don't catch the
exception, I'm screwed - but you knew that

> > public void Send( String Message, boolean EndLine )
> > {
> > byte[] message = Message.getBytes();
>
> Never use String.getBytes() - use String.getBytes (String), ie
> specifying an encoding. Use the same encoding as the server will
> understand.

Did not know that. Will do that from now on.

> > catch( Exception E )
> > {
> > E.printStackTrace();
> > }
> > }
>
> Catching bare Exception is almost never a good thing to do - if you want
> to catch everything, use Throwable. If you don't, catch specific
> exceptions.

See NullPointerException above

> > public void SendEndLine()
> > {
> > try
> > {
> > byte cariageReturn = new String( "\r" ).getBytes()[0];
>
> new String (String) is almost never required, and certainly isn't
> required here. Why not just use DataOut.writeByte ('\r'); in the first
> place though?
>
> > public byte[] ReadAvailable()
> > {
> > byte[] tempByteArray = null;
> > try
> > {
> > int numberOfBytes = DataIn.available();
> > tempByteArray = new byte[ numberOfBytes ];
> > DataIn.read( tempByteArray, 0, numberOfBytes );
> > }
> > catch( IOException E )
> > {
> > Error( E.getMessage() );
> > Sleep( 100 );
> > return tempByteArray;
> > }
>
> Aside from the problems I mentioned earlier, why do you have a call to
> sleep here?

I think it's a leftover, from when I was using a continuous loop, and I
didn't want to hog the cpu. In this piece of code, it's a couple of bytes
that I could use later (I'm working on a VERY restricted environment, with
256 kilobytes for EVERYTHING).

>
> > public void ConnectMåler()
> > {
> > String tempStorage = "";
>
> You never seem to use this variable.

Leftover from earlier. Will be scrapped in final edition, but thank you for
pointing it out.

> > tempStorage = "";
> > Måler.Send( "login", true );//not true login
> > /* Still "fast forwarding" */
> >
> > while( Måler.ReadAvailable().length > 0 )
> > {
> > Måler.Sleep( 10 );
> > }
>
> Why are you ignoring what's coming back?

I'm "fastforwarding". I already _know_ what's comming back, "Password:", so
there's no need to analyze it.

> > tempStorage = "";
> > tempStorage = null;
>
> These two lines are unnecessary, even if tempStorage was being used
> somewhere.

That is correct. If I use tempStorage and move its contents to some other
variable, I will probably be screwed big time. Took me two weeks to track
that down, when I did it to an array. Thanks!

> --
> Jon Skeet - <skeet@pobox.com>
> http://www.pobox.com/~skeet/

Thank you for the usefull input, even the things I knew in advance - this is
after all supposed to be a help to others, with similar problems, and if
they can learn from my mistakes - good for them.

Martin Schou



MistWing SilverTail (12-04-2002)
Kommentar
Fra : MistWing SilverTail


Dato : 12-04-02 01:42

> Catching NullPointerException is very rarely a good idea

Why? Quite often, if I don't catch it, I get a compiler error saying that I
didn't catch it


--

MistWing SilverTail

Dragon Code
DC2.Dw Gf L6m3t5w W- T Phfwlt Sks,wl Cau+,bau,bl' Bfl/pl/zz A- Fr+++ Nn
M O/ H--- $ Fo R- Ac+ J+ S+ U! I--# V+++![Power] V---[Control] V++[Food
Fight Magic ++] Q+++[tk] Tc+++[sw] Tc+[other]

Furry Code
FMSmpsw3r A-- C- D H+ M- P R+ T+++ W- Z+ S- RLCT ca++$ d-- e+ f- h- i+
j+ p-- sx--




Lars Mosegård (12-04-2002)
Kommentar
Fra : Lars Mosegård


Dato : 12-04-02 17:41


"MistWing SilverTail" <MistWing@erols.com> skrev i en meddelelse
news:a95a6r$bgd$1@bob.news.rcn.net...
> > Catching NullPointerException is very rarely a good idea
>
> Why? Quite often, if I don't catch it, I get a compiler error saying that I
> didn't catch it
>
No!
java.lang.NullPointerException is a subclass of java.lang.RuntimeException, so
you will get no complaints from the compiler.

Lars



Roedy Green (12-04-2002)
Kommentar
Fra : Roedy Green


Dato : 12-04-02 18:46

On Fri, 12 Apr 2002 18:40:42 +0200, "Lars Mosegård"
<lamos@FJERNpost8.tele.dk> wrote or quoted :

>No!
>java.lang.NullPointerException is a subclass of java.lang.RuntimeException, so
>you will get no complaints from the compiler.

When do you need catch and when don't you? For a giant list see
http:/mindprod.com/jglosse.html#EXCEPTION

Browsing the list will gel your intuition.


--
The answers to most Java questions are in the
Java glossary indexed and cross-indexed by keyword.
It is usually faster to look them up there than ask
here and wait for a response. See:
http://www.mindprod.com/jgloss.html
or http://209.139.205.39/jagg.html

-
eagerly seeking telecommuting programming work.
canadian mind products, roedy green

Søg
Reklame
Statistik
Spørgsmål : 177501
Tips : 31968
Nyheder : 719565
Indlæg : 6408522
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste