Вы находитесь на странице: 1из 756

Real's HowTo PDF version.

This is the PDF version of the Real's HowTo Web site ( http://www.rgagnon.com/howto.html ).

For up−to−date content, please refer to the Web site.

There are 4 files : Real's Java , Real's Javascript, Real's Powerbuilder and Real's VBS and Misc
Prog HowTo.

Please don't make PDF versions available on the internet (it's ok in intranet)

From the PDF, you can't run the examples and the links to other How−to's are not working.

If you feel that effort has been useful to you, perhaps you will consider giving something back?

You can make a donation through PayPal at https://www.paypal.com , make you donation to
real@rgagnon.com

Contributions via PayPal are accepted in any amount using a credit card or checking account.

(Donations of any size gladly accepted)

Real's Howto copyright notice ( real@rgagnon.com )

Redistribution and use in source and binary forms,


with or without modification, are permitted provided
that the following conditions is met:

* the source code is used in a development project

Redistributions of source code or site content


(even partially) in any publications (electronic or paper)
is forbidden without permission.

DISCLAIMER

THIS SOFTWARE IS PROVIDED BY Real Gagnon "AS IS" AND ANY


EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
Real Gagnon BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Real's HowTo@www.rgagnon.com
1 Applet...............................................................................................................................................1
1.1 java−applet........................................................................................................................1
1.2 Goto to a new URL from an Applet....................................................................................1
1.3 Determine the host from where the Applet is loaded.........................................................3
1.4 Have a scrolling status line................................................................................................3
1.5 Use a search engine..........................................................................................................5
1.6 Have an on−screen clock..................................................................................................6
1.7 Have Applets on the same page communicate with each other........................................8
1.8 Have Applets on different frames communicates with each other.....................................9
1.9 Send a message from an Applet to another Applet on a different page..........................10
1.10 Have an applet launch an other applet..........................................................................12
1.11 Get the user name.........................................................................................................14
1.12 Access parameters passed in the URL..........................................................................14
1.13 Convert an Applet to Application....................................................................................16
1.14 Change the mouse cursor in Applet...............................................................................17
1.15 Use an Image as the Applet background.......................................................................17
1.16 Handle the new Control Activation mechanism in IE.....................................................18
1.16.1 Solution #1............................................................................................................19
1.16.2 Solution #2............................................................................................................19
1.16.3 Solution #3............................................................................................................20
1.17 Pass parameters to the Applet JVM (WIN)....................................................................21
1.18 See the Java Console Window Log (Java plugin).........................................................22
1.19 Display debugging infos for an Applet...........................................................................23

2 Date and Time...............................................................................................................................24


2.1 java−date.........................................................................................................................24
2.2 Have year on 4 digits from a Date object.........................................................................24
2.3 Get the current Date and Time........................................................................................24
2.4 Compute days between 2 dates......................................................................................25
2.5 Get the number of days in a month..................................................................................26
2.6 Validate a date.................................................................................................................26
2.6.1 Using DateFormat...................................................................................................26
2.6.2 Using GregorianCalendar.......................................................................................28
2.7 Determine to day of the week..........................................................................................28
2.8 Add/Substract Day/Month/Year to a Date........................................................................28
2.9 Get the correct TimeZone on DateFormat.......................................................................29
2.10 Simply format a date as "YYYYMMDD".........................................................................30
2.11 Compare 2 dates...........................................................................................................30
2.12 Parse a String to obtain a Date/GregorianCalendar object............................................31
2.13 Use System time to generate unique ID........................................................................32
2.14 Get the day name..........................................................................................................32
2.15 Find the current date format...........................................................................................33
2.16 Get a julian date.............................................................................................................33
2.17 Calculate the age...........................................................................................................35
2.18 Format a duration in ms into a string as "Days,Hours,minutes and seconds"...............36
2.19 Get the atomic time........................................................................................................38

3 AWT................................................................................................................................................40
3.1 java−awt...........................................................................................................................40
3.2 Use The CardLayout manager.........................................................................................40
3.3 Detect which card is visible with a CardLayout

Real's HowTo@www.rgagnon.com
3 AWT
3.3 Detect which card is visible with a CardLayout................................................................42
3.4 Use Popups.....................................................................................................................42
3.5 Use a File Dialog..............................................................................................................44
3.6 Use TrueType font...........................................................................................................45
3.7 Display available fonts.....................................................................................................46
3.8 Font with 3D effect...........................................................................................................47
3.9 Use the System Clipboard...............................................................................................47
3.10 Maximize a Frame.........................................................................................................48
3.11 Center a Frame/Dialog...................................................................................................49
3.12 Close a Frame...............................................................................................................50
3.13 Call events on a Frame from a Panel............................................................................51
3.14 Set the small top−left icon on a Frame..........................................................................53
3.15 Prevent a Frame to be resized.......................................................................................54
3.16 Embed an image into a Frame.......................................................................................55
3.17 Display a message box..................................................................................................57
3.18 Display a Splash screen................................................................................................58
3.19 Limit TextField input to numeric value...........................................................................60
3.20 Limit TextField input to a maximum length....................................................................62
3.21 React to the ENTER key in a Textfield..........................................................................62
3.22 Make the ENTER key act like the TAB key....................................................................63
3.23 Reset all textfields in one shot.......................................................................................64
3.24 Limit a TextField to Uppercase......................................................................................65
3.25 Have an ImageButton....................................................................................................66
3.26 Reset a checkbox group................................................................................................69
3.27 Set the listbox width.......................................................................................................69
3.28 Align the column in a List...............................................................................................70
3.29 Have a srolling text display............................................................................................70
3.30 Label dynamic resizing..................................................................................................71
3.31 Make a TextArea "word−wrap"......................................................................................73
3.32 Synchronize a TextArea vs a Choice.............................................................................73
3.33 Display underlined text...................................................................................................73
3.34 Display vertical text........................................................................................................74
3.35 Have Label with many lines...........................................................................................75
3.36 Have a Label with underlined text..................................................................................79
3.37 Have a Label acting as HTML HREF (URLLabel).........................................................80
3.38 Display a GIF in a Canvas.............................................................................................81
3.39 Embed an image into a Frame.......................................................................................82
3.40 Load several images from a single GIF.........................................................................84
3.41 Load an Image from a JAR file......................................................................................85
3.42 Load an Icon from a jar (again)......................................................................................86
3.43 Scale an Image..............................................................................................................87
3.44 Fade an image...............................................................................................................88
3.45 Rotate an image.............................................................................................................90
3.46 Create a scrollable canvas.............................................................................................92
3.47 Use an Image as the Applet background.......................................................................96
3.48 Have a simple Image browser.......................................................................................97
3.49 Simulate a "mouse over" event to toggle an image.....................................................100
3.50 Hide the mouse cursor.................................................................................................101
3.51 Make a color transparent.............................................................................................102
Real's HowTo@www.rgagnon.com
3 AWT
3.52 Save an Image as a GIF or JPEG file..........................................................................103
3.53 Use the same background color as the browser..........................................................104
3.54 Do simple animation using Images..............................................................................105
3.55 Do simple animation to show "work in progress".........................................................106
3.56 Get the color of a specific pixel....................................................................................107
3.57 Do "rubber−band" drawing...........................................................................................108
3.58 Convert RGB value to Hexadecimal (to be used in HTML for example)......................110
3.59 Draw a line or set a pixel in my own image..................................................................110
3.60 Draw a dashed line......................................................................................................111
3.61 Draw a line with a thickness.........................................................................................112
3.62 Draw a pie chart...........................................................................................................114
3.63 Draw faster rectangles.................................................................................................116
3.64 Get a screen capture and save it as a JPEG...............................................................117
3.65 Display a TIF................................................................................................................117
3.66 Convert a multi−page TIF into single−page TIF...........................................................119
3.67 Convert an Image to a BufferedImage.........................................................................120
3.68 Detect a double click vs simple click............................................................................121
3.69 Detect the mouse button used when clicking...............................................................122
3.70 Exit an application from a menu...................................................................................123
3.71 Trigger a click on a Button...........................................................................................124

4 Environment................................................................................................................................126
4.1 java−env........................................................................................................................126
4.2 Read environment variables from an application...........................................................126
4.3 Retrieve environment variables (JDK1.5)......................................................................130
4.4 Retrieve environment variable (JNI)..............................................................................130
4.5 Use a MAKE file.............................................................................................................131
4.6 Detect the browser/JVM type.........................................................................................132
4.7 Fix the "Wrong magic number" error message..............................................................134
4.8 Use a precompiler "à la C" with Java.............................................................................134
4.9 Determine what are the classes actually used in a Java Applet or application..............134
4.10 Set the memory available to the JVM..........................................................................135
4.11 Generate the Javadoc "en français"............................................................................135
4.12 Use JDK1.5 new features............................................................................................136
4.13 Check the class version...............................................................................................137
4.14 Get the system properties or the JVM uptime..............................................................138
4.15 Detect if running in a 64bit JVM...................................................................................139
4.16 Set the default JVM type..............................................................................................139
4.17 Capture the output of JAVAC.......................................................................................140
4.18 Freeze the JVIEW window in MS VJ++.......................................................................141
4.19 Know details about the JAVA at run−time...................................................................141
4.20 Detect the Microsoft JVM version installed..................................................................143
4.21 Run JAVA as a Windows service.................................................................................143
4.22 Execute a class from Windows Explorer......................................................................143
4.23 Create an icon to launch java apps for Windows?.......................................................145
4.24 Fix the "out of environment" error when setting a new CLASSPATH..........................145
4.25 Query Windows registry...............................................................................................146
4.26 Quickly retrieve available Java JVM on a workstation (Windows)...............................148
4.27 Get the Windows "My Documents" path......................................................................149
4.28 Get a return code from a VBS

Real's HowTo@www.rgagnon.com
4 Environment
4.28 Get a return code from a VBS......................................................................................150
4.29 List currently running processes (Windows)................................................................151
4.29.1 Using TASKLIST.EXE.........................................................................................151
4.29.2 Using a VBS........................................................................................................152
4.30 Windows registry vs. Java JDK/JRE installation..........................................................153
4.31 Use a JAR/ZIP/CAB file with an Applet........................................................................154
4.32 Make ZIP/JAR file always accessible from applet.......................................................156
4.33 Make a JAR executable...............................................................................................156
4.34 Accessing jars from within a jar...................................................................................157
4.35 Access a JAR outside the CLASSPATH......................................................................158
4.36 Extract a file from a Jar................................................................................................158
4.37 Determine if running from JAR.....................................................................................160
4.38 Get list of classes in package (in a Jar).......................................................................160
4.39 Add version to Jar packaging.......................................................................................162
4.40 Use ANT to Build a JAR with version/build number.....................................................164
4.41 Include all jars in the classpath definition.....................................................................167
4.42 Windows batch file.......................................................................................................167
4.43 JDK6............................................................................................................................168
4.44 JAR (and ANT).............................................................................................................169
4.45 Detect the browser/JVM type.......................................................................................170
4.46 Detect if Java is enabled from HTML...........................................................................172
4.47 See the Java Console Window Log (Java plugin).......................................................172

5 Internationalization.....................................................................................................................174
5.1 java−inter.......................................................................................................................174
5.2 Load resources based upon client environment at startup............................................174
5.3 Load resources dynamically..........................................................................................177
5.4 Load resources via a resources file...............................................................................180
5.5 Display "special character" using Unicode.....................................................................184
5.6 Display chinese/japanese characters............................................................................185
5.7 Localize a JOptionPane dialog......................................................................................185
5.8 Validate/Convert a number using the current Locale()..................................................187
5.9 Localize a JFileChooser.................................................................................................187
5.10 Disable localization......................................................................................................190
5.11 Generate the Javadoc "en français"............................................................................190
5.12 Sort a String array........................................................................................................191
5.13 Accentuated characters in Properties/ResourceBundle file.........................................193
5.14 Compare accentuated letters.......................................................................................193
5.15 Unaccent letters...........................................................................................................194
5.16 Output french characters to the console......................................................................197
5.17 Get the default character set of the JVM.....................................................................198
5.18 Convert OEM (DOS) file to Ansi (Windows)................................................................198
5.19 Detect non−ASCII character in a String.......................................................................199

6 IO..................................................................................................................................................201
6.1 java−io...........................................................................................................................201
6.2 Redirect output(stdout/stderr) to a frame.......................................................................201
6.3 Redirect printStackTrace() to a String............................................................................202
6.4 Output french characters to the console........................................................................203
Real's HowTo@www.rgagnon.com
6 IO
6.5 Clear the console and control attributes........................................................................204
6.6 Print text to a printer easily............................................................................................205
6.7 Print without a Dialog.....................................................................................................205
6.8 Simple input from the keyboard.....................................................................................206
6.9 Initialize and write to a serial port...................................................................................207
6.10 Redirect to a NULL device...........................................................................................208
6.11 Get the volume label....................................................................................................208
6.12 Easy keyboard input (JDK1.5).....................................................................................209
6.13 Open or close a CD/DVD drive....................................................................................209
6.14 Get faster console output (System.out.println() replacement).....................................211
6.15 Execute an external program.......................................................................................212
6.16 Using Runtime.exec()..................................................................................................212
6.17 Windows CMD (or BAT) file and retrieve the errorlevel or exitcode............................213
6.18 Launch a Unix script....................................................................................................213
6.19 Using the ProcessBuilder.............................................................................................213
6.20 Windows rundll32 utility...............................................................................................214
6.21 PDF (Windows only)....................................................................................................214
6.22 PDF (Mac only)............................................................................................................215
6.23 Path to executable with spaces in them.......................................................................215
6.24 VBSCRIPT...................................................................................................................215
6.25 HTML Help (Windows only).........................................................................................216
6.26 Start Excel....................................................................................................................216
6.27 Launch the application associated with a file extension..............................................216
6.28 Launch an application from another application..........................................................217
6.29 Start the default browser from an application..............................................................219
6.30 Execute a Windows Shortcut (.lnk)..............................................................................221
6.31 Create a file association with a Java program.............................................................221
6.32 Capture the output from a VBS....................................................................................223
6.33 Get a return code from a VBS......................................................................................224
6.34 Execute a CMD file stored in a JAR.............................................................................225
6.35 Read the content of a file.............................................................................................226
6.36 Read a text file from a jar.............................................................................................228
6.37 Extract a file from a Jar................................................................................................231
6.38 Read a data file with floats...........................................................................................232
6.39 Write to the end of a file...............................................................................................233
6.40 Write "real" ascii file.....................................................................................................234
6.41 Copy a file....................................................................................................................235
6.42 Use a "log file"..............................................................................................................237
6.43 Delete files with a certain extension.............................................................................238
6.44 Insert a line in a file......................................................................................................239
6.45 Read a file into a variable in one shot..........................................................................240
6.46 Serialize an object to a file...........................................................................................240
6.47 Redirect stdout to a file................................................................................................242
6.48 Get the "last modified" date from a file.........................................................................242
6.49 Check if a file exists.....................................................................................................242
6.50 Get the current directory..............................................................................................243
6.51 Get the "root" of an application....................................................................................243
6.52 Get the content of a directory with a Filter...................................................................244
6.53 Get the content of a directory with subdirectories........................................................246
6.54 Make a directory

Real's HowTo@www.rgagnon.com
6 IO
6.54 Make a directory..........................................................................................................247
6.55 Create a fixed−length file.............................................................................................247
6.56 Delete a non−empty directory......................................................................................247
6.57 Create a temporary file................................................................................................248
6.58 Detect file modification.................................................................................................249
6.59 Get the default character set of the JVM.....................................................................252
6.60 Parse a pathname........................................................................................................252
6.61 Handle Excel files........................................................................................................253
6.62 JDBC−ODBC Excel driver...........................................................................................253
6.63 JExcel..........................................................................................................................253
6.64 POI...............................................................................................................................254
6.65 JXLS............................................................................................................................255
6.66 xlSQL...........................................................................................................................255
6.67 JCOM...........................................................................................................................256
6.68 OpenXLS Java Spreadsheet SDK...............................................................................257
6.69 Handle CSV file............................................................................................................259
6.70 com.Ostermiller.util CSV Utils......................................................................................259
6.71 opencsv........................................................................................................................259
6.72 ServingXML.................................................................................................................259
6.73 Super CSV...................................................................................................................259
6.74 csvreader.....................................................................................................................259
6.75 CSVFile........................................................................................................................259
6.76 FlatPack.......................................................................................................................260
6.77 Create an Excel file......................................................................................................260
6.78 Create or process a PDF file........................................................................................260
6.79 Convert OEM (DOS) file to Ansi (Windows)................................................................262
6.80 Close a stream in a try/catch block..............................................................................263
6.81 Rename a file extension..............................................................................................264
6.82 Remove HTML tags from a file to extract only the TEXT.............................................264
6.83 Get the Mime Type from a File....................................................................................265
6.83.1 Using javax.activation.MimetypesFileTypeMap..................................................265
6.83.2 Using java.net.URL.............................................................................................266
6.83.3 Using JMimeMagic..............................................................................................266
6.83.4 Using mime−util..................................................................................................267
6.83.5 Using Droid.........................................................................................................267
6.83.6 Aperture framework.............................................................................................267
6.84 Create a compressed (ZIP) file....................................................................................268
6.85 Display compressed (ZIP) file content.........................................................................269
6.86 Expand the compressed (ZIP) file................................................................................270
6.87 Emit a beep..................................................................................................................270
6.88 Emit a Tone..................................................................................................................271
6.89 Play an audio file from an application..........................................................................272

7 JDBC............................................................................................................................................274
7.1 java−jdbc........................................................................................................................274
7.2 Connect to a database via JDBC−ODBC......................................................................274
7.3 SELECT data from a table.............................................................................................275
7.4 INSERT data into a table...............................................................................................276
7.5 MODIFY data in a table.................................................................................................277
Real's HowTo@www.rgagnon.com
7 JDBC
7.6 DELETE data in a table.................................................................................................278
7.7 Test for an empty ResultSet..........................................................................................278
7.8 Store and retrieve an object from a table.......................................................................279
7.9 Retrieve an Image..........................................................................................................281
7.10 Insert an Image............................................................................................................281
7.11 Connect to an Oracle database with JDBC.................................................................281
7.12 Connect to Oracle using a connection pool.................................................................282
7.13 Get JDBC driver for major database vendors..............................................................285
7.14 Handle dates................................................................................................................285
7.15 Call a stored procedure................................................................................................286
7.16 Stored procedure with Input/Output parms and a ResultSet.......................................287
7.17 Fix incomplete field returned by the ResultSet............................................................288
7.18 Get a record count with the SQL Statement................................................................288
7.19 Transfer a ResultSet to a JTable.................................................................................288
7.20 List tables in a database..............................................................................................289
7.21 Display ResultSet data in an HTML Table in Servlet...................................................290
7.22 Detect SQL errors or warnings....................................................................................291
7.23 Using DSN−less connection........................................................................................292
7.24 Read data from Excel worksheet.................................................................................293
7.25 Handle Excel files........................................................................................................294
7.26 JDBC−ODBC Excel driver...........................................................................................295
7.27 JExcel..........................................................................................................................295
7.28 POI...............................................................................................................................296
7.29 JXLS............................................................................................................................296
7.30 xlSQL...........................................................................................................................297
7.31 JCOM...........................................................................................................................297
7.32 OpenXLS Java Spreadsheet SDK...............................................................................298
7.33 Specify a CharSet when connecting to a DBMS..........................................................300
7.34 Get current date using JDBC.......................................................................................300
7.35 Enable JDBC logging...................................................................................................301
7.36 Detect if a table exists..................................................................................................303
7.37 Convert a ResultSet to XML........................................................................................303
7.38 Escape special character in a LIKE clause..................................................................305
7.39 Insert the current date..................................................................................................306
7.40 Log the SQL Statements..............................................................................................306
7.41 Plain JDBC Logging.....................................................................................................306
7.42 P6Spy..........................................................................................................................306
7.43 Proxool.........................................................................................................................306

8 JNI................................................................................................................................................307
8.1 java−jni...........................................................................................................................307
8.2 Use native code through JNI..........................................................................................307
8.3 Pass a string to/from Java to/from C..............................................................................307
8.4 Set the computer clock..................................................................................................309
8.5 Determine the signature of a method.............................................................................309
8.6 Use arrays......................................................................................................................311
8.7 Load a DLL....................................................................................................................312
8.8 Use the MouseWheel.....................................................................................................312
8.9 Throw an Exception (from JNI code).............................................................................312
8.10 Throw my own Exception (from JNI code)

Real's HowTo@www.rgagnon.com
8 JNI
8.10 Throw my own Exception (from JNI code)...................................................................313
8.11 JNI from a package......................................................................................................314
8.12 Make a Window "stay on top"......................................................................................314
8.13 Start a JVM from C......................................................................................................315
8.14 Retrieve environment variable (JNI)............................................................................316
8.15 Get the PID..................................................................................................................316
8.16 Clear the console, set color and cursor position (JNI).................................................317
8.17 Call Windows API (Open source solution)...................................................................320

9 Javascript interaction.................................................................................................................321
9.1 java−js............................................................................................................................321
9.2 * Read me *....................................................................................................................321
9.3 Wake−up a Java applet.................................................................................................321
9.4 Call a Java method from Javascript...............................................................................323
9.5 Calling Java applets methods using DOM and JavaScript............................................325
9.6 Access Java variables from Javascript..........................................................................325
9.7 Call Javascript from a Java applet.................................................................................326
9.8 Create dynamic HTML from a Java applet....................................................................329
9.9 Have Applets on different frames communicates with each other.................................330
9.10 Send a message from an Applet to another Applet on a different page......................331
9.11 Retrieve values from a Java applet for HTML form (CGI)............................................333
9.12 Detect if an Applet is ready..........................................................................................334
9.13 Read/Write HTML field values from JAVA...................................................................335
9.14 Detect if Java is enabled..............................................................................................337
9.15 Detect if Java 1.1 (with event delegation) is available.................................................337
9.16 Access Cookies from a Java Applet............................................................................337
9.17 Set Applet PARAM VALUE from javascript.................................................................340
9.18 Pass an Array between Java and Javascript...............................................................341
9.19 Interaction without LiveConnect...................................................................................343
9.20 Directory listing on the Web server in a Java Applet...................................................347
9.21 Have a Java button close the browser window............................................................349
9.22 Detect if cookies are enabled.......................................................................................350
9.23 Display a page after all applets are loaded..................................................................351

10 Servlet/JSP................................................................................................................................352
10.1 java−jsp........................................................................................................................352
10.2 Read me......................................................................................................................352
10.3 Get parameters passed to a servlet.............................................................................352
10.4 Detect no argument condition in a Servlet...................................................................353
10.5 Set a Cookie from a servlet..........................................................................................354
10.6 Read a Cookie from a servlet......................................................................................354
10.7 Delete (or expire) a Cookie from a servlet...................................................................355
10.8 Ask for a password from a Servlet...............................................................................355
10.9 Talk to a CGI/Servlet....................................................................................................356
10.10 Test for Cookies.........................................................................................................357
10.11 Display ResultSet data in an HTML Table in Servlet.................................................357
10.12 Specify the filename to be used for a file sent by a Servlet.......................................358
10.13 Pass information to another servlet/jsp......................................................................358
10.14 Handle PDF output....................................................................................................359
Real's HowTo@www.rgagnon.com
10 Servlet/JSP
10.15 Detect if the connection is via a secure channel........................................................359
10.16 In a Servlet, check if Form Field is present................................................................359
10.17 Get the root dir of a web app.....................................................................................360
10.18 Get client IP address from JSP..................................................................................360
10.19 Output a binary stream from a JSP............................................................................360
10.20 Use a connection cache from JSP.............................................................................361
10.21 Read a Web Application property..............................................................................362
10.22 Use EJB from JSP.....................................................................................................363
10.23 Define a method in a JSP page.................................................................................363
10.24 Precompile JSP pages...............................................................................................363
10.25 Get a list of directories for JSP..................................................................................365
10.26 Use and share a class in JSP pages.........................................................................365
10.27 Get the root dir of a web app.....................................................................................367
10.28 Launch an applet from a JSP.....................................................................................367
10.29 Prevent caching of a JSP output................................................................................367
10.30 Call another EJB........................................................................................................368
10.31 Keep java files generated from JSP (BEA WLS).......................................................368
10.32 Get the server version (BEA WLS)............................................................................369
10.33 Quickly create a Web application with BEA WLS......................................................369
10.34 Nicely display WEB.XML informations.......................................................................370
10.35 Reverse the CLASSLOADER order (BEA)................................................................371
10.36 Detect change in JSP and recompile (BEA)..............................................................372

11 Language...................................................................................................................................373
11.1 java−language.............................................................................................................373
11.2 * Read me *..................................................................................................................373
11.3 Use a Hashtable..........................................................................................................374
11.4 Scan the content of a hashtable..................................................................................374
11.5 Call a method dynamically (Reflection)........................................................................374
11.6 Create an object from a string......................................................................................376
11.7 Get a variable value from the variable name...............................................................377
11.8 Launch an application from another application..........................................................378
11.9 Create a java source dynamically, compile and call....................................................379
11.10 Access the enclosing class from an inner class.........................................................380
11.11 Access inner class from outside................................................................................381
11.12 Use globally defined constants..................................................................................382
11.13 Serialize an Object.....................................................................................................383
11.14 Serialize an Object over a socket..............................................................................385
11.15 Easily remove my debugging code............................................................................385
11.16 Obtain from where a Class is loaded.........................................................................386
11.17 Get the class name in a static method.......................................................................387
11.18 Get the current method name....................................................................................387
11.19 Detect if a package is available.................................................................................388
11.20 Have a singleton........................................................................................................389
11.21 Make methods that have unspecified number of parameters....................................390
11.22 Multiple expressions in for loops................................................................................391
11.23 Handle the List conflict...............................................................................................391
11.24 Use a generic toString().............................................................................................391
11.25 Use Object.clone().....................................................................................................393
11.26 Static field, constructor and exception

Real's HowTo@www.rgagnon.com
11 Language
11.26 Static field, constructor and exception.......................................................................394
11.27 Use a Label break......................................................................................................395
11.28 Put printStackTrace() into a String.............................................................................396
11.29 Sort an array..............................................................................................................397
11.30 Initialize multidimensional array.................................................................................398
11.31 Get array upperbound................................................................................................399
11.32 Convert a String to an array.......................................................................................399
11.33 Sort in reverse order..................................................................................................400
11.34 Resize an array..........................................................................................................401
11.35 Dump array content...................................................................................................402
11.36 Initialize a static array................................................................................................403
11.37 Sort an Hashtable......................................................................................................404
11.38 Eliminate "[unchecked] unchecked call ..." compiler warning....................................405
11.39 Sort on many fields....................................................................................................406
11.40 Optimize Collection usage.........................................................................................408
11.41 Sort an HashMap.......................................................................................................410
11.42 Get a key from value with an HashMap.....................................................................411
11.43 Use an INI file (properties).........................................................................................411
11.44 Load a properties file.................................................................................................413
11.45 Accentuated characters in Properties/ResourceBundle file.......................................413
11.46 Have a multi−line value in a properties file................................................................414
11.47 Use XML with Properties...........................................................................................415
11.48 Use the Registry to store informations (Preferences API).........................................415

12 Networking................................................................................................................................417
12.1 java−net.......................................................................................................................417
12.2 Extract network card address......................................................................................417
12.3 Get the workstation name/ip........................................................................................419
12.4 Find port number not in use.........................................................................................421
12.5 Disable DNS caching...................................................................................................421
12.6 Encode/Decode to/from Base64..................................................................................422
12.7 Using javax.mail.internet.MimeUtility...........................................................................422
12.8 Using Apache Commons Codec..................................................................................423
12.9 MiGBase64..................................................................................................................424
12.10 Lookup using MX record to validate mail server........................................................424
12.11 Send an email using the SMTP protocol....................................................................431
12.12 Check if there is mail waiting.....................................................................................432
12.13 Receive email............................................................................................................434
12.14 Send email with an attachment..................................................................................436
12.15 Send email with JavaMail..........................................................................................441
12.16 Send email with authentication..................................................................................443
12.17 Handle EML file with JavaMail...................................................................................444
12.18 Send HTML mail with images (Javamail)...................................................................446
12.19 Debug a Javamail Program.......................................................................................448
12.20 Send email with SMTPS (eg. Google GMail) (Javamail)...........................................449
12.20.1 Settings for well known mail providers..............................................................450
12.21 Mix plain text and HTML content in a mail.................................................................450
12.22 Check if a file was modified on the server.................................................................451
12.23 Check if a page exists................................................................................................451
Real's HowTo@www.rgagnon.com
12 Networking
12.24 Connect through a Proxy...........................................................................................453
12.25 Identify yourself using HTTP Authentification............................................................455
12.26 Talk to a CGI/Servlet..................................................................................................457
12.27 Write/Read cookies using HTTP................................................................................458
12.28 Read a GIF or CLASS from an URL save it locally....................................................460
12.29 Resolve a relative URL..............................................................................................462
12.30 File size from URL.....................................................................................................462
12.31 Use the HTTPS protocol............................................................................................463
12.32 Fetch a page from Google.........................................................................................463
12.33 Upload a file to a server.............................................................................................464
12.34 Connect through a Proxy...........................................................................................465
12.35 Have timeout on socket connection...........................................................................467
12.36 Ping a server..............................................................................................................467
12.37 Get the Date from server...........................................................................................468
12.38 Get the client IP address............................................................................................469
12.39 Use the java.net.Socket.setSoLinger method............................................................470
12.40 Use the java.net.Socket.setTcpNoDelay method......................................................470
12.41 Find out who is accessing my ServerSocket.............................................................471
12.42 Transfer a file via Socket...........................................................................................471

13 Security......................................................................................................................................473
13.1 java−security................................................................................................................473
13.2 Encrypt a password.....................................................................................................473
13.3 Create a checksum......................................................................................................475
13.4 Get the user name.......................................................................................................478
13.5 Get username using NT Challenge (NTLM)................................................................478
13.6 Check if the current user belongs a specific Windows group/role...............................480
13.7 Prompt for password from the console........................................................................480
13.8 Display a simple username/password Dialog from an Applet......................................481

14 Swing.........................................................................................................................................485
14.1 java−swing...................................................................................................................485
14.2 * Read me *..................................................................................................................485
14.3 Change component default font...................................................................................485
14.4 Repaint problem under the mouse cursor (JDK1.2)....................................................486
14.5 Set the LookAndFeel...................................................................................................486
14.6 Use any LookAndFeel on any plateform......................................................................486
14.7 Use a Timer.................................................................................................................487
14.8 Share ActionEvent handler..........................................................................................487
14.9 Trigger a click on a Button...........................................................................................489
14.10 Get default values for Swing−based user interface...................................................491
14.11 Close a JFrame under condition................................................................................492
14.12 Maximize a JFrame....................................................................................................492
14.13 Capture System.out into a JFrame............................................................................493
14.14 Remove the titlebar of JInternalFrame.......................................................................495
14.15 Have borders on a JWindow/JFrame.........................................................................496
14.16 Display HTML in a JScrollPane.................................................................................496
14.17 Use a JOptionPane....................................................................................................497
14.18 Localize a JOptionPane dialog..................................................................................498
14.19 Customize JOptionPane buttons

Real's HowTo@www.rgagnon.com
14 Swing
14.19 Customize JOptionPane buttons...............................................................................500
14.20 Localize a JFileChooser.............................................................................................500
14.21 Select a directory with a JFileChooser.......................................................................503
14.22 Disable the JFileChooser's "New folder" button.........................................................504
14.23 Validate a filename from a JFileChooser...................................................................505
14.24 Make a JFrame looks like a JDialog..........................................................................507
14.25 Based on JTextField content, enable or disable a JButton........................................508
14.26 Apply special filter to a JtextField...............................................................................509
14.27 Limit JTextField input to a maximum length...............................................................511
14.28 Validate a value on the lostFocus event....................................................................512
14.29 Make sure that my jTextfield has the focus when a JFrame is created.....................514
14.30 Stop the beep on JFormattedTextField......................................................................515
14.31 Right justified JTextfield content................................................................................516
14.32 Set the focus on a particuliar JTextField....................................................................516
14.33 Make JTextField unselectable...................................................................................516
14.34 Use a JTree to navigate in a site...............................................................................517
14.35 Expand or collapse a JTree.......................................................................................523
14.36 Have a popup attached to a JTree.............................................................................525
14.37 Traverse a JTree........................................................................................................527
14.38 Show dotted lines in a JTree......................................................................................529
14.39 Explore directories with a JTree.................................................................................529
14.40 Prevent JTree collapsing...........................................................................................531
14.41 Single selection in a JTree.........................................................................................531
14.42 Reduce JTree children indentation............................................................................531
14.43 Use + or − for JTree Icons.........................................................................................532
14.44 Change the JTable header color................................................................................533
14.45 Double click on a JTable............................................................................................534
14.46 Read a data file into a JTable....................................................................................535
14.47 Disable row selection in a JTable..............................................................................538
14.48 Read a data file into a JTable and reload if data file have changed..........................538
14.49 Hide a column in JTable............................................................................................540
14.50 Scroll a JTable to the last row....................................................................................542
14.51 Transfer a ResultSet to a JTable...............................................................................542
14.52 Have on a JScrollPane/JTable an horizontal JScrollbar............................................543
14.53 Make a JList select an item on doubleclick or the ENTER key..................................543
14.54 Make a JList like a scrolling text display....................................................................544
14.55 Have images in a JList...............................................................................................545
14.56 Add a row and clear a JList........................................................................................547
14.57 Sort a JList.................................................................................................................548
14.58 Double click on a JList...............................................................................................550
14.59 Have a PopUp on a JList...........................................................................................551
14.60 Set the cursor position in a JTextArea.......................................................................552
14.61 Make a JLabel selectable with the mouse.................................................................552
14.62 Change JLabel background color..............................................................................553
14.63 Bold / Unbold a JLabel...............................................................................................553
14.64 Multi−line JLabel........................................................................................................554
14.65 Underline a string.......................................................................................................554
14.66 Update a JLabel.........................................................................................................555
14.67 Have Multi−line string in a JToolTip...........................................................................555
Real's HowTo@www.rgagnon.com
14 Swing
14.68 Change Tooltip color..................................................................................................555
14.69 Change a JTooltip font...............................................................................................555
14.70 Keep a JTooltip visible...............................................................................................556
14.71 Display icon associated with an executable...............................................................557
14.72 Have items in JMenubar at rightmost position...........................................................559
14.73 Have an JButton with an Image.................................................................................560

15 Thread........................................................................................................................................562
15.1 java−thread..................................................................................................................562
15.2 Pipe the output of a thread to the input of another one................................................562
15.3 Pipe the output of a thread to the input of other threads..............................................564
15.4 Wait the for the completion of a thread........................................................................566
15.5 Control a thread from outside......................................................................................567
15.6 Create a Timer object..................................................................................................568
15.7 Pause the execution....................................................................................................569
15.8 Execute a method at a specified time interval.............................................................569
15.9 Execute a process at regular interval...........................................................................571
15.10 Handle concurrent read/write.....................................................................................572
15.11 Communicate between threads using a Queue.........................................................573

16 Varia...........................................................................................................................................579
16.1 java−varia....................................................................................................................579
16.2 Create a Taglet to document database access (Javadoc)...........................................579
16.2.1 newMethod.........................................................................................................579
16.3 Generate the Javadoc "en français"............................................................................582
16.4 Document a package using Javadoc...........................................................................584
16.5 Use a Log file...............................................................................................................585
16.6 Trace the execution.....................................................................................................587
16.7 Time the execution.......................................................................................................589
16.8 Log information efficiently (with Log4J)........................................................................590
16.9 Call Windows API (Open source solution)...................................................................591
16.10 Call COM object (Open source solution)...................................................................592
16.11 Run JAVA as a Windows service...............................................................................592
16.12 Create entity−relation diagram...................................................................................593
16.13 Java Remote desktop tool.........................................................................................593
16.14 Create entity−relation diagram...................................................................................594
16.15 Launch a java program as a Windows EXE file.........................................................594
16.16 Handle CSV file..........................................................................................................594
16.17 com.Ostermiller.util CSV Utils....................................................................................594
16.18 opencsv......................................................................................................................594
16.19 ServingXML...............................................................................................................595
16.20 Super CSV.................................................................................................................595
16.21 csvreader...................................................................................................................595
16.22 CSVFile......................................................................................................................595
16.23 FlatPack.....................................................................................................................595
16.24 Handle Excel files......................................................................................................595
16.25 JDBC−ODBC Excel driver.........................................................................................595
16.26 JExcel........................................................................................................................596
16.27 POI.............................................................................................................................596
16.28 JXLS

Real's HowTo@www.rgagnon.com
16 Varia
16.28 JXLS..........................................................................................................................597
16.29 xlSQL.........................................................................................................................598
16.30 JCOM.........................................................................................................................598
16.31 OpenXLS Java Spreadsheet SDK.............................................................................599
16.32 Use System time to generate unique ID....................................................................601
16.33 Get a unique identifier................................................................................................601
16.34 Get the hard disk serial number or Motherboard serial number................................602
16.35 Motherboard serial number........................................................................................603
16.36 Hard disk serial number.............................................................................................603
16.37 Sort an array..............................................................................................................604
16.38 Sort a String array......................................................................................................606
16.39 Do a selection sort.....................................................................................................608
16.40 Obtain from where a Class is loaded.........................................................................608
16.41 Get the class name with or without the package.......................................................609
16.42 Convert a .class to .java file.......................................................................................610
16.43 See the generated bytecode......................................................................................611
16.44 Self replicating programs...........................................................................................613
16.45 A curiosity (strange Java code)..................................................................................614
16.46 Classic bugs...............................................................................................................615
16.47 Number of the beast!.................................................................................................616
16.48 Convert wildcard to a regex expression.....................................................................616
16.49 Count distinct elements in a Vector...........................................................................618
16.50 Justify a string with wordwrap....................................................................................619
16.51 Validate a Social Security Number (canadian)..........................................................620
16.52 Validate a Credit Card Number..................................................................................621
16.53 Preventing multiple instances of an application.........................................................624
16.54 Trap JVM shutdown...................................................................................................627
16.55 Browse a Queue (JMS/MQ).......................................................................................628
16.56 Wrap a Java beans in a COM object.........................................................................628

17 XML............................................................................................................................................631
17.1 java−xml.......................................................................................................................631
17.2 Read me......................................................................................................................631
17.3 Display XML using plain HTML....................................................................................632
17.4 Transform XML into HTML using XSLT.......................................................................633
17.5 Parse using SAX or DOM............................................................................................634
17.6 Parse an XML string....................................................................................................636
17.7 Create an XML document with DOM...........................................................................637
17.8 Attach a stylesheet to an XML file................................................................................639
17.9 Create an XML file and attach an XSL.........................................................................640
17.10 Nicely display WEB.XML informations.......................................................................643
17.11 Serialize an object using XML....................................................................................644
17.12 Convert a flat file to XML (SAX).................................................................................645
17.13 Convert a flat file to XML (DOM)................................................................................647
17.14 Convert a ResultSet to XML......................................................................................650
17.15 Parse with XPath.......................................................................................................652
17.16 Strip extra spaces in a XML string.............................................................................653
17.17 Create an XML file and attach an XSL.......................................................................654
17.18 Use XML with Properties...........................................................................................657
Real's HowTo@www.rgagnon.com
17 XML
17.19 Create a RSS feed.....................................................................................................658
17.19.1 RSS 2.0.............................................................................................................658
17.19.2 Atom..................................................................................................................659
17.19.3 Creating a feed..................................................................................................660
17.19.4 Creating a feed with Apache Commons Digester.............................................660
17.19.5 Creating a feed with Rome................................................................................661
17.20 Parse a RSS XML file................................................................................................663
17.20.1 Parsing a feed with Apache Commons Digester...............................................663
17.20.2 Parsing a feed with ROME................................................................................664
17.20.3 RSS−UTIL.TLD.................................................................................................665
17.21 Add a Live bookmark.................................................................................................665
17.22 Validate a RSS feed...................................................................................................665
17.23 Attach a CSS to RSS feed.........................................................................................665

18 DEPRECATED...........................................................................................................................668
18.1 java−deprecated..........................................................................................................668
18.2 * Read me *.................................................................................................................668
18.3 Keep the console open after execution........................................................................668
18.4 Read the Registry........................................................................................................668
18.5 Call a Win API..............................................................................................................669
18.6 Display a BMP image...................................................................................................671
18.7 Play a WAV audio file..................................................................................................671
18.8 Detect if the MS JVM is used.......................................................................................672
18.9 Get the latest MS JVM.................................................................................................672
18.10 Uninstalling the MS JVM............................................................................................672
18.11 Wrap a Java class in a COM object...........................................................................673
18.12 Sign an applet............................................................................................................674
18.13 Bypass the need for a certificate................................................................................675
18.14 Start an executable on the client................................................................................676
18.15 Get rid of the message "Warning − unsigned applet window"...................................677
18.16 Read/write a local file from an Applet........................................................................677
18.17 Write "other−browser−friendly" code when using the Netscape Capabilities
package..............................................................................................................................678
18.18 Disable the JIT compiler in Netscape or IE................................................................679
18.19 Start automatically JAVA when opening Netscape....................................................679
18.20 Use Netscape Java Console hidden commands.......................................................680
18.21 Avoid the Netscape "Couldn't connect to '' with origin from
'local−classpath−classes'" message...................................................................................680
18.22 Post a message on a newsserver using NNTP protocol............................................680
18.23 Read messages from a newsserver..........................................................................681
18.24 Get a list of headers from a newsgroup.....................................................................682
18.25 Get a list of all available newsgroup from a newsserver............................................682
18.26 Detect if Swing is installed.........................................................................................683
18.27 Make Swing always available from Netscape............................................................684

19 String/Number...........................................................................................................................685
19.1 java−stringnumber.......................................................................................................685
19.2 * Read me *..................................................................................................................685
19.3 Convert from type X to type Y......................................................................................686
19.4 Strip certain characters from a String

Real's HowTo@www.rgagnon.com
19 String/Number
19.4 Strip certain characters from a String..........................................................................688
19.5 Replace/remove character in a String..........................................................................689
19.6 Replace every occurences of a string within a string...................................................690
19.7 "Tokenize" a string.......................................................................................................691
19.8 Split a string using String.split()...................................................................................695
19.9 Optimize String operations...........................................................................................698
19.10 Remove spaces from a string....................................................................................699
19.11 Test if a String starts with a digit or uppercase letter.................................................701
19.12 Get InputStream from a String...................................................................................701
19.13 Easy String padding...................................................................................................701
19.14 Replace \r\n with the <br> tag....................................................................................702
19.15 Unaccent letters.........................................................................................................702
19.16 Apply a mask to String...............................................................................................705
19.17 Format a String (JDK1.5)...........................................................................................706
19.18 Replace a "\" by "\\"....................................................................................................707
19.19 Substitute tokens in a String......................................................................................707
19.20 Compare accentuated letters.....................................................................................707
19.21 Create a String with fixed length and filled with a specific character.........................709
19.22 Unquote a String........................................................................................................709
19.23 Escape HTML special characters from a String.........................................................710
19.24 Unescape HTML special characters from a String....................................................712
19.25 Using HashMap.........................................................................................................712
19.26 Using Array................................................................................................................713
19.27 Detect non−ASCII character in a String.....................................................................714
19.28 Remove HTML tags from a file to extract only the TEXT...........................................715
19.29 Convert a byte array to a Hex string..........................................................................716
19.30 Apply proper uppercase and lowercase on a String..................................................717
19.31 Encode/Decode to/from Base64................................................................................718
19.32 Using javax.mail.internet.MimeUtility.........................................................................718
19.33 Using Apache Commons Codec................................................................................719
19.34 MiGBase64................................................................................................................719
19.35 Convert from type X to type Y....................................................................................719
19.36 Type conversion (JDK1.5).........................................................................................721
19.37 Round a double..........................................................................................................722
19.38 Display numbers with commas..................................................................................723
19.39 Display numbers in scientific notation........................................................................724
19.40 Display numbers with leading zeroes........................................................................725
19.41 Get a random number................................................................................................726
19.42 Convert an UNSIGNED byte to a JAVA type.............................................................726
19.43 Deal with big−endian and little−endian order.............................................................727
19.44 Pass an integer by reference.....................................................................................727
19.45 Pass floats as string literals to a method...................................................................728
19.46 Get random numbers.................................................................................................728
19.47 Convert number into words........................................................................................729
19.48 Arithmetic with double................................................................................................736
19.49 Detect even/odd number............................................................................................737
19.50 Convert bytes to megabytes......................................................................................737
19.51 Validate a number......................................................................................................738
1 Applet
1.1 java−applet

1.2 Goto to a new URL from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0002.html

You have to use

getAppletContext().showDocument
(new URL("http://www.whatever.com"));

or

getAppletContext().showDocument
(new URL("http://www.whatever.com"),"HTML FRAME ID");

If "HTML frame ID" do not exists then a new browser window will be opened. The following "HTML
frame ID" have special meanings :

"_self" current frame


"_parent" parent frame
"_top" base frame
"_blank" new window

For example, we want to display lowres.html page if resolution is 640x480 else the hires.html is
used.

import java.applet.*;
import java.awt.*;
import java.net.*;

public class whatres extends Applet {


public void init() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
if (dim.width==640 &dim.height==480) {
try {
getAppletContext().showDocument
(new URL(getCodeBase()+"lowres.html"),"_top");
}
catch (Exception ex) {}
}
else {
try {
getAppletContext().showDocument
(new URL(getCodeBase()+"hires.html"),"_top");
}
catch (Exception ex) {}
}

1 Applet
}
}

NOTE: The previous example works only so long as the document was retrieved without specifying an actual document name, since
getDocumentBase() returns the full URL including the name of the document. If the document name was specified, you should try something
like this or specify the complete URL (thanks to Rob Judd): :

try {
String docString = getDocumentBase().toString();
if (docString.endsWith("/")) {
getAppletContext().showDocument
(new URL(getDocumentBase()+"lowres.html"), "_top");
}
else {
getAppletContext().showDocument
(new URL(getDocumentBase()+"/../lowres.html"), "_top");
}
}
catch (Exception e) {}

Another example, type a new URL in a textfield, and press a button to go to that page.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class GotoURLButton extends Applet implements


ActionListener {
Button b;
TextField t;

public void init() {


t = new TextField(20);
t.setText("http://www.google.com");
add(t);
b = new Button("Go to this URL");
add(b);
b.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b) {
try {
getAppletContext().showDocument(new URL(t.getText()));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

Try it here.

1 Applet
1.3 Determine the host from where the Applet is loaded
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0003.html

import java.applet.*;
import java.awt.*;

public class FromWhere extends Applet {


public void init() {
Label label = new Label(getCodeBase().toString());

add(label);
//
// you can check the value of getCodeBase()
// to implements a simple copy protection
// scheme. If it's not equals to your
// URL then quit.
// NOTE : This is not a very strong protection!
//
}
}

Try it here

1.4 Have a scrolling status line


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0010.html

/*
ScrollStatus.java
Optional parameters: message, width
Default values:
message = "Isn't scrolling text in the status line annoying? "
width = 36
Example usage:
<applet code="ScrollStatus.class"
width=0 height=0>
<param name="message" value="Hello World!">
<param name="width" value="24">
</applet>
*/
import java.util.*;
import java.applet.Applet;

public class ScrollStatus extends Applet implements Runnable {


Thread thread;
String message;
StringBuffer buffer;
int at;
int width;

public void init(){


message = getParameter("message");
if(message == null)
message = " Isn't scrolling text in the status line annoying? ";

1.3 Determine the host from where the Applet is loaded


String ws = getParameter("width");
if(ws == null) {
width = 36;
}
else{
width = Integer.valueOf(ws).intValue();
}
if(width < 5 || width > 180) {
width = 36;
}

buffer = new StringBuffer(width);


buffer.setLength(width);
at = 0;

if(message.length() < width) {


char buf[] = new char[width];
for(int i = 0; i < width; ++i) {
buf[i] = ' ';
}
message.getChars
(0, message.length(), buf, (width − message.length()) / 2);
message = new String(buf);
}
}

public void start(){


thread = new Thread(this);
thread.start();
}

public void stop(){


thread.stop();
}

public void scroll(){


int ml = message.length();
int k = at;
for(int i = 0; i < width; ++i, ++k){
if(k >= ml) {
k = 0;
}
buffer.setCharAt(i, message.charAt(k));
}
getAppletContext().showStatus(buffer.toString());
at++;
if(at >= ml) {
at = 0;
}
}

public void run(){


while(true){
scroll();
try{
Thread.sleep(25); // wait 25 ms
}
catch(InterruptedException e){
break;
}
}
}
}

1.3 Determine the host from where the Applet is loaded


Try it here.

1.5 Use a search engine


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0011.html

import java.applet.Applet;
import java.net.*;
import java.awt.*;

public class SearchApplet extends Applet {


TextField searchParameter;
Choice searchEngine;
Button searchButton;

public void init() {


setBackground(Color.white);
searchParameter = new TextField(20);
add(searchParameter);
searchEngine = new Choice();
searchEngine.addItem("AltaVista");
searchEngine.addItem("WebCrawler");
searchEngine.addItem("Yahoo");
searchEngine.select(0);
add(searchEngine);
searchButton = new Button("Search");
add(searchButton);
}

// JDK1.02 style event handling


public boolean action(Event e, Object o) {
if (e.target.equals(searchButton)) {
try {
sendSearch();
}
catch (Exception e1) {
showStatus("Exception caught:" + e1.toString());
}
}
return true;
}

public void sendSearch() throws Exception {


String url;
String searchString = searchParameter.getText();
if (searchString.equals("")) {
showStatus("Must enter a search string");
return;
}

switch (searchEngine.getSelectedIndex()) {
case 0: url =
"http://www.altavista.com/web/results?q=";
break;
case 1: url =
"http://msxml.webcrawler.com/info.wbcrwl/search/web/";
break;

1.5 Use a search engine


case 2: url =
"http://search.yahoo.com/bin/search?p=";
break;
default: showStatus("Invalid search engine selected.");
return;
}

// encode the search data


url += URLEncoder.encode(searchString);

// launch the search engine


showStatus("Connecting to search location " + url);
getAppletContext().showDocument(new URL(url), "_top");
}
}

Try it here.

It's not easy to call Google from an Applet but you can do it in application as seen in this HowTo.

1.6 Have an on−screen clock


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0012.html

import java.applet.*;
import java.awt.*;
import java.util.*;
import java.text.*;

public class MyClock extends Applet {


MyPanel mp;
public void init() {
mp = new MyPanel(getParameter("format"));
add(mp);
}
}

class MyPanel extends Panel {


MyClockThread mct;
Color b, f;
SimpleDateFormat formatter;
String previousDateText = "";
String dateText;

MyPanel(String df) {
super();
formatter = new SimpleDateFormat(df);
validate();
setBackground(new Color(0).black);
setForeground(new Color(0).yellow);
b = this.getBackground();
f = this.getForeground();
mct = new MyClockThread(this);
mct.start();
}

public Dimension getPreferredSize() {


return new Dimension

1.6 Have an on−screen clock


(this.getFontMetrics(this.getFont()).stringWidth(getNow()) + 25, 30);
}

public void paint(Graphics g) {


if (g != null) {
g.setColor(b);
g.drawString(previousDateText,10,15);
g.setColor(f);
dateText = getNow();
g.drawString(dateText,10,15);
previousDateText = dateText;
}
}

public String getNow() {


return formatter.format(new Date());
}
}

class MyClockThread extends Thread {


MyPanel mp;

public MyClockThread(MyPanel a) {
mp = a;
}

public void run() {


while (true) {
try {
mp.repaint();
this.sleep(1000);
}
catch(InterruptedException e) { }
}
}
}

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="MyClock.class"
HEIGHT=25 WIDTH=200>
<PARAM NAME="format" VALUE="yyyy−MM−dd hh:mm:ss">
</APPLET><P>
<APPLET CODE="MyClock.class"
HEIGHT=25 WIDTH=200>
<PARAM NAME="format" VALUE="h:mm a">
</APPLET><P>
<APPLET CODE="MyClock.class"
HEIGHT=25 WIDTH=200>
<PARAM NAME="format" VALUE="yyyy.MMMMM.dd GGG hh:mm aaa">
</APPLET><P>
<APPLET CODE="MyClock.class"
HEIGHT=25 WIDTH=200>
<PARAM NAME="format" VALUE="H:mm:ss:SSS">
</APPLET><P>
/BODY/HTML

Try it here.

1.6 Have an on−screen clock


1.7 Have Applets on the same page communicate with each
other
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0022.html

[Applet1_0022.java]

import java.awt.*;
public class Applet1_0022 extends java.applet.Applet {
TextField inputText;
Button b;

public void init() {


setLayout(new FlowLayout());
inputText = new TextField( "", 15 );
b = new Button("Send to Applet 2");
add(inputText);
add(b);
}

// JDK 1.02 style evant handling


public boolean action(Event ev, Object arg) {
if (ev.target instanceof Button) {
String textMsg = inputText.getText().trim();
Applet2_0022 applet2 =
(Applet2_0022)getAppletContext().getApplet("applet2");
if ( applet2 != null ) {
applet2.append( textMsg );
return true;
}
else {
System.out.println("Applet2 not found?");
return false;
}
}
return false;
}
}

[Applet2_0022.java]

import java.awt.*;

public class Applet2_0022 extends java.applet.Applet {


TextArea textBox;

public void init() {


setLayout(new FlowLayout());
textBox = new TextArea( 5, 40 );
add( textBox );
}

public void append( String msg ) {


textBox.append( msg );
textBox.append( "\n" );
}
}

1.7 Have Applets on the same page communicate with each other
[HTML]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="Applet1_0022.class"
NAME="applet1"
HEIGHT=200 WIDTH=150>
</APPLET>
<APPLET CODE="Applet2_0022.class"
NAME="applet2"
HEIGHT=200 WIDTH=400>
</APPLET>
</BODY></HEAD>

Try it here.

1.8 Have Applets on different frames communicates with each


other
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0023.html

It is possible to share data between different applets via static variables

[HTML (java−0023.html)]

<HTML><HEAD></HEAD>
<FRAMESET COLS="50%,*">
<FRAME SRC="java−0023−f1.html" NAME="f1">
<FRAME SRC="java−0023−f2.html" NAME="f2">
</FRAMESET>
</HEAD>

[HTML (java−0023−f1.html AND java−0023−f2.html)]

<HTML><HEAD></HEAD>
<BODY>
<APPLET CODE="Java0023.class"
HEIGHT=200
WIDTH=200>
</APPLET>
</BODY></HTML>

[JAVA source (Java0023.java)]

import java.awt.*;
import java.applet.*;

public class Java0023 extends Applet {


TextField tf;
Button a,b;

public void init() {


setLayout(new FlowLayout());
a = new Button("Send to Message");
b = new Button("Receive from Message");
add(a);

1.8 Have Applets on different frames communicates with each other


add(b);
tf = new TextField(20);
add(tf);
}

// JDK 1.02 style evant handling


public boolean action(Event e, Object o) {
if (e.target instanceof Button) {
if (e.target == a) {
StaticMessage.message = tf.getText();
}
if (e.target == b) {
tf.setText(StaticMessage.message);
}
return true;
}
return false;
}
}

class StaticMessage {
public static String message = "";
}

Try it here.

Check this DDJ article for a more elaborate way to implement this principle.

There is one way to do it by using a Javascript function as a bridge, take a look at this How−to.

1.9 Send a message from an Applet to another Applet on a


different page
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0041.html

FirstApplet encodes the message for SecondApplet in the search (or query) section of
SecondApplet.html URL. Then SecondApplet decodes the search section of its URL and extract the
message coming from FirstApplet.

FirstAppletJ.html

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="FirstAppletJ.class"
HEIGHT=100
WIDTH=300>
/APPLET/BODY/HTML

FirstAppletJ.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

1.9 Send a message from an Applet to another Applet on a different page


public class FirstAppletJ extends Applet implements
ActionListener {
Button b;
TextField t;
public void init() {
add(new Label("Message to 2nd applet :"));
add(t= new TextField(20));
add(b = new Button("Load 2nd applet"));
b.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b) {
try {
getAppletContext().showDocument
(new URL(getCodeBase(),
"SecondAppletJ.html?" + "message="
+ URLEncoder.encode(t.getText())));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

SecondAppletJ.html

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="SecondAppletJ.class"
HEIGHT=100
WIDTH=400>
/APPLET/BODY/HTML

SecondApplet.java

import java.applet.*;
import java.awt.*;
import java.net.*;

public class SecondAppletJ extends Applet {


public void init() {
Label l = new Label("Message from 1st Applet");
add (l);
TextField tf = new TextField( 50 );
add(tf);

// complete current URL


String s = getDocumentBase().toString();

// extract the search (or query) section


String theMessage = s.substring(s.indexOf('?') + 1);

// remove message header


theMessage = theMessage.substring("message=".length());

// decode the string (incomplete)


theMessage = theMessage.replace('+',' ');

/*
with JDK1.2, the decoding can be done
with java.net.URLDecoder.decode(theMessage).

1.9 Send a message from an Applet to another Applet on a different page


you to convert from a MIME format called "x−www−form−urlencoded"
to a String
To convert to a String, each character is examined in turn:
. The ASCII characters 'a' through 'z',
'A' through 'Z', and '0'
through '9' remain the same.
. The plus sign '+' is converted into a
space character ' '.
. The remaining characters are represented by 3−character
strings which begin with the percent sign,
"%xy", where xy is the two−digit hexadecimal
representation of the lower 8−bits of the character.
*/

tf.setText(theMessage);
}
}

You can try it here! NOTE : On IE, you must be connected to the Internet

The decoding is incomplete but should be Ok for simple need!

If you need to pass the message via the PARAM tag of the SecondApplet then take a look at this
How−to.

1.10 Have an applet launch an other applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0025.html

The idea is to load first a small Applet with a quick loading time, display a message to the user and
then load a larger Applet.

[HTML (testappletloader.html)

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="AppletLoader.class"
NAME="AppletLoader"
HEIGHT=200
WIDTH=200>
<PARAM NAME="appletToLoad" VALUE="SecondApplet0025">
<PARAM NAME="SecondAppletParm" VALUE="Hello World">
</APPLET></BODY></HTML>

[JAVA source (AppletLoader.java)]

import java.applet.Applet;
import java.applet.AppletStub;
import java.awt.*;

public class AppletLoader extends Applet


implements Runnable, AppletStub {
String appletToLoad;
Thread appletThread;

1.10 Have an applet launch an other applet


public void init() {
appletToLoad = getParameter("appletToLoad");
setBackground(Color.white);
}

public void paint(Graphics g) {


g.drawString("Loading the Second Applet ...", 30, 30);
}

public void run() {


try {
//
// REMOVE THIS
// for demo purpose only to see
// the "loading message!
//
Thread.sleep(2000);
//
Class appletClass = Class.forName(appletToLoad);
Applet realApplet = (Applet)appletClass.newInstance();
realApplet.setStub(this);
setLayout( new GridLayout(1,0));
add(realApplet);
realApplet.init();
realApplet.start();
}
catch (Exception e) {
System.out.println( e );
}
validate();
}

public void start(){


appletThread = new Thread(this);
appletThread.start();
}

public void stop() {


appletThread.stop();
appletThread = null;
}

public void appletResize( int width, int height ){


resize( width, height );
}
}

[SecondApplet0025.java for demonstration]

import java.awt.*;

public class SecondApplet0025 extends java.applet.Applet {


TextField tf;
public void init() {
System.out.println("Starting Second applet");
add(new Label("Second Applet"));
add(tf = new TextField( 10 ) );
String s = getParameter("SecondAppletParm");
tf.setText(s);
}
}

1.10 Have an applet launch an other applet


try it here.

1.11 Get the user name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0048.html

In application :

String username;
username = System.getProperty("user.name");

or in JDK1.5

public class Test {


public static void main(String args[]) {
com.sun.security.auth.module.NTSystem NTSystem = new
com.sun.security.auth.module.NTSystem();
System.out.println(NTSystem.getName());
}
}

In Applet there is no way unless you ask for it or use a signed applet. If you have access to a
server−side, something like an ASP page can be used to detect the current NT user name if the
client is configured correcty.

See this related HowTo for a JSP hack!

1.12 Access parameters passed in the URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0049.html

import java.applet.*;
import java.util.*;
public class AppletUrlParams extends Applet {
Hashtable searchparms;
public void init() {
// dump to the console the URL, the search and search values
// the URL http://myserver.com/mypage.html?value1=x&value2=y&value3=z
// the search value1=x&value2=y&value3=z
// the values value1=x
// value2=y
// value3=z
//
// then the values are stored in a Hashtable for easy reference.
// ex. String name = searchparms.get("value2")
doit();
}

public void doit() {


int i;
String completeURL = getDocumentBase().toString();

1.11 Get the user name


System.out.println("Complete URL: " + completeURL);
i = completeURL.indexOf("?");
if (i > −1) {
String searchURL = completeURL.substring(completeURL.indexOf("?") + 1);
System.out.println("Search URL: " + searchURL);

StringTokenizer st =
new StringTokenizer(searchURL, "
while(st.hasMoreTokens()){
String searchValue=st.nextToken();
System.out.println("value :" + searchValue);
}
initHashtable(searchURL);
dumpHashtable();
}
}

public void initHashtable(String search) {


searchparms = new Hashtable();
StringTokenizer st1 =
new StringTokenizer(search, "
while(st1.hasMoreTokens()){
StringTokenizer st2 =
new StringTokenizer(st1.nextToken(), "=");
searchparms.put(st2.nextToken(),
java.net.URLDecoder.decode(st2.nextToken()));
}
}

public void dumpHashtable() {


Enumeration keys = searchparms.keys();
System.out.println("−−−−−−−−");
while( keys.hasMoreElements() ) {
String s = (String) keys.nextElement();
System.out.println("key : " + s + " value : " + searchparms.get(s));
}
System.out.println("−−−−−−−−");
}
}

Test it here.

The resultat in the Java console should be :

key : firsparam value : Hello


key : secondparam value : World
key : thirdparam value : Hello World

A note from mm300

Access parameters passed in the URL in line String completeURL = getDocumentBase().toString();


is a trap: NS won't return the whole URL, but only domain name and directory but without .html and
parameters. In IE (5.5) it's ok. So: if we have www.domain.com/applets/win.html?winner=Maurice

getDocumentBase () will return:


NS: www.domain.com/applets/
IE: www.domain.com/applets/win.html?winner=Maurice

1.11 Get the user name


1.13 Convert an Applet to Application
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0305.html

Take this simple Applet

import java.applet.*;
import java.awt.*;

public class UnderlineText extends Applet{


String s = "Java Howto";
int x=20;
int y=50;

public void init() {


add(new Button("Real's"));
}

public void paint(Graphics g) {


g.drawString(s, x,y);
g.drawLine(x , y+2 , x+getFontMetrics(getFont()).stringWidth(s) , y+2 );
}
}

You use it with the following HTML

<HTML>
<TABLE><TR><TD>
<APPLET CODE=UnderlineText.class WIDTH=100 HEIGHT=100>
</APPLET>
/HMTL

To be able to use the same class as an application, we simply extend a Panel instead of an Applet,
put it in Frame and call the init() method.

import java.awt.*;

public class UnderlineText extends Panel{


String s = "Java Howto";
int x=20;
int y=50;

public static void main(String[] args) {


Frame f = new Frame();
f.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
};
});

UnderlineText ut = new UnderlineText();


ut.setSize(100,100); // same size as defined in the HTML APPLET
f.add(ut);
f.pack();
ut.init();
f.setSize(100,100 + 20); // add 20, seems enough for the Frame title,
f.show();
}

1.13 Convert an Applet to Application


public void init() {
add(new Button("Real's"));
}

public void paint(Graphics g) {


g.drawString(s, x,y);
g.drawLine(x , y+2 , x+getFontMetrics(getFont()).stringWidth(s) , y+2 );
}
}

1.14 Change the mouse cursor in Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0228.html

[JDK1.0.2]

// loop until the browser frame


Frame browserFrame;
Component parentComponent;
parentComponent = getParent();
while ( parentComponent != null &&
!(parentComponent instanceof Frame)) {
parentComponent = parentComponent.getParent();
}

browserFrame = (Frame) parentComponent;


browserFrame.setCursor(Frame.WAIT_CURSOR);

// CROSSHAIR_CURSOR, DEFAULT_CURSOR,
// E_RESIZE_CURSOR, HAND_CURSOR
// MOVE_CURSOR, N_RESIZE_CURSOR,
// NE_RESIZE_CURSOR, NW_RESIZE_CURSOR;
// S_RESIZE_CURSOR,SE_RESIZE_CURSOR,
// SW_RESIZE_CURSOR, TEXT_CURSOR,
// W_RESIZE_CURSOR, WAIT_CURSOR

[JDK1.1]

// setCursor is supported at the component level


setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

1.15 Use an Image as the Applet background


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0233.html

import java.applet.Applet;
import java.net.*;

// TILE BACKGROUND
// in the HTML use :
// PARAM NAME="bgImage" VALUE="images/myImage.jpg"
// in the APPLET tag

public class Tile extends Applet {

1.14 Change the mouse cursor in Applet


Image bgImage = null;

public void init() {


try {
MediaTracker tracker = new MediaTracker (this);
bgImage = getImage
(new URL(getCodeBase(), getParameter("bgImage")));
tracker.addImage (bgImage, 0);
tracker.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}
setLayout(new FlowLayout());
add(new Button("Ok"));
add(new TextField(10));
}

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


if(bgImage != null) {
int x = 0, y = 0;
while(y < size().height) {
x = 0;
while(x<size().width) {
g.drawImage(bgImage, x, y, this);
x=x+bgImage.getWidth(null);
}
y=y+bgImage.getHeight(null);
}
}
else {
g.clearRect(0, 0, size().width, size().height);
}
}
}

<HTML>
<TABLE><TR><TD>
<APPLET CODE=Tile.class WIDTH=150 HEIGHT=150>
<PARAM NAME="bgImage" VALUE="images/jht.gif">
</APPLET>
/HMTL

Try it here.

1.16 Handle the new Control Activation mechanism in IE


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0526.html

Microsoft has now licensed the technologies from Eolas, removing the click to activate requirement
in Internet Explorer. This change will be made part of the next pre−release versions of Windows
Vista SP1 and Windows XP SP3. More at IEBlog

1.16 Handle the new Control Activation mechanism in IE


The latest IE patch introduces a new behavior with APPLETS or ActiveX controls on a page. This
was done to resolve an issue concerning a patent problem with a company called Eolas.

When a web page uses the APPLET, EMBED, or OBJECT elements to load an ActiveX control, the
control's user interface is blocked until the user activates it. If a page uses these elements to load
multiple controls, each interactive control must be individually activated.

A tooltip "Click to activate and use this control" is shown. Then to activate an interactive control,
either click it or use the TAB key to set focus on it and then press the SPACEBAR or the ENTER
key. Interactive controls loaded from external script files immediately respond to user interaction
and do not need to be activated.

Check out this Microsoft's white paper on the subject.

1.16.1 Solution #1

The workaround for an APPLET (to bypass the manual activation) is to generate in Javascript the
APPLET tag but you need to generate it from an outside JS page!

<html>
<body leftmargin=0 topmargin=0 scroll=no>
<script src="myapplet.js"></script>
</body>
</html>

and the myapplet.js is

document.write
('<applet code="MyApplet.class" height="2000" width="196"></applet>')

NOTE If you uncheck the Disable Script Debugging (Internet Explorer) option in the Advanced Tab
of the Internet Options Control Panel, controls will still require activation.

NOTE: While inactive controls do not respond to direct user interaction; they do respond to script
commands.

Try a page with the regular APPLET tag here.

And now the same APPLET but with an external JS file here.

Both on the same page (same Applet), here!

The workaround suggested by Microsoft is fine with static APPLET tag but if your APPLET tag
needs to be generated by a JSP ou Servlet (to adjust the PARAM parameters for example) then
you're out of luck because the APPLET declaration is in a JS file which is a static file.

1.16.2 Solution #2

As seen in this article, all you need is to change the content from an outside file. So you need a
generic JS function to rewrite the APPLET tag with the original and that's it!

The main HTML (in BODY tag we call our "rewrite" function) :

<HTML><HEAD></HEAD>

1.16.1 Solution #1
<BODY onload="rewriteApplet();">
<p>This example "rewrite" the applet tag from an external JS.
This way you can generate the Applet tag from a JSP like before.
<P>
<script language="Javascript1.2" src="./rewriteapplet.js">
</script>
<APPLET CODE="TextFieldWithLimitApplet.class"
HEIGHT=100
WIDTH=300>
</APPLET>
</BODY></HTML>

The generic JS routine to rewrite all APPLET tags.


[rewriteapplet.js]

function rewriteApplet() {
var v=document.getElementsByTagName("applet");
for(i=0;i<v.length;i++){
var el=v[i];
el.outerHTML=el.outerHTML
}
}

Try it here!

The same principle can be used for the OBJECT tag.

This site http://www.ediy.co.nz/internet−explorer−flash−applet−activation−fix−xidc19237.html offers


a really small JS script (only 292 bytes long) to handle the situation.

IMPORTANT NOTES :
• AFAIK, this trick does not work from a FRAME!
• If you have PARAM tags associated with the applet then they will be replaced by two strange
PARAMS (_CX and _CY)! So beware... It looks that this behaviour has something to do with the
fact that the Java plugin is an ActiveX. Pre−XP SP2 installation are not supposed to do that kind
of substitution (not verified!).
• For simple applet with no param, this is an interesting generic solution.

1.16.3 Solution #3

This solution is a little bit ugly but there is no better solution when you have dynamic APPLET
PARAM generated on the server−side.

The requirement is to write only the APPLET tag from an outside JS file, the PARAMS can be
handled by the main page like before! The trick is to have 2 external JS function, one to write the
<APPLET> tag (and the static PARAM if any) and a second function to write the </APPLET>. The
enclosed dynamic PARAM parameters are generated by the JSP (ASP page).

[rewriteapplet.js]

function writeHeader(urlApplet) {
document.write
('<applet codebase="' + urlApplet + '" code="myApplet.class"')
document.write
(' width="100%" height="98%" hspace="0" vspace="0" align="middle" >')
document.write

1.16.3 Solution #3
(' <PARAM NAME="printdialog" VALUE="false">')
}

function writeFooter() {
document.write('</applet>')
}

The JSP or ASP

...
<script language="Javascript1.2"
src="<%= CONTEXT_PATH %>/scripts/rewriteapplet.js">
/script
...
<script>
writeHeader('<%=urlApplet %>');
</script>

<%
if(resultVB.isObjectInResult(idObject)) {
int i = 1;
Iterator itPages = pages.iterator();
while (itPages.hasNext()) {
String url = (String) itPages.next();
%>
<PARAM NAME="page<%=i%>" value="<%=url %>">
<%
i++;
}
}
else {
%>
<PARAM NAME="page1" value="<%=fileUrlErr %>">
<%
}
%>

<script>
writeFooter();
/script

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

1.17 Pass parameters to the Applet JVM (WIN)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0531.html

It's possible to pass some parameters to the JVM in Applet but these have to be set in the browser
and cannot be controlled by your applet. Each user that loads your applet has to adjust the JVM
args themselves.

Open the Java control panel (in Windows: Start > Control Panel > Java) and select the Java tab.
Press View button of the Applet Runtime Settings, and add the required parameters in the 4th

1.17 Pass parameters to the Applet JVM (WIN)


column, it is editable event if it's grayed.

You have to make sure that that the parameter you supply are correct, otherwise your browser will
die when it tries to open the first applet.

This can be useful to set a JVM property to resolve a compatibilty problem with graphic card like in
this bug report : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4839812.

You can force the language used in the Java console. In java control panel − java tab, you set a
parameter for JRE Applet runtime.
• Specify −Duser.language=en to override the default locale in java control panel −> java tab,
you set a parameter for JRE Applet runtime.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

1.18 See the Java Console Window Log (Java plugin)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0533.html

The Java Console Window Log is also stored on disk. On the Windows plateform, it's in the folder :

C:\Documents and Settings\


<username>\
Application Data\
Sun\
Java\
Deployment\
log

It's a file with the extension .trace

1.18 See the Java Console Window Log (Java plugin)


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

1.19 Display debugging infos for an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0597.html

Make sure that all browsers and JRE are closed. Start the Java Configuration Panel via
Start−Parameters or you can launch C:\Program Files\Java\jre[version]\bin\javacpl.exe.

On the Java tab, click to set the parameter for the applet runtime (plugin). Now add the following
parameters in the column parameters.

−Djavaplugin.trace=true −Djavaplugin.trace.option=basic|net|security|ext|liveconnect

Next, on the Advanced tab, select Java Console −> Display the console.

The next time when loading an applet, the java console will display with a full trace.

The log is stored in a file. For Windows, the file is C:\Documents and
Settings\[YourAccount]\Application Data\Sun\Java\Deployment\log\plugin[version].log/trace

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

1.19 Display debugging infos for an Applet


2 Date and Time
2.1 java−date

2.2 Have year on 4 digits from a Date object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0096.html

You need to add 1900 to it to get the 4 digit year.

int year = myDate.getYear() + 1900;

The getYear() method returns the number of years elapsed after the year 1900. So for year 2000,
mydate.getYear() will return 100. So 100 + 1900 = 2000.

2.3 Get the current Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0106.html

import java.util.Calendar;
import java.text.SimpleDateFormat;

public class DateUtils {


public static final String DATE_FORMAT_NOW = "yyyy−MM−dd HH:mm:ss";

public static String now() {


Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
return sdf.format(cal.getTime());

public static void main(String arg[]) {


System.out.println("Now : " + DateUtils.now());
}
}

Here some formatting possibilities available through the SimpleDateFormat class.

import java.util.Calendar;
import java.text.SimpleDateFormat;

public class DateUtils {

public static String now(String dateFormat) {


Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
return sdf.format(cal.getTime());

2 Date and Time


}

public static void main(String arg[]) {


System.out.println(DateUtils.now("dd MMMMM yyyy"));
System.out.println(DateUtils.now("yyyyMMdd"));
System.out.println(DateUtils.now("dd.MM.yy"));
System.out.println(DateUtils.now("MM/dd/yy"));
System.out.println(DateUtils.now("yyyy.MM.dd G 'at' hh:mm:ss z"));
System.out.println(DateUtils.now("EEE, MMM d, ''yy"));
System.out.println(DateUtils.now("h:mm a"));
System.out.println(DateUtils.now("H:mm:ss:SSS"));
System.out.println(DateUtils.now("K:mm a,z"));
System.out.println(DateUtils.now("yyyy.MMMMM.dd GGG hh:mm aaa"));
}
}

Thanks to T. Guirado for the idea.

2.4 Compute days between 2 dates


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0097.html

import java.util.*;
public class TestDate {
public static void main(String args[]){
/*
ex .
java TestDate 1999 0 1 1999 8 1
to get days between 1999−01−01 and 1999−09−01
(remember months are zero−based...)
*/

TestDate a = new TestDate(args);


}

TestDate(String args[]) {
Calendar c1 = new GregorianCalendar();;
Calendar c2 = new GregorianCalendar();;

// need more error checking here...


c1.set(Integer.parseInt(args[0]),
Integer.parseInt(args[1]) ,
Integer.parseInt(args[2]), 0, 0, 0);
c2.set(Integer.parseInt(args[3]),
Integer.parseInt(args[4]) ,
Integer.parseInt(args[5]), 0, 0, 0);

System.out.println
(daysBetween(c1.getTime(),c2.getTime()) +
" day(s) between " + args[0] + "−" + args[1] + "−" + args[2] +
" and " + args[3] + "−" + args[4] + "−" + args[5]);
}

static final long ONE_HOUR = 60 * 60 * 1000L;


public long daysBetween(Date d1, Date d2){
return ( (d2.getTime() − d1.getTime() + ONE_HOUR) /
(ONE_HOUR * 24));
}
}

2.4 Compute days between 2 dates


NOTE: The daysBetween() method works only on Dates set at midnight. One hour (known as the "fudge" factor) is added to the 2 Dates passed
as parameters to take in account the possible DLS (Day Light Saving) one hour missing.

The "right" way would be to compute the julian day number of both dates and then do the
substraction. See this HowTo. Thanks to P. Hill for the tip.

2.5 Get the number of days in a month


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0098.html

public static int daysInMonth(GregorianCalendar c) {


int [] daysInMonths = {31,28,31,30,31,30,31,31,30,31,30,31};
daysInMonths[1] += c.isLeapYear(c.get(GregorianCalendar.YEAR)) ? 1 : 0;
return daysInMonths[c.get(GregorianCalendar.MONTH)];
}

Actually, the Calendar class provides a method to that very simply. For a given Calendar or
GregorianCalendar object :

calObject.getActualMaximum(calobject.DAY_OF_MONTH)

In the Java API documentation there is a note saying that The version (getActualMaximum()) of this
function on Calendar uses an iterative algorithm to determine the actual maximum value for the
field. There is almost always a more efficient way to accomplish this (in most cases, you can simply
return getMaximum()). GregorianCalendar overrides this function with a more efficient
implementation. So it looks like it's a lot more efficient to call getActualMaximum from a
GregorianCalendar object than a Calendar object. (Thanks to P. Harris for the tip)

gregCalObject.getActualMaximum(gregCalObject.DAY_OF_MONTH)

2.6 Validate a date


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0099.html

2.6.1 Using DateFormat


import java.text.*;

public class DateUtils {


public static boolean isValidDateStr(String date) {
try {
DateFormat df =
DateFormat.getDateInstance
(DateFormat.SHORT); // YYYY−MM−DD
df.setLenient(false); // this is important!
df.parse(date);
}
catch (ParseException e) {
return false;
}
catch (IllegalArgumentException e) {
return false;

2.5 Get the number of days in a month


}
return true;
}

public static void main(String[] args) {


System.out.println(" 1900−12−13 valid ? "
+ DateUtils.isValidDateStr("1900−12−13"));

// "1990−12/13" throws a ParseException


System.out.println(" 1900−12/13 valid ? "
+ DateUtils.isValidDateStr("1900−12/13"));
// "1990−13−12" throws a IllegalArgumentException
System.out.println(" 1900−13−12 valid ? "
+ DateUtils.isValidDateStr("1900−13−12"));
/*
* output :
* 1900−12−13 valid ? true
* 1900−12/13 valid ? false
* 1900−13−12 valid ? false
*/
}
}

Using SimpleDateFormat

package com.rgagnon.howto;

import java.text.*;

public class DateUtils {


public static boolean isValidDateStr(String date, String format) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setLenient(false);
sdf.parse(date);
}
catch (ParseException e) {
return false;
}
catch (IllegalArgumentException e) {
return false;
}
return true;
}

public static void main(String[] args) {


System.out.println(" 1900−12−13 valid ? "
+ DateUtils.isValidDateStr("1900−12−13","yyyy−MM−dd"));

// "1990−12/13" throws a ParseException


System.out.println(" 1900−12/13 valid ? "
+ DateUtils.isValidDateStr("1900−12/13","yyyy−MM−dd"));
// "1990−13−12" throws a IllegalArgumentException
System.out.println(" 1900−13−12 valid ? "
+ DateUtils.isValidDateStr("1900−13−12","yyyy−MM−dd"));
/*
* output :
* 1900−12−13 valid ? true
* 1900−12/13 valid ? false
* 1900−13−12 valid ? false
*/
}
}

2.5 Get the number of days in a month


2.6.2 Using GregorianCalendar
import java.util.*;

public class jtest {


public static void main(String args[]) {
try {
GregorianCalendar gc = new GregorianCalendar();
gc.setLenient(false); // must do this
gc.set(GregorianCalendar.YEAR, 2003);
gc.set(GregorianCalendar.MONTH, 42);// invalid month
gc.set(GregorianCalendar.DATE, 1);

gc.getTime(); // exception thrown here


}
catch (Exception e) {
e.printStackTrace();
}
}
}

2.7 Determine to day of the week


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0100.html

For the day of the week for today :

GregorianCalendar newCal = new GregorianCalendar( );


int day = newCal.get( Calendar.DAY_OF_WEEK );

For the day of the week for any date :

Calendar newCal = new GregorianCalendar();


newCal.set(1997, 2, 1, 0, 0, 0);
// BUG fix in Calendar class!
newCal.setTime(newCal.getTime());
int day = newCal.get(Calendar.DAY_OF_WEEK);
/*
also available :
newCal.get( Calendar.DAY_OF_MONTH )
newCal.get( Calendar.DAY_OF_WEEK_IN_MONTH )
newCal.get( Calendar.DAY_OF_YEAR )
newCal.get( Calendar.DATE )
*/

2.8 Add/Substract Day/Month/Year to a Date


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0101.html

add() and roll() are used to add or substract values to a Calendar object.

2.6.2 Using GregorianCalendar


You specify which Calendar field is to be affected by the operation (Calendar.YEAR,
Calendar.MONTH, Calendar.DATE).

add() adds or substracts values to the specified Calendar field, the next larger field is modified when
the result makes the Calendar "rolls over".

String DATE_FORMAT = "yyyy−MM−dd";


java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance();
c1.set(1999, 0 , 20); // 1999 jan 20
System.out.println("Date is : " + sdf.format(c1.getTime()));
c1.add(Calendar.DATE,20);
System.out.println("Date + 20 days is : " + sdf.format(c1.getTime()));

To substract, simply use a negative argument.

roll() does the same thing except you specify if you want to roll up (add 1) or roll down (substract 1)
to the specified Calendar field. The operation only affects the specified field while add() adjusts
other Calendar fields. See the following example, roll() makes january rolls to december in the same
year while add() substract the YEAR field for the correct result.

String DATE_FORMAT = "yyyy−MM−dd";


java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance();
// roll down the month
c1.set(1999, 0 , 20); // 1999 jan 20
System.out.println("Date is : " + sdf.format(c1.getTime()));
c1.roll(Calendar.MONTH, false); // roll down, substract 1 month
System.out.println
("Date roll down 1 month : "
+ sdf.format(c1.getTime())); // 1999 jan 20

c1.set(1999, 0 , 20); // 1999 jan 20


System.out.println("Date is : " + sdf.format(c1.getTime()));
c1.add(Calendar.MONTH, −1); // substract 1 month
System.out.println
("Date minus 1 month : "
+ sdf.format(c1.getTime())); // 1998 dec 20

Thanks to P. Rehley for the bug fix.

2.9 Get the correct TimeZone on DateFormat


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0102.html

There is a bug in the DateFormat/SimpleDateFormat classes. We must set the TimeZone manually.

System.out.println("Good TimeZone from Calendar : " +


Calendar.getInstance().getTimeZone().getID());
DateFormat df = DateFormat.getDateInstance();
System.out.println("Bad TimeZone from DateFormat : " +
df.getTimeZone().getID());
// fix the TimeZone

2.9 Get the correct TimeZone on DateFormat


df.setCalendar(Calendar.getInstance());
System.out.println("Good TimeZone from DateFormat : " +
df.getTimeZone.getID());

2.10 Simply format a date as "YYYYMMDD"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0103.html

The format "YYYYMMDD" can be useful when sorting records or comparing 2 dates.

public static String getStrDate(GregorianCalendar c) {


int m = c.get(GregorianCalendar.MONTH) + 1;
int d = c.get(GregorianCalendar.DATE);
String mm = Integer.toString(m);
String dd = Integer.toString(d);
return "" + c.get(GregorianCalendar.YEAR) + (m < 10 ? "0" + mm : mm) +
(d < 10 ? "0" + dd : dd);
}

Thanks to Vladimir Garmaev for the bug fix

Or you can use the SimpleDateFormat from the java.text package.

import java.util.Calendar;
import java.text.SimpleDateFormat;

public class TestDate {


public static void main(String args[]){
String DATE_FORMAT = "yyyyMMdd";
SimpleDateFormat sdf =
new SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance(); // today
System.out.println("Today is " + sdf.format(c1.getTime()));
}
}

2.11 Compare 2 dates


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0104.html

import java.util.*;
import java.util.*;
import java.text.*;

public class TestDate {


public static void main(String args[]){
String DATE_FORMAT = "yyyy−MM−dd";
java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
// remember months are zero−based : 0 jan 1 feb ...
c1.set(1999, 11 , 31);
c2.set(1999, 0 , 30);

2.10 Simply format a date as "YYYYMMDD"


System.out.print(sdf.format(c1.getTime()));

if (c1.before(c2)) {
System.out.print(" is before ");
}
if (c1.after(c2)) {
System.out.print(" is after ");
}
if (c1.equals(c2)) {
System.out.print(" same as ");
}
System.out.println(sdf.format(c2.getTime()));
}
}

2.12 Parse a String to obtain a Date/GregorianCalendar object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0105.html

import java.util.Date;
import java.util.Locale;
import java.util.Calendar;
import java.text.SimpleDateFormat;

public class DateUtils {

public static Calendar parseTimestamp(String timestamp)


throws Exception {
/*
** we specify Locale.US since months are in english
*/
SimpleDateFormat sdf = new SimpleDateFormat
("dd−MMM−yyyy HH:mm:ss", Locale.US);
Date d = sdf.parse(timestamp);
Calendar cal = Calendar.getInstance();
cal.setTime(d);
return cal;
}

public static void main (String a[]) throws Exception{


String timestampToParse = "24−Feb−1998 17:39:35";
System.out.println("Timestamp : " + timestampToParse);

SimpleDateFormat sdf =
new java.text.SimpleDateFormat("yyyy−MM−dd HH:mm:ss");
System.out.println("Calendar : "
+ sdf.format(parseTimestamp(timestampToParse).getTime()));
/*
output :
Timestamp : 24−Feb−1998 17:39:35
Calendar : 1998−02−24 17:39:35
*/
}

2.12 Parse a String to obtain a Date/GregorianCalendar object


2.13 Use System time to generate unique ID
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0385.html

Since the granulaty of a PC can be as high as 55ms (down to 10ms), you can't use the System time
to generate a unique ID because of the risk of getting duplicated IDs. This can be solved by using
the following technique to make sure that the number returned is unique (in a single JVM).

public class UniqueID {


static long current= System.currentTimeMillis();
static public synchronized long get(){
return current++;
}
}

See also this HowTo

2.14 Get the day name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0403.html

import java.util.*;
import java.text.SimpleDateFormat;
import java.text.DateFormat;

public class GetDayName {

public static void main(String[] args) {


Date date1 =
(new GregorianCalendar
(1989, Calendar.OCTOBER, 17)).getTime();
Date date2 = new Date();
System.out.println
("1989−10−17 was a " + sayDayName(date1));
System.out.println("Today is a " + sayDayName(date2));
}

public static String sayDayName(Date d) {


DateFormat f = new SimpleDateFormat("EEEE");
try {
return f.format(d);
}
catch(Exception e) {
e.printStackTrace();
return "";
}
}
}

An alternate way :

import java.util.Calendar;
import java.text.SimpleDateFormat;
import java.text.DateFormat;

2.13 Use System time to generate unique ID


import java.text.DateFormatSymbols;

public class GetDayName {

public static void main(String[] args) {


String dayNames[] = new DateFormatSymbols().getWeekdays();
Calendar date2 = Calendar.getInstance();
System.out.println("Today is a "
+ dayNames[date2.get(Calendar.DAY_OF_WEEK)]);
}
}

2.15 Find the current date format


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0413.html

import java.text.*;
import java.util.*;
public class Dtest {
public static void main(String args[]) {
SimpleDateFormat df = (SimpleDateFormat)
DateFormat.getDateInstance(DateFormat.SHORT);
System.out.println("The short date format is " + df.toPattern());
Locale loc = Locale.ITALY;
df = (SimpleDateFormat)
DateFormat.getDateInstance(DateFormat.SHORT, loc);
System.out.println("The short date format is " + df.toPattern());
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.
Written and compiled by Réal Gagnon ©1998−2005
[ home ]

2.16 Get a julian date


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0506.html

A Julian date is the number of elapsed days since the beginning of a cycle of 7,980 years invented
by Joseph Scaliger in 1583. The purpose of the system is to make it easy to compute an integer
(whole number) difference between one calendar date and another calendar date.

The starting point for the first Julian cycle began on January 1, 4713 B.C. nd will end on January 22,
3268 (3268−01−22 G). The following day will begin the first day of the second Julian date period (or
7,980 year cycle).

import java.util.Calendar;
public class JulianDate {
/**
* Returns the Julian day number that begins at noon of
* this day, Positive year signifies A.D., negative year B.C.

2.15 Find the current date format


* Remember that the year after 1 B.C. was 1 A.D.
*
* ref :
* Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
// Gregorian Calendar adopted Oct. 15, 1582 (2299161)
public static int JGREG= 15 + 31*(10+12*1582);
public static double HALFSECOND = 0.5;

public static double toJulian(int[] ymd) {


int year=ymd[0];
int month=ymd[1]; // jan=1, feb=2,...
int day=ymd[2];
int julianYear = year;
if (year < 0) julianYear++;
int julianMonth = month;
if (month > 2) {
julianMonth++;
}
else {
julianYear−−;
julianMonth += 13;
}

double julian = (java.lang.Math.floor(365.25 * julianYear)


+ java.lang.Math.floor(30.6001*julianMonth) + day + 1720995.0);
if (day + 31 * (month + 12 * year) >= JGREG) {
// change over to Gregorian calendar
int ja = (int)(0.01 * julianYear);
julian += 2 − ja + (0.25 * ja);
}
return java.lang.Math.floor(julian);
}

/**
* Converts a Julian day to a calendar date
* ref :
* Numerical Recipes in C, 2nd ed., Cambridge University Press 1992
*/
public static int[] fromJulian(double injulian) {
int jalpha,ja,jb,jc,jd,je,year,month,day;
double julian = injulian + HALFSECOND / 86400.0;
ja = (int) injulian;
if (ja>= JGREG) {
jalpha = (int) (((ja − 1867216) − 0.25) / 36524.25);
ja = ja + 1 + jalpha − jalpha / 4;
}

jb = ja + 1524;
jc = (int) (6680.0 + ((jb − 2439870) − 122.1) / 365.25);
jd = 365 * jc + jc / 4;
je = (int) ((jb − jd) / 30.6001);
day = jb − jd − (int) (30.6001 * je);
month = je − 1;
if (month > 12) month = month − 12;
year = jc − 4715;
if (month > 2) year−−;
if (year <= 0) year−−;

return new int[] {year, month, day};


}

public static void main(String args[]) {

2.15 Find the current date format


// FIRST TEST reference point
System.out.println("Julian date for May 23, 1968 : "
+ toJulian( new int[] {1968, 5, 23 } ));
// output : 2440000
int results[] = fromJulian(toJulian(new int[] {1968, 5, 23 }));
System.out.println
("... back to calendar : " + results[0] + " "
+ results[1] + " " + results[2]);

// SECOND TEST today


Calendar today = Calendar.getInstance();
double todayJulian = toJulian
(new int[]{today.get(Calendar.YEAR), today.get(Calendar.MONTH)+1,
today.get(Calendar.DATE)});
System.out.println("Julian date for today : " + todayJulian);
results = fromJulian(todayJulian);
System.out.println
("... back to calendar : " + results[0] + " " + results[1]
+ " " + results[2]);

// THIRD TEST
double date1 = toJulian(new int[]{2005,1,1});
double date2 = toJulian(new int[]{2005,1,31});
System.out.println("Between 2005−01−01 and 2005−01−31 : "
+ (date2 − date1) + " days");

/*
expected output :
Julian date for May 23, 1968 : 2440000.0
... back to calendar 1968 5 23
Julian date for today : 2453487.0
... back to calendar 2005 4 26
Between 2005−01−01 and 2005−01−31 : 30.0 days
*/
}
}

There is a lot of variation around the idea of a "Julian date". You can have the Modified Julian Date
(JD) or the Truncated Julian Date (TJD). The main difference is the starting for counting the days.

Before Y2K, many applications (especially mainframe systems) were storing dates in a format
called "the Julian format". This format is a 5 digit number, consisting of a 2 digit year and a 3 digit
day−of−year number. For example, 17−July−1998 is stored as 98221, since 17−July is the 221th
day of the year. This format is not really useful since Y2K! The main reason for using the 5−digits
Julian date was to save disk space and still have a format easy to use to handle dates.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.
Written and compiled by Réal Gagnon ©1998−2005
[ home ]

2.17 Calculate the age


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0547.html

import java.util.GregorianCalendar;
import java.util.Calendar;

2.17 Calculate the age


public class CalcAge {

public static void main(String [] args) {


// remember ... months are 0−based : jan=0 feb=1 ...
System.out.println
("1962−11−11 : " + age(1962,10,11));
System.out.println
("1999−12−03 : " + age(1999,11,3));
}

private static int age(int y, int m, int d) {


Calendar cal = new GregorianCalendar(y, m, d);
Calendar now = new GregorianCalendar();
int res = now.get(Calendar.YEAR) − cal.get(Calendar.YEAR);
if((cal.get(Calendar.MONTH) > now.get(Calendar.MONTH))
|| (cal.get(Calendar.MONTH) == now.get(Calendar.MONTH)
&cal.get(Calendar.DAY_OF_MONTH) > now.get(Calendar.DAY_OF_MONTH)))
{
res−−;
}
return res;
}
}

2.18 Format a duration in ms into a string as


"Days,Hours,minutes and seconds"
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0585.html

public class TimeUtils {

public final static long ONE_SECOND = 1000;


public final static long ONE_MINUTE = ONE_SECOND * 60;
public final static long ONE_HOUR = ONE_MINUTE * 60;
public final static long ONE_DAY = ONE_HOUR * 24;

private TimeUtils() { }

/**
* converts time (in milliseconds) to
* "<w> days, <x> hours, <y> minutes and (z) seconds"
*/
public static String millisecondToDHMS(long duration) {
String res = "";
long temp = 0;
if (duration >= ONE_SECOND) {
temp = duration / ONE_DAY;
if (temp > 0) {
res = temp + " day";
if (temp > 1) {
res += "s";
}
duration −= temp * ONE_DAY;

if (duration >= ONE_MINUTE) {


res += ", ";
}

2.18 Format a duration in ms into a string as "Days,Hours,minutes and seconds"


}

temp = duration / ONE_HOUR;


if (temp > 0) {
res += temp + " hour";
if (temp > 1) {
res += "s";
}
duration −= temp * ONE_HOUR;
if (duration >= ONE_MINUTE) {
res += ", ";
}
}

temp = duration / ONE_MINUTE;


if (temp > 0) {
res += temp + " minute";
if (temp > 1) {
res += "s";
}
duration −= temp * ONE_MINUTE;

if(duration >= ONE_SECOND) {


res += " and ";
}
}

temp = duration / ONE_SECOND;


if (temp > 0) {
res += temp + " second";
if (temp > 1) {
res += "s";
}
}
return res;
}
else {
return "0 second";
}
}

public static void main (String args []) {


System.out.println(millisecondToDHMS(123));
System.out.println(millisecondToDHMS((5* ONE_SECOND) + 123));
System.out.println(millisecondToDHMS(ONE_DAY + ONE_HOUR));
System.out.println(millisecondToDHMS
(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
System.out.println(millisecondToDHMS
((4*ONE_DAY) + (3*ONE_HOUR) + (2 * ONE_MINUTE) + ONE_SECOND));
System.out.println(millisecondToDHMS
((5*ONE_DAY) + (4*ONE_HOUR) + ONE_MINUTE + (2 * ONE_SECOND) + 123));
/*
output :
0 second
5 seconds
1 day, 1 hour
1 day, 1 hour, 2 minutes
4 days, 3 hours, 2 minutes and 1 second
5 days, 4 hours, 1 minute and 2 seconds
*/
}
}

2.18 Format a duration in ms into a string as "Days,Hours,minutes and seconds"


2.19 Get the atomic time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0589.html

We connect to a publicly accessible time server on the internet and parse the result.

List of available time servers : http://tf.nist.gov/service/time−servers.html

NOTE : All users should ensure that their software NEVER queries a server more frequently than
once every 4 seconds. Systems that exceed this rate will be refused service. In extreme cases,
systems that exceed this limit may be considered as attempting a denial−of−service attack.

import java.io.*;
import java.text.*;
import java.util.*;
import java.net.*;

public final class DateUtils {


// NIST, Boulder, Colorado (time−a.timefreq.bldrdoc.gov)
public static final String ATOMICTIME_SERVER="http://132.163.4.101:13";
// NIST, Gaithersburg, Maryland (time−a.nist.gov)
// public static final String ATOMICTIME_SERVER="http://129.6.15.28:13";
public final static GregorianCalendar getAtomicTime() throws IOException{
BufferedReader in = null;

try {
URLConnection conn = new URL(ATOMICTIME_SERVER).openConnection();
in = new BufferedReader
(new InputStreamReader(conn.getInputStream()));

String atomicTime;
while (true) {
if ( (atomicTime = in.readLine()).indexOf("*") > −1) {
break;
}
}
System.out.println("DEBUG : " + atomicTime);
String[] fields = atomicTime.split(" ");
GregorianCalendar calendar = new GregorianCalendar();

String[] date = fields[1].split("−");


calendar.set(Calendar.YEAR, 2000 + Integer.parseInt(date[0]));
calendar.set(Calendar.MONTH, Integer.parseInt(date[1])−1);
calendar.set(Calendar.DATE, Integer.parseInt(date[2]));

// deals with the timezone and the daylight−saving−time


TimeZone tz = TimeZone.getDefault();
int gmt = (tz.getRawOffset() + tz.getDSTSavings()) / 3600000;
System.out.println("DEBUG : " + gmt);

String[] time = fields[2].split(":");


calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time[0]) + gmt);
calendar.set(Calendar.MINUTE, Integer.parseInt(time[1]));
calendar.set(Calendar.SECOND, Integer.parseInt(time[2]));
return calendar;
}
catch (IOException e){
throw e;
}

2.19 Get the atomic time


finally {
if (in != null) {
in.close();
}
}
}

public static void main(String args[]) throws IOException {


SimpleDateFormat sdf =
new SimpleDateFormat("yyyy−MM−dd HH:mm:ss");
System.out.println("Atomic time : " +
sdf.format(DateUtils.getAtomicTime().getTime()));
}

/*
ref : http://www.bldrdoc.gov/doc−tour/atomic_clock.html

49825 95−04−18 22:24:11 50 0 0 50.0 UTC(NIST) *

| | | | | | | | |
These are the last + | | | | | | | |
five digits of the | | | | | | | |
Modified Julian Date | | | | | | | |
| | | | | | | |
Year, Month and Day

// thanks to TrueJavaProgrammer for the idea!

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

2.19 Get the atomic time


3 AWT
3.1 java−awt

3.2 Use The CardLayout manager


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0237.html

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class CardLayoutDemo extends Applet


implements ActionListener{
Panel p1,p2,p3,p0;
Choice c1,c2;
Button b1,b2,b3, b4;
TextField t1, t2;

public void init() {


// The first Card
p1 = new myPanel(new Color(0).red,
new FlowLayout(),
100,100) ;
Choice c1 = new Choice();
c1.addItem("Option 1");
c1.addItem("Option 2");
p1.add(c1);

// The second Card


p2 = new myPanel(new Color(0).blue,
new FlowLayout(),
100, 100);
c2 = new Choice();
c2.addItem("Option A");
c2.addItem("Option B");
c2.addItem("Option C");
p2.add(c2);

// the third Card


p3 = new myPanel(new Color(0).black,
new FlowLayout(),
100, 100);
t1 = new TextField(8);
t1.setBackground(new Color(0).white);
p3.add(t1);

// Main card (receive the other)


p0 = new myPanel(new Color(0).white,
new CardLayout(0,0),
100,100);
setLayout(new FlowLayout());
add(p0);

// Add cards

3 AWT
p0.add("First card", p1);
p0.add("2nd card", p2);
p0.add("3rd card", p3);

add(b1 = new Button("card 1"));


add(b2 = new Button("card 2"));
add(b3 = new Button("card 3"));
add(b4 = new Button("Which card is selected ?"));
add(t2 = new TextField(2));
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
b4.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == b1) {
//Show the first list
((CardLayout)p0.getLayout()).show(p0, "First card");
}
else if (e.getSource() == b2) {
//Show the second list
((CardLayout)p0.getLayout()).show(p0, "2nd card");
}
else if (e.getSource() == b3) {
//Show the third list
((CardLayout)p0.getLayout()).show(p0, "3rd card");
}
else if (e.getSource() == b4) {
// get the current card
Component c[] = p0.getComponents();
int i = 0;
int j = c.length;
while (i < j) {
if (c[i].isVisible()) {
t2.setText("" + (i+1));
break;
}
else
i ++;
}
}
}
}

class myPanel extends Panel{


int w;
int h;

myPanel(Color co, LayoutManager la, int width, int height){


super();
w = width;
h = height;
setBackground(co);
setLayout(la);
}

public Dimension getMinimumSize() {


return new Dimension(w,h);
}

public Dimension getPreferredSize() {

3 AWT
return new Dimension(w,h);
}
}

<HTML>
<TABLE><TR><TD>
<APPLET CODE=CardLayoutDemo.class WIDTH=300 HEIGHT=300>
</APPLET>
/HMTL

Try it here.

3.3 Detect which card is visible with a CardLayout


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0423.html

Component getComponentShowing(Container c) {
Component[] comps = c.getComponents();
int i = 0;
while(i < comps.length &!comps[i].isVisible())
++i;
return (i == comps.length) ? null : comps[i];
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

3.4 Use Popups


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0238.html

[JDK1.1]

import java.awt.*;
import java.awt.event.*;
import java.util.Hashtable;

public class PopupTest extends Frame


implements ActionListener, MouseListener {

Hashtable popupTable = new Hashtable();

public PopupTest() {
/*
** regular menu
*/
Menu m = new Menu("file");
MenuItem item = new MenuItem("file−1");
item.addActionListener(this);
m.add(item);
item = new MenuItem("file−2");

3.3 Detect which card is visible with a CardLayout


m.add(item);
MenuBar mb = new MenuBar();
mb.add(m);

setMenuBar(mb);
setSize(100, 100);
setLayout(new BorderLayout());

/*
** label with a popup
*/
Label l = new Label("label");
addPopup(l, "label");
add(l, "North");

/*
** panel with popup
*/
Panel p = new Panel();
p.setBackground(new Color(0).red);
addPopup(p, "Panel");
add(p, "Center");

/*
** button with popup
*/
Button b = new Button("button");
addPopup(b, "button");
add(b, "South");

addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);

setVisible(true);
}

public void actionPerformed(ActionEvent e) {


/*
** handle actions related to popup
*/
System.out.println("actionPerformed, event=" + e );
System.out.println(" command=" + e.getActionCommand());
System.out.println(" param=" + e.paramString());
System.out.println(" source=" + e.getSource());
}

public void mouseClicked (MouseEvent e) { }


public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
public void mousePressed (MouseEvent e) {
mouseAction(e);
}

public void mouseReleased (MouseEvent e) {


mouseAction(e);
}

3.3 Detect which card is visible with a CardLayout


void mouseAction (MouseEvent e) {
/*
** determine if we have to show a Popup
*/
Component c = e.getComponent();
if (e.isPopupTrigger()) {
PopupMenu pm = getHash(c);
pm.show(c, c.getSize().width/2, c.getSize().height/2);
}
}

/*
** initialize a Popup for a particular Component
*/

void addPopup(Component c, String name) {


PopupMenu pm = new PopupMenu();
MenuItem mi1 = new MenuItem(name + "−1");
pm.add(mi1);
mi1.addActionListener(this);

MenuItem mi2 = new MenuItem(name + "−2");


pm.add(mi2);
mi2.addActionListener(this);

setHash(c, pm);
c.add(pm);
c.addMouseListener(this);
}

void setHash(Component c, PopupMenu p) {


/*
** associate a Component with a particular Popup
*/
popupTable.put(c, p);
}

PopupMenu getHash(Component c) {
/*
** return a Popup associated with a particular Component
*/
return (PopupMenu)(popupTable.get(c));
}

public static void main (String argv[]) {


new PopupTest();
}
}

3.5 Use a File Dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0247.html

On the Win platform, the setFilenameFilter method don't work. We must use the setFile method
instead to set a filter.

import java.awt.*;
public class UseFileDialog {

3.5 Use a File Dialog


public String loadFile
(Frame f, String title, String defDir, String fileType) {
FileDialog fd = new FileDialog(f, title, FileDialog.LOAD);
fd.setFile(fileType);
fd.setDirectory(defDir);
fd.setLocation(50, 50);
fd.show();
return fd.getFile();
}

public String saveFile


(Frame f, String title, String defDir, String fileType) {
FileDialog fd = new FileDialog(f, title, FileDialog.SAVE);
fd.setFile(fileType);
fd.setDirectory(defDir);
fd.setLocation(50, 50);
fd.show();
return fd.getFile();
}

public static void main(String s[]) {


UseFileDialog ufd = new UseFileDialog();
System.out.println
("Loading : "
+ ufd.loadFile(new Frame(), "Open...", ".\\", "*.java"));
System.out.println
("Saving : "
+ ufd.saveFile(new Frame(), "Save...", ".\\", "*.java"));
System.exit(0);
}
}

to work with the full pathname, replace

return fd.getFile();

by

return fd.getDirectory() +
System.getProperty("file.separator") + fd.getFile();

On other plateforms, setFilenameFilter may do the job, then you simply do :

fd.setFilenameFilter(new FilenameFilter(){
public boolean accept(File dir, String name){
return (name.endsWith(".jpg") || name.endsWith(".gif"));
}
});

3.6 Use TrueType font


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0270.html

[JDK1.4]
The names of the most common fonts supported by Java are TimesRoman, Courier, and Helvetica.

3.6 Use TrueType font


To add fonts, simply edit the properties.font file located in the lib of your JDK installation.

On a Windows system, to check what are the fonts available, go in the Font applet in the
Parameters folder. Choose a font and doubleclick on it. Check the name of the font. For example,
on my system, I have a font called Kaufmann, the real name is "Kaufmann BT". To be able to use
this font, I add the following line in the properties.font file in the section called # for backword
compatibility.

Kaufmann.0=Kaufmann BT, ANSI_CHARSET

To use it, in a java program :

setFont(new Font("Kaufmann", Font.BOLD, 20));

NOTE: The three common fonts are the only ones guaranteed to be supported across all systems. To be able to use other fonts, you must
modify the properties.font file and these new fonts are not cross−plateform compatibles.

[JDK1.5]
@todo

3.7 Display available fonts


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0278.html

[JDK1.1]

import java.awt.*;
public class FontList {
public static void main(String args[]) {
String[] fontNames = Toolkit.getDefaultToolkit().getFontList();
int j = fontNames.length;
for (int i = 0 ; i < j ;i++ ) {
System.out.println(fontNames[i]);
}
}
}

[JDK1.2]

import java.awt.*;
public class FontList {
public static void main(String args[]) {
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
String fontNames[] = ge.getAvailableFontFamilyNames();
int j = fontNames.length;
for (int i = 0 ; i < j ;i++ ) {
System.out.println(fontNames[i]);
}
}
}

3.7 Display available fonts


3.8 Font with 3D effect
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0312.html

import java.awt.*;
import java.applet.*;

public class SimpleApplet extends Applet {

public void init() {


setBackground(new Color(255,255,255)); // white
}

public void paint(Graphics g) {


g.setFont(new Font("Helvetica", Font.PLAIN, 42));
g.setColor(new Color(0,0,0)); // black
g.drawString("Real's HowTo", 100, 100);
g.drawString("Real's HowTo", 101, 101);
g.setColor(getBackground());
g.drawString("Real's HowTo", 100, 100);

g.setColor(new Color(0,0,0)); // black


g.drawString("Real's HowTo", 100, 200);
g.setColor(new Color(0,0,255)); // blue
g.drawString("Real's HowTo", 102, 202);
g.setColor(getBackground());
g.drawString("Real's HowTo", 101, 201);

}
}

<HTML>
<TABLE><TR><TD>
<APPLET CODE=SimpleApplet.class WIDTH=410 HEIGHT=500>
</APPLET>
</HMTL>

try it here

3.9 Use the System Clipboard


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0382.html

import java.awt.datatransfer.*;
import java.awt.*;

public class Java2Clipboard implements ClipboardOwner {


public static void main(String[] args) throws Exception {
Java2Clipboard jc = new Java2Clipboard();
jc.toClipboard();
Frame f = new Frame
("Open a text editor and paste the message from Java");
f.setSize(600,10);
f.show();
}

3.8 Font with 3D effect


public void toClipboard() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {
sm.checkSystemClipboardAccess();
}
catch (Exception e) {e.printStackTrace();}
}
Toolkit tk = Toolkit.getDefaultToolkit();
StringSelection st =
new StringSelection("Hello world from Java");
Clipboard cp = tk.getSystemClipboard();
cp.setContents(st, this);
}

public void lostOwnership(Clipboard clip, Transferable tr) {


System.out.println("Lost Clipboard Ownership?!?");
}
}

NOTE: You can only use text (no graphic) with this functionality provided by the current JDK (1.4).

3.10 Maximize a Frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0222.html

// place this in the Frame constructor, after the show()


this.move(0,0);
resize(Toolkit.GetDefaultToolkit().getScreenSize());

JDK1.2 offers a new method, setState(), to minimize or maximize a Frame.

frame.setState(Frame.ICONIFIED); // minimize the frame

Latest JDK provides more ways to do that.

JDK1.4

import java.awt.*;
...
GraphicsDevice device;
Frame frame = new Frame();
device =
GraphicsEnvironment.
getLocalGraphicsEnvironment().
getDefaultScreenDevice();
if ( device.isFullScreenSupported() ) {
device.setFullScreenWindow(frame);
}
else {
System.err.println("Full screen not supported");
}

The "full−screen" Frame is in exclusive mode. In this mode you can change the resolution

import java.awt.*;

3.10 Maximize a Frame


class ScreenRes {
public static void main(String args[]) {
new ScreenRes().doit();
}

public void doit() {


Frame frame = new Frame();
GraphicsDevice device;
device =
GraphicsEnvironment.
getLocalGraphicsEnvironment().
getDefaultScreenDevice();
if ( device.isFullScreenSupported() ) {
device.setFullScreenWindow(frame);
if (device.isDisplayChangeSupported()) {
device.setDisplayMode(
new DisplayMode( 1024, 768,
8, // bitDepth − 8 bits 256 colors
DisplayMode.REFRESH_RATE_UNKNOWN ));

}
else {
System.err.println("Change display mode not supported");
}
}
else {
System.err.println("Full screen not supported");
}
}
}

When the JFrame is destroyed, the original resolution is restored.

To remove (manually) the "exclusive mode" on the JFrame :

device.setFullScreenWindow(null);

SWING jdk1.3

JFrame frame = new JFrame();


frame.setExtendedState(Frame.MAXIMIZED_BOTH);
// can be
// frame.setExtendedState(Frame.MAXIMIZED_HORIZ);
// frame.setExtendedState(Frame.MAXIMIZED_VERT);

3.11 Center a Frame/Dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0223.html

// centers the dialog within the screen [1.1]


// (put that in the Frame/Dialog class)
public void centerScreen() {
Dimension dim = getToolkit().getScreenSize();
Rectangle abounds = getBounds();
setLocation((dim.width − abounds.width) / 2,
(dim.height − abounds.height) / 2);
super.setVsible(true);

3.11 Center a Frame/Dialog


requestFocus();
}

// centers the dialog within the parent container [1.1]


// (put that in the Dialog class)
public void centerParent () {
int x;
int y;

// Find out our parent


Container myParent = getParent();
Point topLeft = myParent.getLocationOnScreen();
Dimension parentSize = myParent.getSize();

Dimension mySize = getSize();

if (parentSize.width > mySize.width)


x = ((parentSize.width − mySize.width)/2) + topLeft.x;
else
x = topLeft.x;

if (parentSize.height > mySize.height)


y = ((parentSize.height − mySize.height)/2) + topLeft.y;
else
y = topLeft.y;

setLocation (x, y);


super.setVsible(true);
requestFocus();
}

New with JDK1.4, JDialog has method to position a JDialog relative to a parent. For a JWindow or a
JFrame with no parent, then

f.setSize(100,100);
f.setLocationRelativeTo(NULL);

3.12 Close a Frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0225.html

[JDK1.0.2]

public boolean handleEvent(Event evt) {


if (evt.id == Event.WINDOW_DESTROY) {
System.exit(0);
return true;
}
return super.handleEvent(evt);
}

[JDK1.1 Method 1]

public aFrame extends Frame implements WindowListener {


public aFrame(){
addWindowListener( this );
}

3.12 Close a Frame


public void windowActivated(WindowEvent e){}
public void windowDeactivated(WindowEvent e){}
public void windowOpened(WindowEvent e){}
public void windowClosing(WindowEvent e){ System.exit(0); }
public void windowClosed(WindowEvent e){}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
}

[JDK1.1 Method 2]

public class aFrame extends Frame {


public aFrame(){
addWindowListener( new Terminate() );
}
}

class Terminate extends WindowAdapter{


public void windowClosing(WindowEvent e){
System.exit(0);
}
}

[JDK1.1 Method 3]

public class aFrame extends Frame {


public aFrame() {
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
}

For a Dialog or a Window, a System.exit(0) may not be appropriate, call the dispose() method
instead.

class SimplePopUp extends Dialog {


SimplePopUp() {
super(new Frame(), "simple popup");
this.addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
}
}
);
}

3.13 Call events on a Frame from a Panel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0268.html

3.13 Call events on a Frame from a Panel


A component on a Panel can easily call events on the parent Frame. This way, we can put all the
logic in one place. In this example, a Frame contains 1 button and a Panel with 2 buttons on it. The
first button on the Panel will generate an event for the button on the Frame while the second panel
button will trigger a request to close the Frame and the application.

[TestEventPanel.java]

import java.awt.*;
import java.awt.event.*;

public class TestEventPanel extends Panel {


Button b1,b2;

TestEventPanel(){
super();
setLayout(new FlowLayout());
setBackground(new Color(0).black);
b1 = new Button("call event on the frame");
add(b1);
b2 = new Button("close the parent frame");
add(b2);
}
}

The Frame after adding the Panel, will act as an ActionListener for events for the 2 Panel buttons.

[TestEventFrame.java]

import java.awt.*;
import java.awt.event.*;

public class TestEventFrame extends Frame implements


ActionListener, WindowListener {
TestEventPanel p1;
Button b1;

TestEventFrame(String title){
super(title);
setLayout(new FlowLayout());
p1 = new TestEventPanel();

b1 = new Button("A dummy button");


add(b1);

// the Panel with 2 buttons on it


add(p1);
createFrame();

// add the actionlistener


b1.addActionListener(this);
p1.b1.addActionListener(this);
p1.b2.addActionListener(this);
addWindowListener(this);
}

void createFrame() {
Dimension d = getToolkit().getScreenSize();
setLocation(d.width/4,d.height/3);
setSize(400,100);
setVisible(true);
}

3.13 Call events on a Frame from a Panel


public void actionPerformed(ActionEvent ae){

if (ae.getSource()==p1.b1) {
System.out.println(ae.getActionCommand());
ActionEvent new_ae =
new ActionEvent (b1,
ActionEvent.ACTION_PERFORMED,
"Panel b1 is calling the dummy button");
b1.dispatchEvent (new_ae);
}

if (ae.getSource()==b1) {
System.out.println("dummy receive :" + ae.getActionCommand());
}

if (ae.getSource()==p1.b2) {
System.out.println(ae.getActionCommand());
processEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
}

public void windowClosing(WindowEvent e) {


this.dispose();
System.exit(0);
}
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { }
public void windowClosed(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowOpened(WindowEvent e) { }
}

and finally

[Java0268.java]

import java.awt.*;

public class Java0268 extends java.applet.Applet {


TestEventFrame myTestEventFrame;

public void init() {


myTestEventFrame =
new TestEventFrame("TestEvent Frame");
}
}

Try it here.

3.14 Set the small top−left icon on a Frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0246.html

There is a bug in JDK1.0.2 for Windows, so you are stuck with the JAVA coffee cup.

3.14 Set the small top−left icon on a Frame


In JDK1.1, this is fixed. You have to use a GIF file (not ICO file!). The GIF dimension should be
16x16.

You set the icon (probably in the Frame constructor) with :

setIconImage(Toolkit.getDefaultToolkit().getImage("myIcon.gif"));

To get the image from a Jar instead, do :

setIconImage
(Toolkit.getDefaultToolkit()
.getImage(getClass().
getResource("images/myIcon.gif")));

3.15 Prevent a Frame to be resized


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0252.html

import java.awt.*;
import java.awt.event.*;

public class TestNoMaximize {


MyFrame theFrame;

public static void main (String args[]){


TestNoMaximize t = new TestNoMaximize();
t.theFrame = new MyFrame("A Dummy Frame");
t.theFrame.setVisible(true);
}
}

class MyFrame extends Frame {


public MyFrame(String title){
super(title);
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
// no minimize or maximize
this.setResizable(false);
this.setSize(200,200);
}

public void paint(Graphics g) {


g.drawString("try to resize me...", 50, 50);
}
}

There is no way to allow minimizing but not maximizing unless you trap the maximizing in the paint
method and then resize to the original size.

import java.awt.*;
import java.awt.event.*;

3.15 Prevent a Frame to be resized


public class TestNoMaximize {
MyFrame theFrame;

public static void main (String args[]){


TestNoMaximize t = new TestNoMaximize();
t.theFrame = new MyFrame("A Dummy Frame");
t.theFrame.setVisible(true);
}
}

class MyFrame extends Frame {


public MyFrame(String title){
super(title);
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
this.setSize(200,200);
}

public void paint(Graphics g) {


Dimension d = this.getSize();
if (d.getHeight() != 200 &d.getWidth() != 200)
this.setSize(200,200);
g.drawString("try to maximize me...", 50, 50);
}
}

NOTE: These How−to may not work with the Microsoft JVM. It's a feature...

3.16 Embed an image into a Frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0302.html

A given image is tiled as the frame background.

The result is not too good with Label...

import java.awt.*;
import java.awt.event.*;

public class ImageFrame extends Frame {

private Image image;

ImageFrame() {
super("");
try {
MediaTracker mt = new MediaTracker (this);
// for Applet, change the method to retrieve the image
// and of course use your own image!
image = Toolkit.getDefaultToolkit().getImage("images/jht.gif");
mt.addImage(image, 0);
mt.waitForID(0);
}

3.16 Embed an image into a Frame


catch (Exception e) {
e.printStackTrace();
}

setLayout(new FlowLayout());

add(new TextField(10));
add(new Button("hello"));
add(new List(20));
add(new TextArea(20,20));
// Label may not look too good ...
add(new Label("Hello"));
setSize(500, 500);

addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// change this for an Applet
System.out.println("Bye.");
System.exit(0);
}
}
);
}

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


if(image != null) {
int x = 0, y = 0;
while(y < getSize().height) {
x = 0;
while(x< getSize().width) {
g.drawImage(image, x, y, this);
x= x + image.getWidth(null);
}
y = y + image.getHeight(null);
}
}
else {
g.clearRect(0, 0, getSize().width, getSize().height);
}
}

static public void main(String[] args) {


ImageFrame iframe = new ImageFrame();
iframe.setVisible(true);
}
}

The result :

3.16 Embed an image into a Frame


3.17 Display a message box
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0242.html

If using Swing then look at the JOptionPane component.

With plain AWT, this simple class can be used as a Message Box.

import java.awt.*;
import java.awt.event.*;

public class MsgBox extends Dialog implements ActionListener {


private Button ok,can;
public boolean isOk = false;

/*
* @param frame parent frame
* @param msg message to be displayed
* @param okcan true : ok cancel buttons, false : ok button only
*/
MsgBox(Frame frame, String msg, boolean okcan){
super(frame, "Message", true);
setLayout(new BorderLayout());
add("Center",new Label(msg));
addOKCancelPanel(okcan);
createFrame();
pack();
setVisible(true);
}

MsgBox(Frame frame, String msg){


this(frame, msg, false);

3.17 Display a message box


}

void addOKCancelPanel( boolean okcan ) {


Panel p = new Panel();
p.setLayout(new FlowLayout());
createOKButton( p );
if (okcan == true)
createCancelButton( p );
add("South",p);
}

void createOKButton(Panel p) {
p.add(ok = new Button("OK"));
ok.addActionListener(this);
}

void createCancelButton(Panel p) {
p.add(can = new Button("Cancel"));
can.addActionListener(this);
}

void createFrame() {
Dimension d = getToolkit().getScreenSize();
setLocation(d.width/3,d.height/3);
}

public void actionPerformed(ActionEvent ae){


if(ae.getSource() == ok) {
isOk = true;
setVisible(false);
}
else if(ae.getSource() == can) {
setVisible(false);
}
}

public static void main(String args[]){


Frame f = new Frame();
f.setSize(200,200);
f.setVisible(true);
MsgBox message = new MsgBox
(f , "Hey you user, are you sure ?", true);

if (message.isOk)
System.out.println("Ok pressed");

if (!message.isOk)
System.out.println("Cancel pressed");

message.dispose();
}
}

3.18 Display a Splash screen


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0267.html

This Splash class display a window containing a specified image while a parent Frame is doing its

3.18 Display a Splash screen


initialization. When the parent is activated, the Splash window is destroyed.

[JDK1.1]
import java.awt.*;
import java.awt.event.*;

public class Splash extends Window {


private Image splashImage;
private int imgWidth, imgHeight;
private String imgName;
private static final int BORDERSIZE = 5;
private static final Color BORDERCOLOR = Color.blue;
Toolkit tk;

public Splash(Frame f, String imgName) {


super(f);
this.imgName = imgName;
tk = Toolkit.getDefaultToolkit();
splashImage = loadSplashImage();
showSplashScreen();
f.addWindowListener(new WindowListener());
}
public Image loadSplashImage() {
MediaTracker tracker = new MediaTracker(this);
Image result;
result = tk.getImage(imgName);
tracker.addImage(result, 0);
try {
tracker.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}
imgWidth = result.getWidth(this);
imgHeight = result.getHeight(this);
return (result);
}

public void showSplashScreen() {


Dimension screenSize = tk.getScreenSize();
setBackground(BORDERCOLOR);
int w = imgWidth + (BORDERSIZE * 2);
int h = imgHeight + (BORDERSIZE * 2);
int x = (screenSize.width − w) /2;
int y = (screenSize.height − h) /2;
setBounds(x, y, w, h);
setVisible(true);
}

public void paint(Graphics g) {


g.drawImage(splashImage, BORDERSIZE, BORDERSIZE,
imgWidth, imgHeight, this);
}

class WindowListener extends WindowAdapter {


// was windowActivated, thanks to H.Grippa for the fix!
public void windowOpened(WindowEvent we) {
setVisible(false);
dispose();
}
}
}

3.18 Display a Splash screen


The following example use this image (jht.gif) as the splash image.

import java.awt.*;
import java.awt.event.*;

public class TestSplash {


MyFrame theFrame;

public static void main (String args[]){


TestSplash t = new TestSplash();
t.createMainFrame();
}

private void createMainFrame() {


theFrame = new MyFrame("A Dummy Frame");
theFrame.setVisible(true);
}

class MyFrame extends Frame {


Splash mySplash;
public MyFrame(String title){
super(title);
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
mySplash = new Splash(this, "jht.gif");

// dummy delay so we can see the Splash!


for(int i = 0; i < 3000; i++) {
System.out.println(i) ;
}
setSize(200,200);
}
}

3.19 Limit TextField input to numeric value


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0226.html

[JDK1.0.2]

// You still have to trap the InvalidNumberFormat


// Exception when converting textfield content to numeric
// bug fixed! 980211 thanks to JM Guerra Chapa
import java.awt.*;
public class app extends java.applet.Applet {
TextField textField1;

public void init() {


setLayout(new FlowLayout());
textField1 = new TextField(10);

3.19 Limit TextField input to numeric value


add(textField1);
}

public boolean handleEvent(Event event) {


if (event.target==textfield1 &event.id == Event.KEY_PRESS) {
char c = (char)event.key;
if (c >= '0' &c <= '9') {
// keep digit
return super.handleEvent(event);
}
else if (Character.isISOControl(c)) {
// keep control character (like del, bksp)
return super.handleEvent(event);
}
else {
// discard Character
return true;
}
}
return super.handleEvent(event);
}
}

[JDK1.1]
thanks to Lionel Giltay

import java.awt.TextField ;
import java.awt.event.KeyAdapter ;
import java.awt.event.KeyEvent ;

public class NumericTextField extends TextField


{
public NumericTextField (String _initialStr, int _col)
{
super (_initialStr, _col) ;

this.addKeyListener(new KeyAdapter()
{
public void keyTyped (KeyEvent e)
{
char c = e.getKeyChar() ;

if (! ((c==KeyEvent.VK_BACK_SPACE) || (c==KeyEvent.VK_DELETE)
|| (c== KeyEvent.VK_ENTER) || (c == KeyEvent.VK_TAB)
|| (Character.isDigit(c))))
{
e.consume() ;
}
}
});
}

public NumericTextField (int _col)


{
this ("", _col) ;
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

3.19 Limit TextField input to numeric value


3.20 Limit TextField input to a maximum length
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0227.html

[JDK11]

import java.awt.*;
import java.awt.event.*;

public class TextFieldWithLimit extends TextField


implements KeyListener {
private int maxLength;
public TextFieldWithLimit
(String initialStr,int col,int maxLength) {
super(initialStr,col);
this.maxLength = maxLength;
addKeyListener(this);
}
public TextFieldWithLimit (int col,int maxLength) {
this("",col,maxLength);
}

public void keyPressed(KeyEvent e) {


char c = e.getKeyChar();
int len = getText().length();
if (len <maxLength) {
return;
}
else {
if((c==KeyEvent.VK_BACK_SPACE)||
(c==KeyEvent.VK_DELETE) ||
(c==KeyEvent.VK_ENTER)||
(c==KeyEvent.VK_TAB)||
e.isActionKey())
return;
else {
e.consume();
}
}
}
public void keyReleased(KeyEvent e) { }
public void keyTyped(KeyEvent e) { }
}

3.21 React to the ENTER key in a Textfield


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0253.html

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class testENTER extends Applet


implements KeyListener {

3.20 Limit TextField input to a maximum length


TextField t;
public void init(){
TextField t = new TextField("press ENTER");
add(t);
t.addKeyListener(this);
}
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ENTER) {
Toolkit.getDefaultToolkit().beep();
System.out.println("ENTER pressed");
}
}
}

Or the short version using the KeyAdapter class.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class testENTER extends Applet{


TextField t;
public void init(){
TextField t = new TextField("press ENTER");
add(t);
t.addKeyListener
(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ENTER) {
Toolkit.getDefaultToolkit().beep();
System.out.println("ENTER pressed");
}
}
}
);
}
}

3.22 Make the ENTER key act like the TAB key
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0254.html

First create a TextField that listen to the Enter and react like a Tab key [JDK11]

import java.awt.*;
import java.awt.event.*;

public class MyTextField extends TextField {


MyTextField(int len) {
super(len);
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
int key = evt.getKeyCode();
if (key == KeyEvent.VK_ENTER)

3.22 Make the ENTER key act like the TAB key
transferFocus();}});
}
}

to use it, try something like this

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class TestEnterAsTab extends Applet {


MyTextField t1, t2;
public void init(){
MyTextField t1 = new MyTextField(10);
MyTextField t2 = new MyTextField(10);
add(t1);add(t2);
}
}

3.23 Reset all textfields in one shot


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0274.html

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class FirstApplet extends Applet implements


ActionListener {
TextField t1;
TextField t2;
TextField t3;
TextField t4onPanel;
Panel p1;
Button b;

public void init() {


add(t1= new TextField(20));
add(t2= new TextField(20));
add(t3= new TextField(20));
t4onPanel = new TextField(20);
p1 = new Panel();
p1.setBackground(new Color(0).yellow);
p1.add(t4onPanel);
add(p1);
add(b = new Button("reset TextFields"));
b.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b)
resetTextFields(this);
}

public static void resetTextFields(Container c) {


Component [] components = c.getComponents();
for (int i = 0; i <components.length; i++ ) {
if (components[i] instanceof Container)

3.23 Reset all textfields in one shot


resetTextFields((Container) components[i]) ;
else if (components[i] instanceof TextField)
((TextField) components[i]).setText("") ;
}
}
}

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="FirstApplet.class"
NAME="myApplet"
HEIGHT=200 WIDTH=200>
</APPLET></BODY></HTML>

3.24 Limit a TextField to Uppercase


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0279.html

[JDK1.1]
import java.awt.*;
import java.awt.event.*;

public class UpperTF extends Frame {


public static void main(String argv[]) {
new UpperTF().setVisible(true);
}

public UpperTF() {
setLayout(new FlowLayout());
TextField tf = new TextField(10);
add(tf);
tf.addKeyListener(
new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (Character.isLetter(e.getKeyChar()))
e.setModifiers(Event.SHIFT_MASK);
}
});
pack();

addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}

public Dimension getPreferredSize() {


return new Dimension(200,200);
}
}

3.24 Limit a TextField to Uppercase


3.25 Have an ImageButton
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0245.html

This implementation of an ImageButton requires JDK1.1 and is a good example of the new Event
architecture. This ImageButton needs 2 GIF images representing the normal and pressed state
( ). Also a method to disable the button by using a special filter is given.

[ImageButton.java]

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.net.*;

public class ImageButton extends Canvas {


protected ActionListener actionListener = null;
int w,h;
boolean clicked;
boolean down;
boolean enabled;
Image UPimage;
Image DOWNimage;
Image disabledimage;

public ImageButton(URL up_b, URL down_b) {


clicked=false;
down=false;
enabled=true;
InitImage(up_b,down_b);
setSize(w,h);
addMouseListener(new ImageButtonMouseListener());
addMouseMotionListener(new ImageButtonMouseMotionListener());
}

public void InitImage(URL up, URL down) {


MediaTracker tracker;
try {
UPimage = getToolkit().getImage(up);
DOWNimage = getToolkit().getImage(down);
tracker = new MediaTracker(this);
tracker.addImage(UPimage,0);
tracker.addImage(DOWNimage,1);
tracker.waitForAll();
}
catch (InterruptedException e) {
e.printStackTrace();
}
disabledimage=createImage(new FilteredImageSource
(UPimage.getSource(),new ImageButtonDisableFilter()));
w=UPimage.getWidth(this);
h=UPimage.getHeight(this);
}

public void paint(Graphics g) {


if (down) {
g.drawImage(DOWNimage,0,0,this);
}
else {

3.25 Have an ImageButton


if (enabled) {
g.drawImage(UPimage,0,0,this);
}
else {
g.drawImage(disabledimage,0,0,this);
}
}
}

public void setEnabled(boolean b) {


enabled=b;
repaint();
}

public boolean isEnabled() {


return (enabled);
}

public void addActionListener(ActionListener l) {


actionListener =
AWTEventMulticaster.add(actionListener,l);
}
public void removeActionListener(ActionListener l) {
actionListener =
AWTEventMulticaster.remove(actionListener, l);
}

public class ImageButtonMouseListener extends MouseAdapter {


public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
if ((p.x < w)&&(p.y < h)&&(p.x > 0)&&(p.y > 0)&&(enabled==true)) {
clicked=true;
down=true;
repaint();
}
}
public void mouseReleased(MouseEvent e) {
Point p = e.getPoint();
if (down) {
down=false;
repaint();
}
if ((p.x < w)&&(p.y < h)&&(p.x > 0)&&(p.y > 0)&&(clicked==true)) {
ActionEvent ae =
new ActionEvent(e.getComponent(),0,"click");
if (actionListener != null) {
actionListener.actionPerformed(ae);
}
}
clicked=false;
}
}
public class ImageButtonMouseMotionListener extends
MouseMotionAdapter {
public void mouseDragged(MouseEvent e) {
Point p = e.getPoint();
if ((p.x < w)&&(p.y < h)&&(p.x > 0)&&(p.y > 0)&&(clicked==true)) {
if (down==false) {
down=true;
repaint();
}
}
else {

3.25 Have an ImageButton


if (down==true) {
down=false;
repaint();
}
}
}
}

public Dimension getPreferredSize() {


return (new Dimension(UPimage.getWidth(this),
UPimage.getHeight(this)));
}

public Dimension getMinimumSize() {


return getPreferredSize();
}

class ImageButtonDisableFilter extends RGBImageFilter {


public ImageButtonDisableFilter() {
canFilterIndexColorModel=true;
}
public int filterRGB(int x, int y, int rgb) {
return (rgb &~0xff000000) | 0x80000000;
}
}
}

[TestImageButton.java]

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.net.*;

public class TestImageButton extends Applet


implements ActionListener,ItemListener {
ImageButton ib;
Checkbox c;

public void init() {


setLayout(new FlowLayout());
try {
ib = new ImageButton
(new URL(getCodeBase(), "Gumby.gif"),
new URL(getCodeBase(), "Gumbyblu.gif"));
c = new Checkbox("disable");
ib.addActionListener(this);
c.addItemListener(this);
add(ib);
add(c);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == ib) System.out.println("Click ImageButton");
}

public void itemStateChanged(ItemEvent ie) {


ib.setEnabled(!ib.isEnabled());

3.25 Have an ImageButton


}
}

3.26 Reset a checkbox group


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0221.html

import java.applet.*;
import java.awt.*;

public class radio extends Applet {


CheckboxGroup cbg;
public void init() {
add(new Label("Payment mode?"));
cbg = new CheckboxGroup();
add(new Checkbox("Visa", cbg, false));
add(new Checkbox("Mastercard", cbg, false));
add(new Checkbox("American Express", cbg, false));
add(new Checkbox("Cash", cbg, true));
add(new Button("clear radio"));
}

public boolean action(Event e, Object o) {


if (o.equals("clear radio")){
Checkbox current = cbg.getCurrent();
cbg.setCurrent( null );
current.setState( false );
return true;
}
return false;
}
}

3.27 Set the listbox width


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0231.html

The width can be specified via the preferredSize method. This class lets you specify a font (fixed
pitch) and calculate the appropriate width in pixels.

class myListbox extends List {


int width;
int height;
public myListbox(int r, int n, boolean m){
// (r) line number, (n) width, (m) multiselect
this(r, n, m, new Font("Courier", Font.BOLD, 10));
width = n;
height = r;
}

public myListbox(int r, int n, boolean m, Font f){


super(r,m);
width = n;
height = r;

3.26 Reset a checkbox group


setFont(f);
}

public Dimension preferredSize (){


FontMetrics fm=getFontMetrics(getFont());
// the character W used as reference
return new Dimension
(fm.charWidth('W')*width, fm.getHeight()*height);
}
}

3.28 Align the column in a List


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0244.html

The trick is to use a FIXED width character set like "Courier".

ml = new List();
my.setFont(new Font("Courier", Font.BOLD, 10));

When inserting a line, we simply pad spaces as needed. Here the first column is 20 characters
wide, the second 10 and the last one the remaining.

insertItem(ml, "ARCHIVE", "STATUS", "PORT");

public void insertItem(List lbx,


String col1, String col2, String col3) {
String spaces2 = " ";
String spaces10 = " ";
String spaces20 = spaces10 + spaces10;
lbx.addItem(col1 +
spaces20.substring(0,20−col1.length()) +
spaces2 +
col2 +
spaces10.substring(0,10−col2.length()) +
col3);
}

In real life, the preferred way would be to extend the java.awt.List and override the addItem method.

3.29 Have a srolling text display


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0271.html

A srolling text display can be used to log informations or events. In this snippet, we are using a List
component to display the data. We are keeping only the last 10 events. It's a good idea to limit the
amount of data kept in the List , in fact we have no choice because the maximum capacity is about
32k (Win).

import java.awt.*;

3.28 Align the column in a List


import java.awt.event.*;

public class TelnetLikeDisplay extends Applet


implements ActionListener {
Button b;
int i = 0;
static final int LINE_BUFFERED = 10;
static final int LINE_DISPLAYED = LINE_BUFFERED − 1;
List l;

public void init() {


setLayout(new FlowLayout(FlowLayout.LEFT));
add(b = new Button("New Line"));
b.addActionListener(this);
add(l = new List(5));
l.setSize(100,100);
l.setForeground(new Color(0).yellow);
l.setBackground(new Color(0).black);
}

public void actionPerformed(ActionEvent ae) {


String newLine = "Line #" + i;
if (i <LINE_BUFFERED) {
l.addItem(newLine);
l.makeVisible(i);
}
else {
l.remove(0);
l.add(newLine, LINE_DISPLAYED);
l.makeVisible(LINE_DISPLAYED);
}
i++;
}
}

3.30 Label dynamic resizing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0232.html

If there is no Layout Manager installed, try something like this:

aLabel.setText ("A very long label");


aLabel.resize (aLabel.preferredSize());

With a Layout Manager, you have to validate() the layout to redraw the components invalidated.

Label aLabel = new Label("short label");


aLabel.setText ("A very long label");
this.validate();

While this method works in Netscape or the Appletviewer, on IE4/5 there is no resizing. You may
want to try this instead (thanks to Dan for the tip):

Label aLabel = new Label("short label");


aLabel.setText(""A very long label");
aLabel.invalidate(); // make sure the component is marked as non−valid
this.validate();

3.30 Label dynamic resizing


This example how to change a Label or a String drawn with the drawString method by clicking on a
button.

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class TestPaint extends Applet


implements ActionListener {
MyPanel p;
Label l;
Button b1, b2;
TextField t1, t2;

public void init() {


setLayout(new FlowLayout());
t1 = new TextField(10);
b1 = new Button("Change Label");
add(t1); add(b1);
t2 = new TextField(10);
b2 = new Button("Change drawString");
add(t2); add(b2);
l = new Label("label text");
add(l);

// a Panel with a drawString call


p = new MyPanel();
add(p);
b1.addActionListener(this);
b2.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == b1) {
l.setText(t1.getText());
l.invalidate();
validate();
}
if (e.getSource() == b2) {
p.someString = t2.getText();
p.repaint();
}
}
}

class MyPanel extends Panel {


String someString = "drawstring";

MyPanel() { super(); }

public void paint (Graphics g) {


g.drawString(someString, 10,50);
}

public Dimension getPreferredSize() {


return new Dimension (100,100);
}
}

3.30 Label dynamic resizing


3.31 Make a TextArea "word−wrap"
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0241.html

Simply create the TextArea with no horizontal scrollbar.

myTextArea = new TextArea


("text", 3 , 100 , TextArea.SCROLLBARS_VERTICAL_ONLY);

3.32 Synchronize a TextArea vs a Choice


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0281.html

import java.awt.*;
import java.awt.event.*;

class ChoiceEx extends Frame implements ItemListener {


Choice choice = new Choice();
TextArea textarea = new TextArea();
ChoiceEx() {
super("");

for (int i=0; i<10; i++) {


choice.addItem("item "+i);
}
// Set listeners
choice.addItemListener(this);
add(choice, BorderLayout.SOUTH);
add(textarea, BorderLayout.NORTH);
pack();
setVisible(true);
}

// When list or choice is updated


public void itemStateChanged(ItemEvent evt) {
textarea.setText("Item #" + choice.getSelectedIndex());
}

static public void main(String[] args) {


new ChoiceEx();
}
}

3.33 Display underlined text


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0258.html

import java.applet.*;
import java.awt.*;

public class underlineText extends Applet{


String s = "Underlined text";

3.31 Make a TextArea "word−wrap"


int x=10;
int y=10;

public void init() {}

public void paint(Graphics g) {


g.drawString(s, x,y);
g.drawLine(x , y+2 , x+getFontMetrics(getFont()).stringWidth(s) , y+2 );
}
}

Check this How−to for underlined text with a Label component.


Check this How−to for underlined text in Swing.

3.34 Display vertical text


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0259.html

import java.applet.*;
import java.awt.*;

public class verticalText extends Applet {


String s = "Vertical text";
int x=10;
int y=10;
int v;
public void init() {}

public void paint(Graphics g) {


v=g.getFontMetrics(getFont()).getHeight()+1;
System.out.println(v);
int j =0;
int k= s.length();
while(j < k+1) {
if (j == k)
g.drawString(s.substring(j),x, y+(j*v));
else
g.drawString(s.substring(j,j+1),x, y+(j*v));
j++;
}
}
}

[JDK1.4]

import java.awt.geom.AffineTransform;
import java.awt.Graphics2D;

public void paint(Graphics g){


Graphics2D g2d = (Graphics2D)g;

// clockwise 90 degrees
AffineTransform at = new AffineTransform();
// thanks to M.C. Henle for the bug fix!
at.setToRotation(−Math.PI/2.0, width/2.0, height/2.0);
g2d.setTransform(at);
g2d.drawString("Vertical text", x, y);

3.34 Display vertical text


}

3.35 Have Label with many lines


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0269.html

The Label component included in the AWT do not support "\n" in its definition. The following class
implements a multi−line Label. Lines are separated byt the token "\n". Lines can be left, right or
center justified. Plus, there is a possibility to have a border around the label.

import java.awt.*;
import java.util.*;

public class MultiLineLabel extends Canvas {


public static final int LEFT = 0;
public static final int CENTER = 1;
public static final int RIGHT = 2;
private String text;
private String lines[];
private int num_lines;
private int line_height;
private int line_ascent;
private int line_widths[];
private int max_width;
private int alignment;
private boolean border;
private int topBottomMargin;
private int leftRightMargin;
private int x = 0;
private int y = 0;
Dimension offDimension;
Image offImage;
Graphics offGraphics;
Color borderColor = new Color(0).black;

public MultiLineLabel(String s, int i, boolean b) {


// s the label
// i alignement MultiLineLabel.CENTER, MultiLineLabel.RIGHT,
// MultiLineLabel.LEFT
// default MultiLineLabel.LEFT
// b border present or not
setAlignment(i);
setText(s);
setBorder(b);
}

public MultiLineLabel(String string, int i) {


this(string, i, false);
}

public MultiLineLabel(String string) {


this(string, 0);
}

public MultiLineLabel() {
this("", 0);
}

3.35 Have Label with many lines


public void addNotify() {
super.addNotify();
calc();
}

public void setX(int i) { x = i; }


public void setY(int i) { y = i; }

public int getLeftRightMargin() {


return leftRightMargin;
}

public void setLeftRightMargin(int i) {


// make sense only if alignment is MultiLineLabel.LEFT!
if (i >= 0) leftRightMargin = i ;
}

public int getAlignment() {


return alignment;
}

public void setAlignment(int i) {


switch (alignment) {
case 0:
case 1:
case 2:
alignment = i;
break;
default:
throw new IllegalArgumentException();
}
repaint();
}

public int getTopBottomMargin() {


return topBottomMargin;
}

public void setTopBottomMargin(int i) {


if (i >= 0) topBottomMargin = i;
}

public void setFont(Font font) {


super.setFont(font);
calc();
repaint();
}

public Dimension getMinimumSize() {


Dimension d = new Dimension
(max_width + leftRightMargin * 2,
num_lines * line_height + topBottomMargin * 2);
if (d.width == 0) d.width = 10;
if (d.height == 0) d.height = 10;
return d;
}

public Dimension getPreferredSize() {


return getMinimumSize();
}

3.35 Have Label with many lines


public boolean getBorder() {
return border;
}

public void setBorder(boolean flag) {


border = flag;
}

public void setText(String s) {


// parse the string , "\n" is a the line separator
StringTokenizer st =
new StringTokenizer(s,"\n");
num_lines = st.countTokens();
lines = new String[num_lines];
line_widths = new int[num_lines];
for (int i = 0; i < num_lines; i++)
lines[i] = st.nextToken();
calc();
repaint();
text = new String(s);
}

public String getText() {


return text;
}

public Color getBorderColor() {


return borderColor;
}

public void setBorderColor(Color c) {


borderColor = c;
}

private void calc() {


// calc dimension and extract maximum width
Font f = getFont();
if (f != null) {
FontMetrics fm = getFontMetrics(f);
if (fm != null) {
line_height = fm.getHeight();
line_ascent = fm.getAscent();
max_width = 0;
for (int i = 0; i < num_lines; i++) {
line_widths[i] =
fm.stringWidth(lines[i]);
if (line_widths[i] > max_width)
max_width = line_widths[i];
}
}
}
}

public void update(Graphics g) {


super.paint(g);
Dimension d = getSize();
if ( (offGraphics == null) ||
(d.width != offDimension.width) ||
(d.height != offDimension.height)
) {
offDimension = d;
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();

3.35 Have Label with many lines


}
offGraphics.setColor(getBackground());
offGraphics.fillRect
(x, y, getSize().width − 1,
getSize().height − 1);
if (border) {
offGraphics.setColor(borderColor);
offGraphics.drawRect
(x, y, getSize().width − 1, getSize().height − 1);
}
int j = line_ascent +
(d.height − num_lines * line_height) / 2;
for (int k = 0; k < num_lines; ) {
int i;
switch (alignment) {
case 0:
i = 0;
break;
case 2:
i = d.width − line_widths[k];
break;
default:
i = (d.width − line_widths[k]) / 2;
break;
}
i += leftRightMargin;
offGraphics.setColor(getForeground());
offGraphics.drawString(lines[k], i + x, j + y);
k++;
j += line_height;
}
g.drawImage(offImage,0,0,this);
}

public void paint(Graphics g) {


update(g);
}

public static void main(String args[]){


Frame f = new Frame("Test MultiLineLabel");
f.setSize(200,200);
f.setLayout(new FlowLayout());
f.setVisible(true);

MultiLineLabel mll1 = new MultiLineLabel


("This a test!\nsecond line\nthird line",
MultiLineLabel.LEFT, true);
// mll1.setBorderColor(new Color(0).blue);
mll1.setLeftRightMargin(15);
mll1.setTopBottomMargin(15);
f.add(mll1);

Button b = new Button("Dummy");


f.add(b);

MultiLineLabel mll2 = new MultiLineLabel


("123\n4\n567", MultiLineLabel.RIGHT, false);
mll2.setForeground(new Color(0).yellow);
mll2.setBackground(new Color(0).black);
f.add(mll2);

f.validate();
}

3.35 Have Label with many lines


}

3.36 Have a Label with underlined text


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0272.html

[UnderlinedLabel.java]

import java.awt.*;

public class UnderlinedLabel extends Label {


public UnderlinedLabel(){
this("");
}

public UnderlinedLabel(String text){


super(text);
}

public void paint(Graphics g) {


Rectangle r;
super.paint(g);
r = g.getClipBounds();
g.drawLine
(0,
r.height − this.getFontMetrics(this.getFont()).getDescent(),
this.getFontMetrics(this.getFont()).stringWidth(this.getText()),
r.height − this.getFontMetrics(this.getFont()).getDescent());
}
}

[TestUnderlinedLabel.java]

import java.applet.*;
import java.awt.*;

public class TestUnderlinedLabel extends Applet {


public void init() {
UnderlinedLabel ul1 =
new UnderlinedLabel
("Java How−to");
add(ul1);
}
}

[testapplet.html]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="TestUnderlinedLabel.class"
NAME="myApplet"
HEIGHT=200 WIDTH=200>
/APPLET/BODY/HTML

Check this How−to for underlined text in Swing.

3.36 Have a Label with underlined text


3.37 Have a Label acting as HTML HREF (URLLabel)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0273.html

[URLLabel.java]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class URLLabel extends Label {


private java.applet.Applet applet;
private URL url;
private String target = "";
private Color unvisitedURL = Color.blue;
private Color visitedURL = Color.green;

public URLLabel(Applet applet , String url, String text){


this(applet, url, text, "_self");
}

public URLLabel
(Applet applet , String url, String text, String target){
super(text);
setForeground(unvisitedURL);
try {
this.applet = applet;
this.url = new URL(url);
this.target = target;
addMouseListener( new Clicked() );
}
catch (Exception e) {
e.printStackTrace();
}
}

public void paint(Graphics g) {


Rectangle r;
super.paint(g);
r = g.getClipBounds();
g.drawLine(0,
r.height − this.getFontMetrics(this.getFont()).getDescent(),
this.getFontMetrics(this.getFont()).stringWidth(this.getText()),
r.height − this.getFontMetrics(this.getFont()).getDescent());
}

public void setUnvisitedURLColor(Color c) {


unvisitedURL = c;
}

public void setVisitedURLColor(Color c) {


visitedURL = c;
}

class Clicked extends MouseAdapter{


public void mouseClicked(MouseEvent me){
setForeground(visitedURL);
applet.getAppletContext().showDocument(url, target);
}

3.37 Have a Label acting as HTML HREF (URLLabel)


}
}

[TestURLLabel.java]

import java.applet.*;
import java.awt.*;

public class TestURLLabel extends Applet {


public void init() {
URLLabel ull1 = new URLLabel(this,
"http://www.rgagnon.com/howto.html",
"Java How−to");
add(ull1);
URLLabel ull2 = new URLLabel(this,
"http://www.rgagnon.com/bigindex.html",
"Java How−to BigIndex");
add(ull2);
URLLabel ull3 = new URLLabel(this,
"http://www.rgagnon.com/javadetails/java−0001.html",
"Java How−to 0001");
add(ull3);
URLLabel ull4 = new URLLabel(this,
"http://www.rgagnon.com/javadetails/java−0002.html",
"Java How−to 0002");
add(ull4);
validate();
}
}

[testapplet.html]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="TestURLLabel.class"
NAME="myApplet"
HEIGHT=200 WIDTH=200>
</APPLET></BODY></HTML>

Try it here.

3.38 Display a GIF in a Canvas


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0229.html

import java.awt.*;
import java.awt.image.*;

public class ImageCanvas extends Canvas {


Image image;

public ImageCanvas(String name) {


MediaTracker media = new MediaTracker(this);
image = Toolkit.getDefaultToolkit().getImage(name);
media.addImage(image, 0);
try {
media.waitForID(0);
}

3.38 Display a GIF in a Canvas


catch (Exception e) {}
}

public ImageCanvas(ImageProducer imageProducer) {


image = createImage(imageProducer);
}

public void paint(Graphics g) {


g.drawImage(image, 0,0, this);
}

public static void main(String argv[]) {


if (argv.length <1) {
System.out.println
("usage: ImageCanvas.class [image file name]");
System.exit(0);
}
Frame frame = new Frame(argv[0]);
frame.setLayout(new BorderLayout());
frame.add("Center", new ImageCanvas(argv[0]));
frame.resize(400,400);
frame.show();
}
}

3.39 Embed an image into a Frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0302.html

A given image is tiled as the frame background.

The result is not too good with Label...

import java.awt.*;
import java.awt.event.*;

public class ImageFrame extends Frame {

private Image image;

ImageFrame() {
super("");
try {
MediaTracker mt = new MediaTracker (this);
// for Applet, change the method to retrieve the image
// and of course use your own image!
image = Toolkit.getDefaultToolkit().getImage("images/jht.gif");
mt.addImage(image, 0);
mt.waitForID(0);
}
catch (Exception e) {
e.printStackTrace();
}

setLayout(new FlowLayout());

add(new TextField(10));
add(new Button("hello"));

3.39 Embed an image into a Frame


add(new List(20));
add(new TextArea(20,20));
// Label may not look too good ...
add(new Label("Hello"));
setSize(500, 500);

addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// change this for an Applet
System.out.println("Bye.");
System.exit(0);
}
}
);
}

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


if(image != null) {
int x = 0, y = 0;
while(y < getSize().height) {
x = 0;
while(x< getSize().width) {
g.drawImage(image, x, y, this);
x= x + image.getWidth(null);
}
y = y + image.getHeight(null);
}
}
else {
g.clearRect(0, 0, getSize().width, getSize().height);
}
}

static public void main(String[] args) {


ImageFrame iframe = new ImageFrame();
iframe.setVisible(true);
}
}

The result :

3.39 Embed an image into a Frame


3.40 Load several images from a single GIF
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0239.html

It's a good idea to combine small GIFs into a single big one to speed up the loading process. In the
following snippet, I assume that all images are the same height and width. You may want to get this
GIF ( ) if you want to try the example on your workstation!

import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;

public class strip extends Applet{


int iconHeight = 16;
int iconWidth = 16;
int iconCount = 2;
Image icon[] = new Image[iconCount];
Image allIcons;

public void init(){


loadImages("item.gif");
}

public void paint(Graphics g) {


g.drawImage(allIcons, 0, 0, this);
g.drawImage(icon[0], 0, 20, this);
g.drawImage(icon[1], 0, 40, this);
}

public void loadImages(String s) {


MediaTracker t=new MediaTracker(this);

3.40 Load several images from a single GIF


allIcons=createImage(1,1);
try {
URL u=new URL(getCodeBase(), s);
allIcons=Toolkit.getDefaultToolkit().getImage(u);
t.addImage(allIcons,0);
}
catch (MalformedURLException me) {
System.out.println("MalformedURLException: " + me);
}
try {
t.waitForAll(15000);
}
catch (InterruptedException e) {
System.out.println("interrupted");
}
for (int i=0; i < iconCount; i++) {
Image z=createImage(iconWidth,iconHeight);
Graphics g=z.getGraphics();
g.clipRect(0,0,iconWidth,iconHeight);
g.drawImage(allIcons,−i*iconWidth,0,this);
icon[i]=z;
}
}
}

3.41 Load an Image from a JAR file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0240.html

[JDK1.1 application]

String imgName = "image.jpg";


URL imgURL = getClass().getResource(imgName);
Toolkit tk = Toolkit.getDefaultToolkit();
Image img = null;
try {
MediaTracker m = new MediaTracker(this);
img = tk.getImage(imgURL);
m.addImage(img, 0);
m.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}

[JDK 1.1 applet]


Because of some security reason, it's not possible with some browser (like Netscape) to use the
getResource() method from an Applet. Instead we must use the getResourceAsStream method.

Image img = null;

try {
MediaTracker m = new MediaTracker(this);
InputStream is = getClass().getResourceAsStream("image.gif");
//
// if your image is in a subdir in the jar then
// InputStream is = getClass().getResourceAsStream("img/image.gif");
// for example

3.41 Load an Image from a JAR file


//
BufferedInputStream bis = new BufferedInputStream(is);
// a buffer large enough for our image
//
// can be
// byte[] byBuf = = new byte[is.available()];
// is.read(byBuf); or something like that...
byte[] byBuf = = new byte[10000];

int byteRead = bis.read(byBuf,0,10000);


img = Toolkit.getDefaultToolkit().createImage(byBuf);
m.addImage(img, 0);
m.waitForAll();
}
}
catch(Exception e) {
e.printStackTrace();
}

[JDK 1.2 application]

URL url = this.getClass().getResource("myIcon.gif");


button.setIcon(new ImageIcon(url));

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

3.42 Load an Icon from a jar (again)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0436.html

public static ImageIcon getImageIcon(String name) {


return new ImageIcon(ClassLoader.getSystemResource(name));
}

ImageIcon img = getImageIcon("resources/images/icone.gif");

Remember that it is always possible to the Java built−in icons so that you don't have to include your
own standard icons.

public static Icon getIconForType(int iconType) {


switch (iconType) {
case 0:
return UIManager.getIcon("OptionPane.errorIcon");
case 1:
return UIManager.getIcon("OptionPane.informationIcon");
case 2:
return UIManager.getIcon("OptionPane.warningIcon");
case 3:
return UIManager.getIcon("OptionPane.questionIcon");
}
return null;
}

3.42 Load an Icon from a jar (again)


A list of what icons are available can be found here

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

3.43 Scale an Image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0243.html

import java.awt.image.*;
import java.awt.*;
import java.net.*;

public class app extends java.applet.Applet {


Image source;
Image resizedImage;

public void init() {


MediaTracker media = new MediaTracker(this);
// java how−to image for example, can be JPG
source = getImage(getDocumentBase(),"../images/jht.gif");
media.addImage(source,0);
try {
media.waitForID(0);
// scale down, half the original size
ImageFilter replicate =
new ReplicateScaleFilter
(source.getWidth(this)/2, source.getHeight(this)/2);
ImageProducer prod =
new FilteredImageSource(source.getSource(),replicate);
resizedImage = createImage(prod);
media.addImage(resizedImage,1);
media.waitForID(1);
}
catch(InterruptedException e) {}
}

public void paint(Graphics g) {


g.drawImage(source, 10,10,this);
g.drawImage(resizedImage,10, 80,this);
}
}

Try it here.

Modern JDK has now a complete library devoted to graphic manipulation.

The following exampe takes a JPG file as input , rescale it to the passed parameters and writes the
result in the specified output file.

import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

3.43 Scale an Image


public class ScaleJPG {
public static void scale(String src, int width, int height, String dest)
throws IOException {
BufferedImage bsrc = ImageIO.read(new File(src));
BufferedImage bdest =
new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bdest.createGraphics();
AffineTransform at =
AffineTransform.getScaleInstance((double)width/bsrc.getWidth(),
(double)height/bsrc.getHeight());
g.drawRenderedImage(bsrc,at);
ImageIO.write(bdest,"JPG",new File(dest));
}

public static void main(String[] args) {


if (args.length == 4) {
try {
ScaleJPG.scale
(args[0],Integer.parseInt(args[1]),
Integer.parseInt(args[2]), args[3]);
}
catch (Exception e) {
e.printStackTrace();
}
}
else {
System.out.println("\nUsage: java ScaleJPG src width height dest\n");
}
}
}

Example :

>java ScaleJPG javahowto.jpg 250 70 javahowto2.jpg

Input:

Ouput:

3.44 Fade an image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0249.html

This example display a GIF with a fade−in, fade−out effect.

import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;

3.44 Fade an image


public class FadeImage extends Applet {
Image img, faded;
int level, sign;
MediaTracker tracker;
AlphaFilter f;
FilteredImageSource fis;

public void init() {


level = 0;
sign = 15;
tracker = new MediaTracker(this);
try {
img = getImage(new URL(getDocumentBase(), "../images/gumby.gif"));
tracker.addImage(img,0);
tracker.waitForID(0);
}
catch (Exception e) {
e.printStackTrace();
}
f = new AlphaFilter();
f.setLevel(level);
fis = new FilteredImageSource(img.getSource(), f) ;

FadeThread ft = new FadeThread();


ft.delayedFading(this, 20);
ft.start();
}

public void paint(Graphics g) {


if (faded != null) {
g.drawImage(faded,0,0,this);
}
}

public void fadeIt() {


Graphics g = this.getGraphics();
level += sign;
if (level &lt; 0) {
level=0;
sign = sign * −1;
}
if (level &gt; 255) {
level=255;
sign = sign * −1;
try {
Thread.sleep(1000);
}
catch (Exception e) {}
}
f.setLevel(level);
if (faded != null) faded.flush();
faded = this.createImage(fis);
tracker.addImage(faded,0);
try {
tracker.waitForID(0);
}
catch (Exception ex) {
ex.printStackTrace();
}
repaint();
}

class FadeThread extends Thread {

3.44 Fade an image


FadeImage fadeApplet;
int delay;

public void delayedFading(FadeImage f, int delay) {


this.fadeApplet = f;
this.delay = delay;
}

public void run() {


while (true) {
try {
sleep(delay);
fadeApplet.fadeIt();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

class AlphaFilter extends RGBImageFilter {


private int level;

public AlphaFilter() {
canFilterIndexColorModel = true;
}

public void setLevel(int lev) {


level = lev;
}

public int filterRGB(int x, int y, int rgb) {


int a = level * 0x01000000;
return (rgb & 0x00ffffff) | a;
}
}
}

Try it here.

3.45 Rotate an image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0248.html

The following snippet rotates an image (90 degrees). The applet assumes the dimension 32x32 for
the image. You may want to grap this image for testing purpose.

import java.applet.Applet;
import java.net.*;

public class rotateGumby extends Applet {


Image img = null;
Image rot = null;

int buffer[] = new int[32 * 32];


int rotate[] = new int[32 * 32];

3.45 Rotate an image


public void init() {
try {
MediaTracker tracker = new MediaTracker (this);
img = getImage(new URL(getDocumentBase(), "gumby.gif"));
tracker.addImage (img, 0);
tracker.waitForAll();
PixelGrabber grabber =
new PixelGrabber(img, 0, 0, 32, 32, buffer, 0, 32);
try {
grabber.grabPixels();
}
catch(InterruptedException e) {
e.printStackTrace();
}
for(int y = 0; y < 32; y++) {
for(int x = 0; x < 32; x++) {
rotate[((32−x−1)*32)+y] = buffer[(y*32)+x];
}
}
rot = createImage(new MemoryImageSource(32, 32, rotate, 0, 32));
}
catch (Exception e) {
e.printStackTrace();
}
}

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


g.drawImage(img, 0, 0,this);
g.drawImage(rot,0, 40, this);
}
}

The next example will rotate a picture 5 degrees at a time. We are using the Java2D package (and
Swing).

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;

public class RotatePanel extends JPanel {


private Image image;
private double currentAngle;

public RotatePanel(Image image) {


this.image = image;
MediaTracker mt = new MediaTracker(this);
mt.addImage(image, 0);
try {
mt.waitForID(0);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void rotate() {

3.45 Rotate an image


//rotate 5 degrees at a time
currentAngle+=5.0;
if (currentAngle >= 360.0) {
currentAngle = 0;
}
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
AffineTransform origXform = g2d.getTransform();
AffineTransform newXform = (AffineTransform)(origXform.clone());
//center of rotation is center of the panel
int xRot = this.getWidth()/2;
int yRot = this.getHeight()/2;
newXform.rotate(Math.toRadians(currentAngle), xRot, yRot);
g2d.setTransform(newXform);
//draw image centered in panel
int x = (getWidth() − image.getWidth(this))/2;
int y = (getHeight() − image.getHeight(this))/2;
g2d.drawImage(image, x, y, this);
g2d.setTransform(origXform);
}

public Dimension getPreferredSize() {


return new Dimension (image.getWidth(this), image.getHeight(this));
}

public static void main(String[] args) {


JFrame f = new JFrame();
Container cp = f.getContentPane();
cp.setLayout(new BorderLayout());
Image testImage =
Toolkit.getDefaultToolkit().getImage("c:/temp/gumby.gif");
final RotatePanel rotatePanel = new RotatePanel(testImage);
JButton b = new JButton ("Rotate");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
rotatePanel.rotate();
}
});
cp.add(rotatePanel, BorderLayout.CENTER);
cp.add(b, BorderLayout.SOUTH);
f.pack();
f.setVisible(true);
}
}

3.46 Create a scrollable canvas


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0230.html

JDK1.1 using a ScrollPane

import java.applet.*;
import java.awt.*;

public class apptest extends Applet {

3.46 Create a scrollable canvas


Canvas c;
ScrollPane s;

public void init() {


setLayout(new BorderLayout());
s = new ScrollPane();
s.setSize(100,100);
add("Center", s);
c = new myCanvas();
c.setSize(500,300);
s.add(c);
}

class myCanvas extends Canvas {


Image buffImage;
Graphics offscreen;
boolean initDone = false;

myCanvas() { super(); }
public void paint(Graphics g) {
if (!initDone)
initpaint(g);
else
g.drawImage(buffImage, 0, 0, this);
}

public void update(Graphics g) {


g.drawImage(buffImage, 0, 0, this);
}

public void initpaint(Graphics g) {


try {
buffImage = this.createImage(500, 500);
offscreen = buffImage.getGraphics();
offscreen.setColor(Color.black);
offscreen.fillRect(0, 0, 500, 500);
offscreen.setColor(Color.white);
offscreen.setFont(new Font("Courier", Font.ITALIC, 42));
offscreen.drawString("Hello World!", 0, 50);
initDone = true;
g.drawImage(buffImage,0,0, this);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

JDK1.0.2 using a Canvas with Scrollbar

import java.applet.*;
import java.awt.*;

public class apptest extends Applet {


ScrollCanvas sc;
public void init() {
setLayout(new FlowLayout());
sc = new ScrollCanvas
(150,150, 300,200, Color.black,
Color.white);
add(sc);
}

3.46 Create a scrollable canvas


public boolean handleEvent(Event e) {
if (e.target instanceof Scrollbar) {
switch (e.id) {
case Event.SCROLL_ABSOLUTE:
case Event.SCROLL_PAGE_DOWN:
case Event.SCROLL_PAGE_UP:
case Event.SCROLL_LINE_UP:
case Event.SCROLL_LINE_DOWN:
sc.redraw();
return true;
}
}
return super.handleEvent(e);
}
}

class ScrollCanvas extends Panel {


int vw,vh;
int rw,rh;
Color b,f;
myCanvas c;
Scrollbar sv, sh;

// constructor
// visible h w
// real h w
// background foreground
ScrollCanvas
(int vw1, int vh1, int rw1, int rh1, Color b1, Color f1) {
super();
vw = vw1; vh = vh1;
rh = rh1; rw = rw1;
b = b1; f = f1;
int ScrollIncrement = 10;
setLayout(new BorderLayout());
c = new myCanvas(vw, vh, rw, rh, b ,f);
add("West", c);
sv = new Scrollbar
(Scrollbar.VERTICAL,0, ScrollIncrement, 0, rh);
add("East", sv);
sh = new Scrollbar
(Scrollbar.HORIZONTAL, 0, ScrollIncrement, 0, rw);
add("South", sh);
}

public void redraw() {


int y = sv.getValue();
int x = sh.getValue();
c.draw(x,y);
}

public Dimension minimumSize() {


return new Dimension(vw,vh);
}

public Dimension preferredSize() {


return new Dimension(vw,vh);
}
}

class myCanvas extends Canvas {


int vw, vh;

3.46 Create a scrollable canvas


int rw, rh;
Color b, f;
int x, y;
Image buffImage;
Graphics offscreen;
boolean initDone;

myCanvas
(int vw1, int vh1, int rw1, int rh1, Color b1, Color f1) {
super();
vw = vw1; vh = vh1;
rh = rh1; rw = rw1;
b = b1; f = f1;
initDone = false;
repaint();
}

public void paint(Graphics g) {


if (!initDone)
initpaint(g);
else
g.drawImage(buffImage, x, y, this);
}

public void update(Graphics g) {


g.drawImage(buffImage, x, y, this);
}

public void initpaint(Graphics g) {


try {
buffImage = this.createImage(rw, rh);
offscreen = buffImage.getGraphics();
offscreen.setColor(b);
offscreen.fillRect(0, 0, rw, rh);
offscreen.setColor(f);
offscreen.setFont(new Font("Courier", Font.ITALIC, 42));
offscreen.drawString("Hello World!", 0, 50);
initDone = true;
g.drawImage(buffImage,0,0, this);
}
catch (Exception e) {
System.out.println("oups...");
}
}

public void draw (int x1, int y1) {


x = −x1;
y = −y1;
update(getGraphics());
}

public Dimension minimumSize() {


return new Dimension(vw,vh);
}

public Dimension preferredSize() {


return new Dimension(vw,vh);
}
}

3.46 Create a scrollable canvas


3.47 Use an Image as the Applet background
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0233.html

import java.applet.Applet;
import java.net.*;

// TILE BACKGROUND
// in the HTML use :
// PARAM NAME="bgImage" VALUE="images/myImage.jpg"
// in the APPLET tag

public class Tile extends Applet {


Image bgImage = null;

public void init() {


try {
MediaTracker tracker = new MediaTracker (this);
bgImage = getImage
(new URL(getCodeBase(), getParameter("bgImage")));
tracker.addImage (bgImage, 0);
tracker.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}
setLayout(new FlowLayout());
add(new Button("Ok"));
add(new TextField(10));
}

public void update( Graphics g) {


paint(g);
}

public void paint(Graphics g) {


if(bgImage != null) {
int x = 0, y = 0;
while(y < size().height) {
x = 0;
while(x<size().width) {
g.drawImage(bgImage, x, y, this);
x=x+bgImage.getWidth(null);
}
y=y+bgImage.getHeight(null);
}
}
else {
g.clearRect(0, 0, size().width, size().height);
}
}
}

<HTML>
<TABLE><TR><TD>
<APPLET CODE=Tile.class WIDTH=150 HEIGHT=150>
<PARAM NAME="bgImage" VALUE="images/jht.gif">
</APPLET>
/HMTL

3.47 Use an Image as the Applet background


Try it here.

3.48 Have a simple Image browser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0277.html

[imagelist.txt]

jht.gif|JAVA How−to
jsht.gif|Javascript How−to
pht.gif|Powerbuilder How−to

[application version]

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class ImageBrowser {


public static void main(String s[]) {
AFrame f = new AFrame();
}
}

class AFrame extends Frame implements ActionListener {


List lbx;
MyCanvas can;
String url[] = new String[50];

public AFrame() {
setTitle("Image selection, double click to display");
setLayout(new GridLayout(1,2));
setSize(800,600);
lbx = new List();
can = new MyCanvas();
add(lbx); add(can);
initLbx();
// action on listbox double click
lbx.addActionListener(this);
// to close the Frame
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
setVisible(true);
}

public void actionPerformed (ActionEvent ae) {


String theUrl = url[lbx.getSelectedIndex()];
MediaTracker media = new MediaTracker(this);
Image image =
Toolkit.getDefaultToolkit().getImage(theUrl);
media.addImage(image, 0);
try {

3.48 Have a simple Image browser


media.waitForID(0);
can.setImage(image);
}
catch (Exception e) { e.printStacktrace();}
}

public void initLbx() {


int i = 0;
try {
String aLine = "";
BufferedReader in
= new BufferedReader(new FileReader("imagelist.txt"));
while(null != (aLine = in.readLine())) {
java.util.StringTokenizer st =
new java.util.StringTokenizer(aLine, "|");
url[i++] = st.nextToken();
// lbx.addItem(st.nextToken());
lbx.add(st.nextToken());
}
}
catch(Exception e) { e.printStackTrace();}
}
}

class MyCanvas extends Canvas {


private Image image;
public MyCanvas() {
super();
}

public void setImage(Image i) {


image = i;
repaint();
}

public void paint(Graphics g) {


if (image != null)
g.drawImage(image, 0,0, this);
}
}

NOTE : You can download this example here

[applet version]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class ImageBrowserApplet extends Applet {


public void init() {
APanel p = new APanel(this);
setLayout(new BorderLayout());
add(p, "Center");
}
}

class APanel extends Panel implements ActionListener {


private List lbx;
private MyCanvas can;

3.48 Have a simple Image browser


private Applet parent = null;
private String url[] = new String[50];

public APanel(Applet a) {
parent = a;
setLayout(new GridLayout(1,2));
lbx = new List();
can = new MyCanvas();
add(lbx); add(can);
initLbx();
// action on listbox double click
lbx.addActionListener(this);
setBackground(new Color(0).white);
}

public void actionPerformed (ActionEvent ae) {


try {
URL theUrl =
new URL(parent.getCodeBase(), url[lbx.getSelectedIndex()]);
MediaTracker media = new MediaTracker(this);
Image image =
Toolkit.getDefaultToolkit().getImage(theUrl);
media.addImage(image, 0);
media.waitForID(0);
can.setImage(image);
}
catch (Exception e) { e.printStackTrace();}
}

public void initLbx() {


int i = 0;
try {
String aLine = "";
URL source =
new URL(parent.getCodeBase(), "imagelist.txt");
BufferedReader in
= new BufferedReader
(new InputStreamReader(source.openStream()));;
while(null != (aLine = in.readLine())) {
java.util.StringTokenizer st =
new java.util.StringTokenizer(aLine, "|");
url[i++] = st.nextToken();
// lbx.addItem(st.nextToken());
lbx.add(st.nextToken());
}
}
catch(Exception e) { e.printStackTrace();}
}
}

class MyCanvas extends Canvas {


private Image image;
public MyCanvas() {
super();
}

public void setImage(Image i) {


image = i;
repaint();
}

public void paint(Graphics g) {


if (image != null)

3.48 Have a simple Image browser


g.drawImage(image, 0,0, this);
}
}

NOTE : You can try this example here

3.49 Simulate a "mouse over" event to toggle an image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0264.html

Use a special Canvas to preload 2 GIFs, and using a MouseListener simply toggle the image.

[JDK1.1]

import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class ToggleGifCanvas extends Canvas


implements MouseListener {
Image img1, img2;
int index = 0;
MediaTracker tracker;

public ToggleGifCanvas(URL n1, URL n2) {


tracker = new MediaTracker(this);
try {
img1 = Toolkit.getDefaultToolkit().getImage(n1);
img2 = Toolkit.getDefaultToolkit().getImage(n2);
tracker.addImage(img1,0);
tracker.addImage(img2,1);
tracker.waitForAll();
addMouseListener(this);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void paint(Graphics g) {


if (img1 != null) {
if (index == 0) {
g.drawImage(img1,0,0,this);
index++;
}
else {
g.drawImage(img2,0,0,this);
index−−;
}
}
}

public Dimension getPreferredSize (){


return new Dimension
(img1.getHeight(this), img2.getWidth(this));
}

public void mouseClicked(MouseEvent e) {}

3.49 Simulate a "mouse over" event to toggle an image


public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {
index = 1;
repaint();
}
public void mouseExited(MouseEvent e) {
index = 0;
repaint();
}
}

To use such Canvas, try something like this. This example needs our Gumby GIFs ( and

).

import java.applet.*;
import java.awt.*;
import java.net.*;

public class TestToogleGifCanvas extends Applet {


ToggleGifCanvas tgc;

public void init() {


try {
tgc = new ToggleGifCanvas
(new URL(getDocumentBase(),"images/gumby.gif"),
new URL(getDocumentBase(),"images/gumby2.gif"));
add(tgc);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Try it here.

3.50 Hide the mouse cursor


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0440.html

One way is to use a transparent GIF as the cursor or create one.

int[] pixels = new int[16 * 16];


Image image = Toolkit.getDefaultToolkit().createImage(
new MemoryImageSource(16, 16, pixels, 0, 16));
Cursor transparentCursor =
Toolkit.getDefaultToolkit().createCustomCursor
(image, new Point(0, 0), "invisibleCursor");

3.50 Hide the mouse cursor


3.51 Make a color transparent
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0265.html

Here we have an Image with a blue background like and we want to display it in an Applet with

a white background. All we have to do is to look for the blue color with the "Alpha bits" set to opaque
and make them transparent.

[Transparency.java]

import java.awt.*;
import java.awt.image.*;

public class Transparency {


public static Image makeColorTransparent
(Image im, final Color color) {
ImageFilter filter = new RGBImageFilter() {
// the color we are looking for... Alpha bits are set to opaque
public int markerRGB = color.getRGB() | 0xFF000000;

public final int filterRGB(int x, int y, int rgb) {


if ( ( rgb | 0xFF000000 ) == markerRGB ) {
// Mark the alpha bits as zero − transparent
return 0x00FFFFFF &rgb;
}
else {
// nothing to do
return rgb;
}
}
};

ImageProducer ip = new FilteredImageSource(im.getSource(), filter);


return Toolkit.getDefaultToolkit().createImage(ip);
}
}

[app.java]

import java.awt.image.*;
import java.awt.*;
import java.net.*;

public class app extends java.applet.Applet {


Image GifOriginalWithWithBlueBackground;
Image GifModifiedWithTransparentBackground;

public void init() {


setBackground(new Color(0).white);

MediaTracker media = new MediaTracker(this);


// image of our friend, Gumby with a blue background
GifOriginalWithWithBlueBackground =
getImage(getDocumentBase(),"gumbyblu.gif");
media.addImage(GifOriginalWithWithBlueBackground,0);
try {
media.waitForID(0);
GifModifiedWithTransparentBackground =

3.51 Make a color transparent


Transparency.makeColorTransparent
(GifOriginalWithWithBlueBackground, new Color(0).blue);
}
catch(InterruptedException e) {}
}

public void paint(Graphics g) {


g.drawImage(GifOriginalWithWithBlueBackground, 10,10,this);
g.drawImage(GifModifiedWithTransparentBackground,10, 80,this);
}
}

[x.html]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="app.class"
NAME="myApplet"
HEIGHT=200 WIDTH=200>
</APPLET>
</BODY></HTML>

3.52 Save an Image as a GIF or JPEG file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0266.html

Take a look at the following package :

http://www.obrador.com/essentialjpeg/jpeg.htm for JPEG


http://www.acme.com for GIF
http://rsb.info.nih.gov/ij/ can display BMP and save as GIF or TIFF

With JDK1.2, Sun introduces a new package called JIMI (available for download at their Web site.
With this package, it's easy to convert a Java Image to a JPEG image file.

double w = 200.0;
double h = 200.0;
BufferedImage image = new BufferedImage(
(int)w,(int)h,BufferedImage.TYPE_INT_RGB);

Graphics2D g = (Graphics2D)image.getGraphics();
g.drawLine(0,0,w,h);

try {
File f = new File("myimage.jpg");
JimiRasterImage jrf = Jimi.createRasterImage(image.getSource());
Jimi.putImage("image/jpeg",jrf,new FileOutputStream(f));
}
catch (JimiException je) {
je.printStackTrace();}

Another way is to use the undocumented com.sun.image.codec.jpeg package.

// [JDK1.2]
// img is a Java Image
//
BufferedImage bimg = null;

3.52 Save an Image as a GIF or JPEG file


int w = img.getWidth(null);
int h = img.getHeight(null);
int [] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(img,0,0,w,h,pixels,0,w);
try {
pg.grabPixels();
}
catch(InterruptedException ie) {
ie.printStackTrace();
}

bimg = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);


bimg.setRGB(0,0,w,h,pixels,0,w);

// Encode as a JPEG
FileOutputStream fos = new FileOutputStream("out.jpg");
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
jpeg.encode(bimg);
fos.close();

Since JDK1.4.2, javax.imageio.ImageIO lets you save and restore Images to disk in a platform
independent format. "png" and "jpeg" format are supported. With ImageIO, instead of Image you
use BufferedImage which is a subclass of Image.

import java.io.*;
import javax.imageio.*;
import java.awt.image.*;

public class FileOperations {

public static BufferedImage readImageFromFile(File file)


throws IOException
{
return ImageIO.read(file);
}

public static void writeImageToJPG


(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"jpg",file);
}
}

3.53 Use the same background color as the browser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0234.html

// in the HTML, use


// PARAM NAME="bgColor" VALUE="B8B5AE"
// (where VALUE is the same hexadecimal value
// as the HTML COLOR value)
// in the APPLET tag
// in the JAVA init method :
Color bgcolor = new Color(
Integer.valueOf(getParameter("BGCOLOR"), 16).intValue());
setBackground(bgcolor);

3.53 Use the same background color as the browser


3.54 Do simple animation using Images
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0262.html

By using a Thread, we switch between 2 GIFs ( and )

import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;

public class AnimationGifApplet extends Applet {


Image [] img;
int index = 0;
int maxImg;
MediaTracker tracker;

public void init() {


img = new Image[2]; // 2 images in animation
maxImg = img.length − 1;
tracker = new MediaTracker(this);
try {
// images loading
img[0] = getImage(new URL(getDocumentBase(), "images/gumby.gif"));
img[1] = getImage(new URL(getDocumentBase(), "images/gumby2.gif"));
tracker.addImage(img[0],0);
tracker.addImage(img[1],1);
tracker.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}

AnimationThread at = new AnimationThread();


at.delayedAnimation(this, 500);
at.start();
}

public void paint(Graphics g) {


if (img[0] != null) {
g.drawImage(img[index],0,0,this);
index = (index <maxImg) ? index + 1 : 0;
}
}

public void animate() {


repaint();
}

class AnimationThread extends Thread {


AnimationGifApplet animationApplet;
int delay;

public void delayedAnimation(AnimationGifApplet a, int delay) {


this.animationApplet = a;
this.delay = delay;
}

3.54 Do simple animation using Images


public void run() {
while (true) {
try {
sleep(delay);
animationApplet.animate();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

Try it here.

3.55 Do simple animation to show "work in progress"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0263.html

Like the previous How−to, using a Thread, we switch between 2 GIFs, for example ( and

).

Click the button to simulate some work, click again to terminate the "work in progress"

[JDK1.1]

import java.applet.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.net.*;

public class AnimationProgress extends Applet


implements ActionListener{
Image [] img;
int index = 0;
int maxImg;
boolean working = false;
Button b;
MediaTracker tracker;

public void init() {


setLayout(new FlowLayout(FlowLayout.LEFT));
add(b = new Button("Working"));
b.addActionListener(this);
img = new Image[2]; // 2 images in animation
maxImg = img.length − 1;
tracker = new MediaTracker(this);
try {
// images loading
img[0] = getImage(new URL(getDocumentBase(), "gumby.gif"));
img[1] = getImage(new URL(getDocumentBase(), "gumby2.gif"));
tracker.addImage(img[0],0);

3.55 Do simple animation to show "work in progress"


tracker.addImage(img[1],1);
tracker.waitForAll();
}
catch (Exception e) {
e.printStackTrace();
}

AnimationThread at = new AnimationThread();


at.delayedAnimation(this, 500);
at.start();
}

public void paint(Graphics g) {


if (img[0] != null) {
if (working) {
g.drawImage(img[index],68,0,this);
index = (index <maxImg) ? index + 1 : 0;
}
}
}

public void animate() {


repaint();
}

public void actionPerformed(ActionEvent ae) {


working = !working;
}

class AnimationThread extends Thread {


AnimationProgress animationApplet;
int delay;

public void delayedAnimation(AnimationProgress a, int delay) {


this.animationApplet = a;
this.delay = delay;
}

public void run() {


while (true) {
try {
sleep(delay);
animationApplet.animate();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

3.56 Get the color of a specific pixel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0257.html

We assume that we have an Image called picture

pixels = new int[width*height];

3.56 Get the color of a specific pixel


PixelGrabber pg =
new PixelGrabber(picture, 0, 0, width, height, pixels, 0, width);
try {
pg.grabPixels();
}
catch (InterruptedException e) { }

From here, individual pixel can be accessed via the pixels array.

int c = pixels[index]; // or pixels[x * width + y]


int red = (c &0x00ff0000) >> 16;
int green = (c &0x0000ff00) >> 8;
int blue = c &0x000000ff;
// and the Java Color is ...
Color c = new Color(red,green,blue);

Here another way to achieve this

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage

...

BufferedImage image = ImageIO.read(urlImage);


int c = image.getRGB(x,y);
int red = (c &0x00ff0000) >> 16;
int green = (c &0x0000ff00) >> 8;
int blue = c &0x000000ff;
// and the Java Color is ...
Color c = new Color(red,green,blue);

3.57 Do "rubber−band" drawing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0251.html

import java.applet.*;
import java.awt.*;
import java.util.Vector;

public class SimpleCAD extends Applet {


int w = 200;
int h = 200;
Vector lines = new Vector();
int np = 0;
int x1,y1;
int x2,y2;
int xl,yl;
Image offImg;
Graphics offGra;
Button btnClear, btnUndo;

public void init() {


setLayout(new FlowLayout());
btnClear = new Button("Clear");
btnUndo = new Button("Undo");
add(btnClear);
add(btnUndo);
setBackground(new Color(0).black);

3.57 Do "rubber−band" drawing


setForeground(new Color(0).white);
}

public void Dragupdate(Graphics g) {


/*
** rubber−band effect
*/
g.setXORMode(getBackground());
setForeground(new Color(0).blue);
if (xl != −1){
// erase the old line
g.drawLine(x1, y1, xl, yl);
if (x2 != −1) {
// draw the new one
g.drawLine(x1, y1, x2, y2);
}
}
}

public void update(Graphics g) {


// draw an offScreen drawing
Dimension dim = getSize();
if (offGra == null) {
offImg = createImage(dim.width, dim.height);
offGra = offImg.getGraphics();
}
offGra.setColor(new Color(0).black);
offGra.fillRect(0,0,dim.width, dim.height);
offGra.setColor(new Color(0).white);
offGra.setPaintMode();
for (int i=0; i < np; i++) {
Rectangle p = (Rectangle)lines.elementAt(i);
if (p.width != −1) {
offGra.drawLine(p.x, p.y, p.width, p.height);
}
}
// put the OffScreen image OnScreen
g.drawImage(offImg,0,0,null);
}

public boolean handleEvent(Event e) {


switch (e.id) {
case Event.MOUSE_DOWN:
// new starting point
x1 = e.x;
y1 = e.y;
// begin an new drawing process
x2 = −1;
return true;
case Event.MOUSE_UP:
// end a drawing process
lines.addElement(new Rectangle(x1, y1, e.x, e.y));
np++;
x2 = xl = −1;
repaint();
return true;
case Event.MOUSE_DRAG:
// xl yl line to be erased
xl = x2;
yl = y2;
// x2 y2 last current point
x2 = e.x;
y2 = e.y;

3.57 Do "rubber−band" drawing


Dragupdate(getGraphics());
return true;
}
return super.handleEvent(e);
}

public boolean action(Event e, Object o) {


if (e.target == btnClear) resetDrawing();
if (e.target == btnUndo) undo();
return true;
}

public void undo() {


if (np>0) {
lines.removeElementAt(np−1);
np−−;
repaint();
}
}

public void resetDrawing() {


lines.removeAllElements();
np=0;
repaint();
}
}

3.58 Convert RGB value to Hexadecimal (to be used in HTML for


example)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0255.html

import java.awt.*;
public class Color2Hex {
public static void main( String[] args ) {
if (args.length != 3) {
System.out.println("Color2Hex r g b");
}
else {
int i = Integer.parseInt(args[0]);
int j = Integer.parseInt(args[1]);
int k = Integer.parseInt(args[2]);

Color c = new Color(i,j,k);


System.out.println
( "hex: " + Integer.toHexString( c.getRGB() &0x00ffffff ) );
}
}
}

3.59 Draw a line or set a pixel in my own image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0250.html

3.58 Convert RGB value to Hexadecimal (to be used in HTML for example)
import java.awt.image.*;
import java.awt.*;
import java.applet.*;

public class CreateAnImage extends Applet {


Image myImage;

public void init() {


int x = 100;
int y = 100;
myImage = createImage(x,y);
Graphics g = myImage.getGraphics();
g.drawLine(0,0,x,y);
g.drawLine(x,0,0,y);
for(int i=0; i <x; i+=2){
setPixel(myImage, 50, i, new Color(0).blue);
setPixel(myImage, i, 50, new Color(0).green);
}
}

public void paint(Graphics g) {


g.drawImage(myImage,0,0,this);
}

public void setPixel


(Image image, int x, int y, Color color ) {
Graphics g = image.getGraphics( );
g.setColor( color );
g.fillRect( x, y, 1, 1 );
g.dispose( );
}
}

3.60 Draw a dashed line


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0224.html

public void drawDashedLine(Graphics g,int x1,int y1,int x2,int y2,


double dashlength, double spacelength) {
if((x1==x2){
g.drawLine(x1,y1,x2,y2);
return;
}
double linelength=Math.sqrt((x2−x1)*(x2−x1)+(y2−y1)*(y2−y1));
double yincrement=(y2−y1)/(linelength/(dashlength+spacelength));
double xincdashspace=(x2−x1)/(linelength/(dashlength+spacelength));
double yincdashspace=(y2−y1)/(linelength/(dashlength+spacelength));
double xincdash=(x2−x1)/(linelength/(dashlength));
double yincdash=(y2−y1)/(linelength/(dashlength));
int counter=0;
for (double i=0;i<linelength−dashlength;i+=dashlength+spacelength){
g.drawLine((int) (x1+xincdashspace*counter),
(int) (y1+yincdashspace*counter),
(int) (x1+xincdashspace*counter+xincdash),
(int) (y1+yincdashspace*counter+yincdash));
counter++;
}
if ((dashlength+spacelength)*counter<=linelength)
g.drawLine((int) (x1+xincdashspace*counter),

3.60 Draw a dashed line


(int) (y1+yincdashspace*counter),
x2,y2);
}

3.61 Draw a line with a thickness


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0260.html

import java.awt.*;
import java.applet.*;

public class thickLine extends Applet {

public void init( ) { }

public void paint( Graphics g ) {


drawThickLine
(g, 0, 0, getSize().width, getSize().height, 5, new Color(0).black);
drawThickLine
(g, 0, getSize().height, getSize().width, 0, 5, new Color(0).red);

drawThickLine
(g, getSize().width/2, 0, getSize().width/2, getSize().height, 8,
new Color(0).green);
drawThickLine
(g, 0, getSize().height/2, getSize().width, getSize().height/2, 12,
new Color(0).blue);
}

public void drawThickLine(


Graphics g, int x1, int y1, int x2, int y2, int thickness, Color c) {
// The thick line is in fact a filled polygon
g.setColor(c);
int dX = x2 − x1;
int dY = y2 − y1;
// line length
double lineLength = Math.sqrt(dX * dX + dY * dY);

double scale = (double)(thickness) / (2 * lineLength);

// The x,y increments from an endpoint needed to create a rectangle...


double ddx = −scale * (double)dY;
double ddy = scale * (double)dX;
ddx += (ddx > 0) ? 0.5 : −0.5;
ddy += (ddy > 0) ? 0.5 : −0.5;
int dx = (int)ddx;
int dy = (int)ddy;

// Now we can compute the corner points...


int xPoints[] = new int[4];
int yPoints[] = new int[4];

xPoints[0] = x1 + dx; yPoints[0] = y1 + dy;


xPoints[1] = x1 − dx; yPoints[1] = y1 − dy;
xPoints[2] = x2 − dx; yPoints[2] = y2 − dy;
xPoints[3] = x2 + dx; yPoints[3] = y2 + dy;

g.fillPolygon(xPoints, yPoints, 4);


}

3.61 Draw a line with a thickness


}

Using JDK1.2

public void paint(Graphics g){


Graphics2D g2d = (Graphics2D)g;
int width = 10;
g2d.setStroke(new BasicStroke(width));
g2d.drawLine(x1, y1, x2, y2);
}

On a Component

int width = 10;


BasicStroke bs = new BasicStroke(width);
JLabel l = new JLabel();
l.getGraphics().setStroke(bs);
l.drawLine(0,0,100,100);

Using JDK1.3

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;

public class TestLine extends JFrame{


private MyPanel panel;
public TestLine() {
setSize(200, 200);
panel = new MyPanel();
getContentPane().add( panel, "Center" );
}

public static void main( String [] args ){


TestLine tl = new TestLine();
tl.setVisible( true );
}
}

class MyPanel extends JPanel {


final static BasicStroke stroke = new BasicStroke(2.0f);
final static BasicStroke wideStroke = new BasicStroke(8.0f);

public MyPanel(){}

public void paintComponent( Graphics g ){


Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint
(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke( stroke );
g2.draw(new Line2D.Double(10.0, 10.0, 100.0, 10.0));
g2.setStroke( wideStroke );
g2.draw(new Line2D.Double(10.0, 50.0, 100.0, 50.0));
}
}

3.61 Draw a line with a thickness


3.62 Draw a pie chart
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0261.html

import java.util.*;
import java.awt.*;
import java.applet.Applet;

public class Graph extends Applet {


int depth, radius;

public void init() {


float value;
String at = getParameter("width");
radius = (at != null) ? Integer.valueOf(at).intValue() : 100;
at = getParameter("depth");
depth = (at != null) ? Integer.valueOf(at).intValue() : 20;
at = getParameter("values");
PieChartCanvas c = new PieChartCanvas(radius, depth);
setLayout(new BorderLayout());

// Create Hashtable to map color name (String) to Color type


Hashtable colors = new Hashtable();
colors.put("green", Color.green);
colors.put("red", Color.red);
colors.put("blue", Color.blue);
colors.put("yellow", Color.yellow);
colors.put("magenta", Color.magenta);
colors.put("cyan", Color.cyan);
colors.put("orange", Color.orange);
colors.put("pink", Color.pink);
colors.put("white", Color.white);
colors.put("black", Color.black);

// "value−color,value−color,..."
StringTokenizer t = new StringTokenizer(at, ",");
String s;
int i;
while (t.hasMoreTokens()) {
s = t.nextToken();
i = s.indexOf('−');
value = Float.valueOf(s.substring(0, i)).floatValue();
c.addSlice(value, (Color)colors.get(s.substring(i + 1)));
}

resize(c.getMinimumSize().width, c.getMinimumSize().height);
add("Center", c);
}
}

class PieChartCanvas extends Canvas {


/*
** author Ciaran Treanor ciaran@broadcom.ie
*/
final double aspectFudge = 2.5;
int radius, depth, called = 1, numSlices = 0;
float total = 0, value[] = new float[10];
Color color[] = new Color[10];
Graphics offGraphics;
Image gfxBuff;

3.62 Draw a pie chart


public PieChartCanvas(int radius, int depth) {
this.value = value;
this.color = color;
this.radius = radius;
this.depth = depth;
}

public void paint(Graphics g) {


int startAngle;
float angle;
Dimension d = getSize();

if(gfxBuff == null) {
gfxBuff = createImage(d.width, d.height);
offGraphics = gfxBuff.getGraphics();
offGraphics.setColor(getBackground());
offGraphics.fillRect(0, 0, d.width, d.height);
}

// do the 3d effect
for(int x = depth; x >= 1; x−−) {
startAngle = −45;
for(int i = 0; i < numSlices; i++) {
offGraphics.setColor(color[i].darker());
angle = Math.round(360 * (value[i] / total));
offGraphics.fillArc(0, x, radius, (int)(radius / aspectFudge),
startAngle, (int)angle);
startAngle += angle;
}
}

// draw the pie slice


startAngle = −45;
for(int i = 0; i < numSlices; i++) {
offGraphics.setColor(color[i]);
angle = Math.round(360 * (value[i] / total));
offGraphics.fillArc(0, 0, radius, (int)(radius / aspectFudge),
startAngle, (int)angle);
startAngle += angle;
}
g.drawImage(gfxBuff, 0, 0, null);
}

public void addSlice(float value, Color color) {


this.value[numSlices] = value;
this.color[numSlices++] = color;
total += value;
}

public Dimension getPreferredSize() {


return getMinimumSize();
}

public Dimension getMinimumSize() {


return new Dimension(radius, (int)((radius / aspectFudge) + depth));
}
}

[JavaPie.hmtl]

<HTML>
<TABLE><TR><TD>
<APPLET CODE=Graph.class WIDTH=150 HEIGHT=150>

3.62 Draw a pie chart


<PARAM NAME="depth" VALUE="30">
<PARAM NAME="width" VALUE="120">
<PARAM NAME="values" VALUE="1−red,5−green,7−blue">
</APPLET>
<TD>
<TABLE>
<TR><TD>item 1<TD BGCOLOR="#FF0000">
<TR><TD>item 2<TD BGCOLOR="#008000">
<TR><TD>item 3<TD BGCOLOR="#0000FF">
</TABLE>
</TABLE>
</HMTL>

Try it here

3.63 Draw faster rectangles


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0364.html

Thanks to Chikirev Sergey

It seems that drawRoundRect(….) 1,5 faster then drawRect(…..) , because one of them is
completely native.

import java.awt.*;
import java.awt.event.*;

public class Class1 extends Frame implements ActionListener{


public void paint(Graphics g){
super.paint(g);
long t=System.currentTimeMillis();
for(int i=0;i<10000;i++){
g.drawRect(10,70,100,50);
}
t=System.currentTimeMillis()−t;
g.drawString(String.valueOf(t),10,70);
t=System.currentTimeMillis();
for(int i=0;i<10000;i++){
g.drawRoundRect(10,130,100,50,0,0);
}
t=System.currentTimeMillis()−t;
g.drawString(String.valueOf(t),10,130);
}

public void actionPerformed(ActionEvent p1){


repaint(0,10,200,300);
}

public static void main (String[] args){


Class1 c=new Class1();
c.setSize(300,300);
c.setLayout(new BorderLayout());
Button b=new Button("Refresh");
c.add(BorderLayout.SOUTH , b);
b.addActionListener(c);
c.show();
}
}

3.63 Draw faster rectangles


3.64 Get a screen capture and save it as a JPEG
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0489.html

The screen capture is done with java.awt.Robot.

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;

class ScreenCapture {
public static void main(String args[]) throws
AWTException, IOException {
// capture the whole screen
BufferedImage screencapture = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );

// Save as JPEG
File file = new File("screencapture.jpg");
ImageIO.write(screencapture, "jpg", file);

// Save as PNG
// File file = new File("screencapture.png");
// ImageIO.write(screencapture, "png", file);
}
}

To capture a specific area

BufferedImage screencapture = new Robot().createScreenCapture(


new Rectangle( 15, 15, 150, 150));

To capture a specific visual object

BufferedImage image = new Robot().createScreenCapture(


new Rectangle( myframe.getX(), myframe.getY(),
myframe.getWidth(), myframe.getHeight() ) );

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

3.65 Display a TIF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0605.html

3.64 Get a screen capture and save it as a JPEG


The regular JDK can only deal with JPG, GIF, BMP or PNG file with the package ImageIO, see this
HowTo.

To deal with TIF file, you must use the JAI (Java Advanced Imaging) package.

This example will display a given TIF file. It will also display other types (JPG,...) by detecting the
type.

import javax.media.jai.PlanarImage;
import com.sun.media.jai.codec.ByteArraySeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.SeekableStream;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.awt.Image;
import java.awt.image.RenderedImage;

import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.ImageIcon;

public class ImageViewer {

static Image load(byte[] data) throws Exception{


Image image = null;
SeekableStream stream = new ByteArraySeekableStream(data);
String[] names = ImageCodec.getDecoderNames(stream);
ImageDecoder dec =
ImageCodec.createImageDecoder(names[0], stream, null);
RenderedImage im = dec.decodeAsRenderedImage();
image = PlanarImage.wrapRenderedImage(im).getAsBufferedImage();
return image;
}

public static void main(String[] args) throws Exception{


String path;
if (args.length==0) {
path = JOptionPane.showInputDialog(null, "Image Path",
"c:/applications/sidebar.tif");
}
else {
path = args[0];
}
FileInputStream in = new FileInputStream(path);
FileChannel channel = in.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int)channel.size());
channel.read(buffer);
Image image = load(buffer.array());
// make sure that the image is not too big
// scale with a width of 500
Image imageScaled =
image.getScaledInstance(500, −1, Image.SCALE_SMOOTH);
//
System.out.println("image: " + path + "\n" + image);
//
JOptionPane.showMessageDialog(null, new JLabel(
new ImageIcon( imageScaled )) );
}
}

3.64 Get a screen capture and save it as a JPEG


The JAI package is composed of 2 jars : jai_core.jar and jai_codec.jar

http://java.sun.com/javase/technologies/desktop/media/jai/
https://jai.dev.java.net/#Downloads

To write a TIF file, see this HowTo

3.66 Convert a multi−page TIF into single−page TIF


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0535.html

Tagged Image File Format (abbreviated TIFF) is a file format for mainly storing images, including
photographs and line art. TIFF was originally created as an attempt to get desktop scanner vendors
of the mid−1980's to agree on a common scanned image file format, rather than have each
company promulgate its own proprietary format.

This HowTo takes a multi−page TIF (from a FAX) and convert it into many single−pages TIF.

This is done with the JAI (Java Advance Image) package.

http://java.sun.com/products/java−media/jai/index.jsp

>
import java.io.*;

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.TIFFEncodeParam;

import java.awt.image.RenderedImage;
import javax.media.jai.RenderedOp;
import javax.media.jai.JAI;
import java.awt.image.renderable.ParameterBlock;

public class TestTiff {

public static void main(String[] args) throws IOException {


new TestTiff().doitJAI();
}

public void doitJAI() throws IOException {


FileSeekableStream ss = new FileSeekableStream("d:/multi.tif");
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", ss, null);
int count = dec.getNumPages();
TIFFEncodeParam param = new TIFFEncodeParam();
param.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);
param.setLittleEndian(false); // Intel
System.out.println("This TIF has " + count + " image(s)");
for (int i = 0; i < count; i++) {
RenderedImage page = dec.decodeAsRenderedImage(i);
File f = new File("d:/single_" + i + ".tif");
System.out.println("Saving " + f.getCanonicalPath());

3.66 Convert a multi−page TIF into single−page TIF


ParameterBlock pb = new ParameterBlock();
pb.addSource(page);
pb.add(f.toString());
pb.add("tiff");
pb.add(param);
RenderedOp r = JAI.create("filestore",pb);
r.dispose();
}
}
}

This solution is working but JAI is a slow performer.

You may want to consider to use an external utility to do this kind on conversion. A nice one is
irfanview (win), a (free) multi−purpose graphic utility.

http://www.irfanview.com/

To do a TIF conversion, use this command line :

C:\IrfanView\i_view32" d:\multi.tif /extract=(d:\,tif) /killmesoftly

irfanview is an amazing software when it comes to transform a graphic format to another one. You
can use it from a command line or from a GUI.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

3.67 Convert an Image to a BufferedImage


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0601.html

import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;

public class ImageUtils {

public static BufferedImage imageToBufferedImage(Image im) {


BufferedImage bi = new BufferedImage
(im.getWidth(null),im.getHeight(null),BufferedImage.TYPE_INT_RGB);
Graphics bg = bi.getGraphics();
bg.drawImage(im, 0, 0, null);
bg.dispose();
return bi;
}

public static BufferedImage readImageFromFile(File file)


throws IOException
{
return ImageIO.read(file);
}

3.67 Convert an Image to a BufferedImage


public static void writeImageToPNG
(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"png",file);
}

public static void writeImageToJPG


(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"jpg",file);
}
}

You need to do something to transform an Image to BufferedImage. But since BufferedImage


extends Image, so there isn't a back−conversion, it's not needed.

3.68 Detect a double click vs simple click


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0235.html

[JDK1.02]

import java.applet.*;
import java.awt.*;

public class d extends Applet {

int dClkRes = 300; // double−click speed in ms


long timeMouseDown=0; // last mouse down time
int lastX=0,lastY=0; // last x and y

public boolean mouseDown(Event event, int x, int y){


/*
** check for double click
*/
long currentTime = event.when;
if ((lastX==x) &(lastY==y) &
((event.when−timeMouseDown) < dClkRes)) {
System.out.println("double click " + currentTime);
return false;
}
else {
//single click action could be added here
System.out.println("simple click " + currentTime);
timeMouseDown = event.when;
lastX=x;
lastY=y;
}
return true;
}
}

[JDK11]

3.68 Detect a double click vs simple click


import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class d extends Applet


implements MouseListener {

public void init() {


this.addMouseListener(this);
}

public void paint(Graphics g) {


g.drawString("Click here", 10,10);
}

public void mousePressed(MouseEvent e) {}


public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {
System.out.println
( "Click at (" + e.getX() + ":" + e.getY() + ")" );
if (e.getClickCount() == 2)
System.out.println( " and it's a double click!");
else
System.out.println( " and it's a simple click!");
}
}

3.69 Detect the mouse button used when clicking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0236.html

[JDK11]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class d extends Applet


implements MouseListener {

public void init() {


this.addMouseListener(this);
}

public void paint(Graphics g) {


g.drawString("Click here", 10,10);
}

public void mousePressed(MouseEvent e) {}


public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {
switch(e.getModifiers()) {
case InputEvent.BUTTON1_MASK: {
System.out.println("That's the LEFT button");
break;

3.69 Detect the mouse button used when clicking


}
case InputEvent.BUTTON2_MASK: {
System.out.println("That's the MIDDLE button");
break;
}
case InputEvent.BUTTON3_MASK: {
System.out.println("That's the RIGHT button");
break;
}
}
}
}

3.70 Exit an application from a menu


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0276.html

import java.awt.*;
import java.awt.event.*;

public class ExitFromMenu extends Frame implements ActionListener {


Menu m = new Menu("Exit From Here");

ExitFromMenu() {
super("");
MenuBar mb = new MenuBar();

mb.add(m);
MenuItem m1 = m.add(new MenuItem("Exit",
new MenuShortcut(KeyEvent.VK_X)));
m1.setActionCommand("Exit");
m.addActionListener(this);

setMenuBar(mb);

addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// unique exit point
System.out.println("Bye.");
System.exit(0);
}
}
);
add(new Label
("You can quit by clicking on the 'X'"),"South");
add(new Label
("You can quit by clicking on the menu item 'Exit'"),"Center");
add(new Label
("You can quit with the MenuShortcut 'ctrl−x'"),"North");
setSize(300, 300);
show();
}

public void actionPerformed(ActionEvent evt) {


String what = evt.getActionCommand();

if (what.equals("Exit"))
processEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));

3.70 Exit an application from a menu


}

static public void main(String[] args) {


new ExitFromMenu();
}
}

3.71 Trigger a click on a Button


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0468.html

Regular AWT

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class TestEvent extends Applet implements ActionListener {


Button b2, b1;
TextField t1;

public void init() {


setLayout(new FlowLayout());
t1 = new TextField(30);
b1 = new Button("Output");
add(b1); add(t1);
b2 = new Button("Fire event 1st button");
add(b2);

b1.addActionListener(this);
b2.addActionListener(this);

public void actionPerformed(ActionEvent e) {


if (e.getSource() == b1) {
t1.setText("1st button clicked");
}
if (e.getSource() == b2) {
// from the b2 button, we creating an event to trigger a click
// on the b1 button
ActionEvent ae =
new ActionEvent((Object)b1, ActionEvent.ACTION_PERFORMED, "");
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
// b1.dispatchEvent(ae); can be used too.
}
}
}

With Swing

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestEventSwing extends JApplet implements ActionListener {


JButton b1, b2;
JTextField t1;

3.71 Trigger a click on a Button


public void init() {
setLayout(new FlowLayout());
t1 = new JTextField(30);
b1 = new JButton("Output");
add(b1); add(t1);
b2 = new JButton("Fire event 1st button");
add(b2);

b1.addActionListener(this);
b2.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == b1) {
t1.setText("first button clicked");
}
if (e.getSource() == b2) {
// from the b2 button, we trigger a click on the b1 button.
// As an added bonus, a visual effect on b1 is visible!
b1.doClick();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

3.71 Trigger a click on a Button


4 Environment
4.1 java−env

4.2 Read environment variables from an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0150.html

NOTE: JDK1.5 or better provides a simpler way to achieve this, see this HowTo.

JDK up to 1.4
Start the JVM with the "−D" switch to pass properties to the application and read them with the
System.getProperty() method.

SET myvar=Hello world


SET myothervar=nothing
java −Dmyvar="%myvar%" −Dmyothervar="%myothervar%" myClass

then in myClass

String myvar = System.getProperty("myvar");


String myothervar = System.getProperty("myothervar");

If you don't know in advance, the name of the variable to be passed to the JVM, then there is no
100% Java way to retrieve them.

One approach (not the easiest one), is to use a JNI call to fetch the variables, see this HowTo.

A more low−tech way, is to launch the appropriate call to the operating system and capture the
output. The following snippet puts all environment variables in a Properties class and display the
value the TEMP variable.
import java.io.*;
import java.util.*;

public class ReadEnv {


public static Properties getEnvVars() throws Throwable {
Process p = null;
Properties envVars = new Properties();
Runtime r = Runtime.getRuntime();
String OS = System.getProperty("os.name").toLowerCase();
// System.out.println(OS);
if (OS.indexOf("windows 9") > −1) {
p = r.exec( "command.com /c set" );
}
else if ( (OS.indexOf("nt") > −1)
|| (OS.indexOf("windows 2000") > −1 )
|| (OS.indexOf("windows xp") > −1) ) {
// thanks to JuanFran for the xp fix!
p = r.exec( "cmd.exe /c set" );
}
else {

4 Environment
// our last hope, we assume Unix (thanks to H. Ware for the fix)
p = r.exec( "env" );
}
BufferedReader br = new BufferedReader
( new InputStreamReader( p.getInputStream() ) );
String line;
while( (line = br.readLine()) != null ) {
int idx = line.indexOf( '=' );
String key = line.substring( 0, idx );
String value = line.substring( idx+1 );
envVars.setProperty( key, value );
// System.out.println( key + " = " + value );
}
return envVars;
}

public static void main(String args[]) {


try {
Properties p = ReadEnv.getEnvVars();
System.out.println("the current value of TEMP is : " +
p.getProperty("TEMP"));
}
catch (Throwable e) {
e.printStackTrace();
}
}
}

thanks to w.rijnders for the w2k fix.

An update from Van Ly :

I found that, on Windows 2003 server, the property value for "os.name" is actually "windows 2003."
So either that has to be added to the bunch of tests or just relax the comparison strings a bit:

else if ( (OS.indexOf("nt") > −1)


|| (OS.indexOf("windows 2000") > −1 )
|| (OS.indexOf("windows 2003") > −1 ) // ok
// but specific to 2003
|| (OS.indexOf("windows xp") > −1) ) {

else if ( (OS.indexOf("nt") > −1)


|| (OS.indexOf("windows 20") > −1 ) // better,
// since no other OS would
// return "windows"
|| (OS.indexOf("windows xp") > −1) ) {

I started with "windows 200" but thought "what the hell" and made it "windows 20" to lengthen its
longivity. You could push it further and use "windows 2," I suppose. The only thing to watch out for
is to not overlap with "windows 9."

On Windows, pre−JDK 1.2 JVM has trouble reading the Output stream directly from the SET
command, it never returns. Here 2 ways to bypass this behaviour.

First, instead of calling directly the SET command, we use a BAT file, after the SET command we
print a known string. Then, in Java, when we read this known string, we exit from loop.

4 Environment
[env.bat]
@set
@echo **end

[java]
...
if (OS.indexOf("windows") > −1) {
p = r.exec( "env.bat" );
}
...

while( (line = br.readLine()) != null ) {


if (line.indexOf("**end")>−1) break;
int idx = line.indexOf( '=' );
String key = line.substring( 0, idx );
String value = line.substring( idx+1 );
hash.put( key, value );
System.out.println( key + " = " + value );
}

The other solution is to send the result of the SET command to file and then read the file from Java.

...
if (OS.indexOf("windows 9") > −1) {
p = r.exec( "command.com /c set > envvar.txt" );
}
else if ( (OS.indexOf("nt") > −1)
|| (OS.indexOf("windows 2000") > −1
|| (OS.indexOf("windows xp") > −1) ) {
// thanks to JuanFran for the xp fix!
p = r.exec( "cmd.exe /c set > envvar.txt" );
}
...

// then read back the file


Properties p = new Properties();
p.load(new FileInputStream("envvar.txt"));

Thanks to JP Daviau

// UNIX
public Properties getEnvironment() throws java.io.IOException {
Properties env = new Properties();
env.load(Runtime.getRuntime().exec("env").getInputStream());
return env;
}

Properties env = getEnvironment();


String myEnvVar = env.get("MYENV_VAR");

To read only one variable :


// NT version , adaptation for other OS is left as an exercise...
Process p = Runtime.getRuntime().exec("cmd.exe /c echo %MYVAR%");
BufferedReader br = new BufferedReader
( new InputStreamReader( p.getInputStream() ) );
String myvar = br.readLine();
System.out.println(myvar);

Java's System properties contains some useful informations about the environment, for example,
the TEMP and PATH environment variables (on Windows).
public class ShowSome {

4 Environment
public static void main(String args[]){
System.out.println("TEMP : "
+ System.getProperty("java.io.tmpdir"));
System.out.println("PATH : "
+ System.getProperty("java.library.path"));
System.out.println("CLASSPATH : "
+ System.getProperty("java.class.path"));
System.out.println("SYSTEM DIR : " +
System.getProperty("user.home")); // ex. c:\windows on Win9x
System.out.println("CURRENT DIR: "
+ System.getProperty("user.dir"));
}
}

Here some tips from H. Ware about the PATH on different OS.

PATH is not quite the same as library path. In unixes, they are completely different−−−the libraries
typically have their own directories.

System.out.println("the current value of PATH is: {" +


p.getProperty("PATH")+"}");

System.out.println("LIBPATH: {" +
System.getProperty("java.library.path")+"}");

gives

the current value of PATH is:


{/home/hware/bin:/usr/local/bin:/usr/xpg4/bin:/opt/SUNWspro/bin:
/usr/ucb:/bin:/usr/bin:/home/hware/linux−bin:/usr/openwin/bin/:
/usr/local/games:/usr/ccs/lib/:/usr/new:/usr/sbin/:/sbin/:
/usr/openwin/lib:/usr/X11/bin:/usr/bin/X11/:/usr/local/bin/X11:
/usr/bin/pbmplus:/usr/etc/:/usr/dt/bin/:/usr/lib:
/usr/lib/nis:/usr/share/bin:/usr/share/bin/X11:
/home/hware/work/cdk/main/cdk/../bin:.}
LIBPATH:
{/usr/lib/j2re1.3/lib/i386:/usr/lib/j2re1.3/lib/i386/native_threads:
/usr/lib/j2re1.3/lib/i386/client:/usr/lib/j2sdk1.3/lib/i386:/usr/lib:/lib}

on my linux workstation. (java added all those except /lib and /usr/lib). But these two lines aren't the
same on window either:

This system is windows nt

the current value of PATH is:


{d:\OrbixWeb3.2\bin;D:\jdk1.3\bin;c:\depot\cdk\main\cdk\bin;c:\depot\
cdk\main\cdk\..\bin;d:\OrbixWeb3.2\bin;D:\Program
Files\IBM\GSK\lib;H:\pvcs65\VM\win32\bin;c:\cygnus
\cygwin−b20\H−i586−cygwin32\bin;d:\cfn\bin;D:\orant\bin;
C:\WINNT\system32;C:\WINNT;
d:\Program Files\Symantec\pcAnywhere;
C:\Program Files\Executive Software\DiskeeperServer\;}
LIBPATH:
{D:\jdk1.3\bin;.;C:\WINNT\System32;C:\WINNT;D:\jdk1.3\bin;
c:\depot\cdk\main\cdk\bin;c:\depot\cdk\main\cdk\..\bin;
d:\OrbixWeb3.2\bin;D:\Program Files\IBM\GSK\lib;
H:\pvcs65\VM\win32\bin;c:\cygnus\cygwin−b20\H−i586−cygwin32\bin;d:\cfn\bin;
D:\orant\bin;C:\WINNT\system32;
C:\WINNT;C:\Program Files\Dell\OpenManage\ResolutionAssistant\Common\bin;
d:\Program Files\Symantec\pcAnywhere;

4 Environment
C:\Program Files\Executive Software\DiskeeperServer\;}

Java is prepending itself! That confused me−−− and broke my exec from ant.

4.3 Retrieve environment variables (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0466.html

JDK1.5
System.getenv() is back!

import java.util.*;

public class Test {


public static void main(String args[]) {
// just one
System.out.println("PATH = " + System.getenv("PATH"));

// all of them
Map env = System.getenv();
for (Iterator it=env.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = (Map.Entry)it.next();
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}

See also this HowTo.

See this Howto for common XP environment variables

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

4.4 Retrieve environment variable (JNI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0460.html

For some odd reasons, the getenv() method was removed from the JDK. Rumors is that a
mechanism to retrieve an environment will be back in JDK1.5 (see this HowTo). But for now, you
can use −D switch to retrieve named environment variable and pass them to the JVM (see this
HowTo) or use this JNI routine :

JNIEXPORT jstring JNICALL JavaHowTo_getenv


(JNIEnv *env, jclass c, jstring jname){
if ( jname == NULL ) {
return NULL ;
}
const char *name =
(*env)−>GetStringUTFChars(env, jname, (jboolean *)NULL) ;

4.3 Retrieve environment variables (JDK1.5)


const char *value = getenv(name) ;
(*env)−>ReleaseStringUTFChars(env, jname, name) ;
return value ? (*env)−>NewStringUTF(env, value) : NULL ;
}

NOTE : This is fine if the environment variable contains only regular 7−bit ASCII characters.

See also this HowTo.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

4.5 Use a MAKE file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0158.html

# jMAKEFILE a MAKEFILE for JAVA development


# (Microsoft nMAKE)
# nmake /f j.makefile.mak doc
# to generate JAVADOC

.SUFFIXES: .class .java

JAVAHOME=c:\windev\jdk1.1.3
JAVAC= $(JAVAHOME)\bin\javac
PATH=$(JAVAHOME)\bin;$(PATH)
CLASSPATH=.;$(JAVAHOME)\lib\classes.zip;$(JSDKHOME)\lib\classes.zip
DEST=.
DOC=.
JAVA=$(JAVAHOME)\bin\java
JAVACFLAGS=−deprecation

.SUFFIXES: .java .class

.java.class:
$(JAVAC) −classpath $(CLASSPATH) $(JAVACFLAGS) $<

CLASSFILES = GetImage.class \
myCanvas.class

SOURCEFILES = GetImage.java \
myCanvas.java

# begin −−−− JAR support −−−−−−−−−−


JARFILE= theJAR.jar

$(JARFILE): $(CLASSFILES) $(SOURCEFILES)


jar cfm0 $(JARFILE) <<manifest.tmp $(CLASSFILES)
$(DATAFILES)
Name: GetImage.class
Java−Bean: False

Name: myCanvas.class
Java−Bean: True
<<

4.5 Use a MAKE file


# end −−−− JAR support −−−−−−−−−−

all : $(JARFILE) $(CLASSFILES) doc

doc : $(CLASSFILES)
javadoc −version −author −d $(DOC) $(SOURCEFILES)

install :
copy $CLASSESFILE $(DEST)

clean:
del $(CLASSFILES)

4.6 Detect the browser/JVM type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0160.html

One way is to instanciate a known browser−specific method and catch the Exception if not found

import java.applet.*;

public class BrowserDetector extends Applet {


public void init() {
if ( isNetscape() )
System.out.println("This browser is a Netscape Browser.");
if ( isMicrosoft() )
System.out.println("This browser is a Microsoft Browser.");
}

public static boolean isNetscape() {


try {
Class.forName("netscape.applet.MozillaAppletContext");
}
catch (ClassNotFoundException e) {
System.out.println("This browser is not a Netscape Browser.");
return false;
}
return true;
}

public static boolean isMicrosoft() {


try {
Class.forName("com.ms.applet.GenericAppletContext");
}
catch (ClassNotFoundException e) {
System.out.println("This browser is not a Microsoft Browser.");
return false;
}
return true;
}
}

Or by examining the string representation of the getAppletContext() method

String theBrowser = "APPLICATION";


String appletContext = getAppletContext().toString();
if (appletContext.startsWith("sun.applet.AppletViewer"))
theBrowser = "APPLETVIEWER";

4.6 Detect the browser/JVM type


else if (appletContext.startsWith("netscape.applet."))
theBrowser = "NETSCAPE";
else if (appletContext.startsWith("com.ms.applet."))
theBrowser = "MICROSOFT";
else if (appletContext.startsWith("sunw.hotjava.tags.TagAppletPanel"))
theBrowser = "HOTJAVA";
else if (appletContext.startsWith( "sun.plugin.navig.win32.AppletPlugin"))
theBrowser = "NETSCAPEPLUGIN";
else if (appletContext.startsWith( "sun.plugin.ocx.ActiveXApplet"))
theBrowser = "MICROSOFTPLUGIN;
else if (appletContext.startsWith
( "sun.plugin.viewer.context.IExplorerAppletContext")
theBrowser = "MICROSOFTPLUGINJRE1.4;

For an application, by looking at the string representation of the getDefaultToolkit() method, we


detect the JVM type

String theJVM = "";


String toolkit = Toolkit.getDefaultToolkit().toString();

if (theBrowser.equals("APPLICATION") {
if (toolkit.startsWith( "sun.awt.windows.WToolkit"))
theJVM = "JAVA";
else if (toolkit.startsWith( "com.ms.awt.WToolkit"))
theJVM = "JVIEW";
}

For example, our MyApplet.class exists in three versions. One is using Microsoft−specific classes,
the other is a JDK1.1 applet and finally a version for JDK102−only browser. The idea is to put all the
required classes in an ARCHIVE file. By using a javascript entities, we decide which archive to use.
During layout time, the javascript entity is remplaced by the right archive name.

<HTML></HTML><HEAD>
<SCRIPT>
function isBrowser(b,v) {
browserOk = false;
versionOk = false;
browserOk = (navigator.appName.indexOf(b) != −1);
versionOk = (v <= parseInt(navigator.appVersion));
return browserOk &versionOk;
}

archiveToBeUsed = "java102.jar";

if (isBrowser("Microsoft", 4)) {
archiveToBeUsed = "ie4.jar";
}
else {
if isBrowser("Netscape", 4) {
archiveToBeUsed = "n4.jar";
}
}

</SCRIPT></HEAD><BODY>
<APPLET CODE ="MyApplet.class"
HEIGHT=100
WIDTH=400
ARCHIVE=}; >
</APPLET>
</BODY></HTML>

4.6 Detect the browser/JVM type


NOTE: You may need to use the document.write() method to generate the right APPLET tag instead of a the Javascript entity to be compatible
with Netscape and IE.

4.7 Fix the "Wrong magic number" error message


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0163.html

The "magic number" is represented by the first few bytes of a given file. It is used to identified the
file type.

For Java classes, the magic number is 0xCAFEBABE (you can verify this by viewing a class file
with hexadecimal editor or the DOS Debug utility). This is used by the browser JVM as a quick
check of whether the called file is really a Java class.

If the message is displayed and you are sure that you have uploaded a "real" class to web server
then it's probably because the FTP download has been done in TEXT mode instead of BINARY so
the resulting file on the server is corrupted.

4.8 Use a precompiler "à la C" with Java


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0164.html

Check this list of what is available.

4.9 Determine what are the classes actually used in a Java


Applet or application
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0165.html

In Netscape

1. Open the Java console


2. Press "9" to set the Debug level
3. Execute your applet.
4. Check the console and take note of the loaded classes.

In application

java −verbose:class MyApp

NOTE: This can be useful if you want to trim a JAR to include only classes actually used.

4.7 Fix the "Wrong magic number" error message


4.10 Set the memory available to the JVM
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0131.html

By default, the JVM will use up to 16Mb of RAM. If your program allocates a lot of memory, you may
need to increase this value to give more room to the garbage collector.

When starting the JVM, two parameters can be adjusted to suit your memory needs :

−mx n Sets the maximum size of the memory allocation pool where n is in bytes, appending "m" to
n will specified the number in megabytes, for example to set the maximum at 20Mb :

java −mx 20m myApp

−ms n Sets the startup size of the memory allocation pool, where n is in bytes, appending "m" to n
will specified the number in megabytes. The default is 1Mb.

With JDK1.2, that syntax have changed, no space between ms/mx and the value :

java −mx20m myApp

4.11 Generate the Javadoc "en français"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0437.html

The javadoc utility uses the regular Java mechanism to internationalize its output. The tools.jar in
the lib directory contains the resource bundle standard.properties used by Javadoc to generated the
labels. To add a new language, you need to create the appropriate resource bundle, in our case for
french, we need a file called standard_fr.properties.

The new file must be in the package com.sun.tools.doclets.standard.resources.

Extract from tools.jar, the standard.properties files (keep the directory structure). Copy it under the
name standard_fr.properties. Translate it (or you can download my "incomplete" version here).

[standard.properties (extract)]

doclet.Window_Split_Index={0}\: {1}−Index
doclet.Packages=Packages
doclet.SerialData=Serial Data\:
doclet.Since=Since\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Subinterfaces of {0} in {1}
doclet.Frame_Version=Frame version
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)

[standard_fr.properties (extract)]

doclet.Window_Split_Index={0}\: {1}−Index
doclet.Packages=Paquetages
doclet.SerialData=Donn\u00E9e s\u00E9rialis\u00E9e\:

4.10 Set the memory available to the JVM


doclet.Since=Depuis\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Sous−interfaces de {0} dans {1}
doclet.Frame_Version=Version avec cadres
doclet.Generated_Docs_Untitled=Documentation g\u00E9n\u00E9r\u00E9e

Once everything translated, put your standard_fr.properties into the tools.jar making sure that the
file is located in the right package (along standard.properties in
com.sun.tools.doclets.standard.resources).

To generate in french, use the −locale switch on the command line

javadoc −locale fr ....

NOTE : Make sure the −locale switch is the first one.

Using Ant,

<javadoc
locale="fr"
sourcefiles="c:/client/Client.java"
destdir="javadoc/Client"
author="true"
version="true"
use="true"
private="true"
windowtitle="Client">
<doctitle><![CDATA[<h1>Client</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright &#169; 2003 Real's Howto.</i>]]></bottom>
</javadoc>

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

4.12 Use JDK1.5 new features


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0462.html

• Download the JDK1.5 and install it.


• From a shell, type
java −version

The response should be something like

java version "1.5.0−beta"


Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0−beta−b32c)
JAVA HOTSPOT(TM) CLIENT VM (BUILD 1.5.0−BETA−B32C, MIXED MODE)

On Windows, if you have a "file not found" message, it's because the JVM can't be found
through the PATH. Do it again but with the complete path (if the path contains spaces, make
sure to use quotes!) :

4.12 Use JDK1.5 new features


"c:\program files\java\j2sdk1.5.0\bin\java" −version
• Let's do our first jdk1.5 program :
public class Test15 {
public static void main(String ... args) {
System.out.printf("Local time: %tT", java.util.Calendar.getInstance());
}
}
• Compile it (again you may need to specify the complete path to the compiler if the PATH is
not set correctly):
"c:\program files\java\j2sdk1.5.0\bin\javac" −source 1.5 Test15.java

Note the switch "−source 1.5", if you don't specify it you won't be able to access the new
features (like System.out.printf()).
• Run it
>"C:\Program Files\Java\j2sdk1.5.0\bin\java" Test15
Local time: 15:26:04

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

4.13 Check the class version


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0544.html

The first 4 bytes are a magic number, 0xCAFEBABe, to identify a valid class file then the next 2
bytes identify the class format version (major and minor).

Possible major/minor value :

major minor Java platform version


45 3 1.0
45 3 1.1
46 0 1.2
47 0 1.3
48 0 1.4
49 0 1.5
50 0 1.6

import java.io.*;

public class ClassVersionChecker {


public static void main(String[] args) throws IOException {
for (int i = 0; i < args.length; i++)
checkClassVersion(args[i]);
}

private static void checkClassVersion(String filename)


throws IOException
{
DataInputStream in = new DataInputStream
(new FileInputStream(filename));

int magic = in.readInt();


if(magic != 0xcafebabe) {

4.13 Check the class version


System.out.println(filename + " is not a valid class!");;
}
int minor = in.readUnsignedShort();
int major = in.readUnsignedShort();
System.out.println(filename + ": " + major + " . " + minor);
in.close();
}
}

> java ClassVersionChecker ClassVersionChecker.class


ClassVersionChecker.class: 49 . 0

from The Java Virtual Machine Specification

magic
The magic item supplies the magic number identifying the class file format; it has the value
0xCAFEBABE.

minor_version, major_version
The values of the minor_version and major_version items are the minor and major version numbers
of this class file.Together, a major and a minor version number determine the version of the class
file format. If a class file has major version number M and minor version number m, we denote the
version of its class file format as M.m. Thus, class file format versions may be ordered
lexicographically, for example, 1.5 < 2.0 < 2.1.

A Java virtual machine implementation can support a class file format of version v if and only if v lies
in some contiguous range Mi.0 v Mj.m. Only Sun can specify what range of versions a Java virtual
machine implementation conforming to a certain release level of the Java platform may support.

4.14 Get the system properties or the JVM uptime


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0549.html

The RuntimeMXBean defines several convenient methods for accessing system properties about
the Java virtual machine.

[J2SE 1.5]

import java.util.Date;

import java.lang.management.RuntimeMXBean;
import java.lang.management.ManagementFactory;

class JMXTest {
public static void main(String args[]) {
JMXTest x = new JMXTest();
x.doit();
}

public void doit() {


try{
RuntimeMXBean mx = ManagementFactory.getRuntimeMXBean();
System.out.println("BOOTCLASSPATH:\n" + mx.getBootClassPath());
System.out.println("CLASSPATH:\n" + mx.getClassPath());

4.14 Get the system properties or the JVM uptime


// the input arguments passed to the Java virtual machine
// which does not include the arguments to the main method.
System.out.println("COMMAND LINE ARGS:\n" + mx.getInputArguments());
// a map of names and values of all system properties.
System.out.println("SYSTEM PROPERTIES:\n" + mx.getSystemProperties());

System.out.println("VM start time : " + new Date(mx.getStartTime()));


System.out.println("VM up time : " + mx.getUptime() + " ms");

}
catch (Exception e) {
e.printStackTrace();
}
}
}

4.15 Detect if running in a 64bit JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0565.html

public static boolean is64BitVM() {


String bits = System.getProperty("sun.arch.data.model", "?");
if (bits.equals("64") {
return true;
}
if (bits.equals("?") {
// probably sun.arch.data.model isn't available
// maybe not a Sun JVM?
// try with the vm.name property
return
System.getProperty("java.vm.name")
.toLowerCase().indexOf("64") >= 0;
}
// probably 32bit
return false;
}
}

4.16 Set the default JVM type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0566.html

If you type, in a Shell

> java −version

you get

java version "1.5.0"


Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0−b64)
Java HotSpot(TM) Client VM (build 1.5.0−b64, mixed mode, sharing)

4.15 Detect if running in a 64bit JVM


The default JVM with a JIT (Just−In−Time compiler) for a "client" mode is used. The other available
mode is "server".

From the Hot Spot FAQ at http://java.sun.com/docs/hotspot/HotSpotFAQ.html#compiler_types.

What's the difference between the −client and −server systems?

These two systems are different binaries. They are essentially two different compilers
(JITs)interfacing to the same runtime system. The client system is optimal for applications which
need fast startup times or small footprints, the server system is optimal for applications where the
overall performance is most important. In general the client system is better suited for interactive
applications such as GUIs. Some of the other differences include the compilation policy,heap
defaults, and inlining policy.

Where do I get the server and client systems?

Client and server systems are both downloaded with the 32−bit Solaris and Linux downloads. For
32−bit Windows, if you download the JRE, you get only the client, you'll need to download the SDK
to get both systems.

For 64−bit, only the server system is included. On Solaris, the 64−bit JRE is an overlay on top of the
32−bit distribution. However, on Linux and Windows, it's a completely separate distribution. The
default setting is defined the file jvm.cfg.

On Debian GNU/Linux with Sun Java 1.5.0, the file is in /etc/java−1.5.0−sun.


On Windows, it's in C:\Program Files\Java\jre1.5.0\lib\i386.

A content like

−client KNOWN
−server KNOWN

defines the client as the default.

−server KNOWN
−client KNOWN

sets the server as the default.

4.17 Capture the output of JAVAC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0147.html

method 1a : redirect to a file

// Win95 (?)
javac −J−Djavac.pipe.output=true myClass.java >output.txt
// WinNT (or better)
javac MyClass.java 2output.txt

method 1a : redirect to stdout with a pause after each screen full

4.17 Capture the output of JAVAC


// WinNT (or better)
javac MyClass.java 21 | MORE

method 2 : use JAVA to capture the output

// [JDK 1.1]
// to compile: java JC mySource.java
// (use redirection to keep the output)
// java JC mySource.java >output.txt

import java.io.*;
public class JC {
public static void main( String args[] )
throws IOException, InterruptedException {
String fn = "JC.java";
if( args.length > 0 ) fn = args[0];
System.out.println( "BEGIN (" + fn + ")" );
Process p =
Runtime.getRuntime().exec( "javac −verbose " + fn );
String buf;
BufferedReader se = new BufferedReader
( new InputStreamReader( p.getErrorStream() ) );
while( (buf = se.readLine()) != null )
System.out.println( " : " + buf );
System.out.println( "END (rc:" + p.waitFor() + ")" );
}
}

or you can always use a small text editor like Textpad where you can write with Java code (with
syntax coloring), compile, capture compiler output and launch your Applet or Application directly
from the editor.

4.18 Freeze the JVIEW window in MS VJ++


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0148.html

In your source, add the following line at the end :

java.io.DataInputStream in =
new java.io.DataInputStream(System.in);
String aLine = in.readLine();

and the JVIEW window won't close until you hit ENTER.
Or simply execute JVIEW directly in a DOS window with

jview <classname>

Check this How−to for a better way...

4.19 Know details about the JAVA at run−time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0149.html

4.18 Freeze the JVIEW window in MS VJ++


Applets can read certain system properties by invoking System.getProperty(String key)

java.version Java version number


java.vendor Java vendor−specific string
java.vendor.url Java vendor URL
os.name Operating system name
os.arch Operating system architecture
file.separator File separator (eg, "/")
path.separator Path separator (eg, ":")
line.separator Line separator
java.class.version Java class version number

But applets are prevented from reading these system properties (for security reason):

java.home Java installation directory


java.class.path Java classpath
user.name User account name
user.home User home directory
user.dir User's current working directory

To read a system property from within an applet, simply invoke System.getProperty(key) on the
property you are interested in.

String s = System.getProperty("java.vendor");

Here a dump that can be useful in a log file:

public String dump() {


StringBuffer sb = new StringBuffer();
Runtime rt = Runtime.getRuntime();

long freeMemory = rt.freeMemory();


long totalMemory = rt.totalMemory();

sb.append("free memory=" + freeMemory); sb.append("\n");


sb.append("total memory=" + totalMemory); sb.append("\n");

java.util.Properties p = null;

try {
p = System.getProperties();
}
catch(Exception e) {
e.printStackTrace();
return "";
}

java.util.Enumeration en = p.propertyNames();

while (en.hasMoreElements()){
String s = (String) en.nextElement();
String strValue= p.getProperty(s);
sb.append(s + "=<" + strValue + ">"); sb.append("\n");
}
// result to a string
return sb.toString();
}

4.18 Freeze the JVIEW window in MS VJ++


4.20 Detect the Microsoft JVM version installed
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0327.html

class MSJVMversion
{
public static void main(String[] args)
{
String build;
build=com.ms.util.SystemVersionManager.getVMVersion().getProperty
("BuildIncrement");
System.out.println("Microsoft JVM installed is " + build);
}
}

NOTE:The above snippet will return the Microsoft VM version. This not the same thing as as the JDK version. In this case , Microsoft's Java
environment only goes up to 1.1.4 and there is no plan to upgrade it.

4.21 Run JAVA as a Windows service


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0151.html

A solution adapted to Java, is the Java Service Wrapper (


http://wrapper.tanukisoftware.org/doc/english/introduction.html ) (opensource). The setup is very
simple with one configuration file and your Java service can be notified when the service is stopped.

If you log in and log out from a machine and a java service is running then the service may be
stopped. The fix is to use Java 1.3.1 or higher and start the process with the JVM switch −Xrs
(Reduce Signals Xtended−switch) to stop the Windows signal from killing the JVM.

For BEA JRockit, it's the −Xnohup

Also, it's possible to the utility SRVANY.EXE, included with the NT resource Kit.

http://www.techeez.com/windows_tips/service_under_nt.htm

SVRANY is used to run any EXE as a windows service. In our situation, SVRANY will run the
specified JAVA.EXE with our class a parameter. But this solution presents many problems. For
exemple, if you kill the SVRANY.EXE process (stop the service) then the JAVA.EXE is not killed,
you need to do it manually.

4.22 Execute a class from Windows Explorer


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0328.html

This HowTo will you show how to start a class (with a main() method) without opening a DOS Shell
or using a JAR file directly from Windows Explorer.

4.20 Detect the Microsoft JVM version installed


Type the following VBScript using a text editor and save it as WRunJava.vbs.

You need to save the script in the SendTo subdirectory located in the Windows directory

On a Win98 system, it's C:\Windows\SendTo.

On XP, go to Documents and Settings folder then select the folder of a specific user, eg.
c:\documents and settings\'user name'\SendTo.

NOTE The SendTo folder is hidden by default. If it is not visible, on the Tools menu, click Folder
Options. On the View tab, click Show hidden files and folders. SO you save the scripts shown
below, into the SendTo folder.

Then in Window Explorer, locate a class file that can be executed (with a main() method). Right
click on it, select the Send To menu and you should see an entry called WRunJava.vbs. Simply
select it and the class should be launched via javaw.exe .

' [WRunJava.vbs] start a java class without a console

Dim WSHShell, FSO, javaclass, javacompletepath, cmdline

Set WSHShell = WScript.CreateObject("WScript.Shell")


Set FSO = WScript.CreateObject("Scripting.FileSystemObject")

If WScript.Arguments.Count = 0 Then
WScript.Echo "no argument on the command line."
Else
javaclass = WScript.Arguments(0)
If fso.GetExtensionName(javaclass) = "class" Then
javacompletepath = fso.GetAbsolutePathName(javaclass)
javapath = fso.GetParentFolderName(javacompletepath)
javaclass = fso.GetBaseName(javaclass)
cmdline = "javaw.exe −cp " &javapath &" " &javaclass
WSHShell.Run cmdline, 1, false
ElseIf fso.GetExtensionName(javaclass) = "jar" Then
javacompletepath = fso.GetAbsolutePathName(javaclass)
cmdline = javaclass
WSHShell.Run cmdline, 1, false
Else
WScript.Echo "Not a java class! (" &javaclass &")"
End if
End If

Set WSHShell = Nothing


Set FSO = Nothing
WScript.Quit(0)

You need a second script to launch a java class with a console (useful to see debugging traces or
text−only Java program). Called it CRunJava.vbs . Then you will have two choices from the
SendTo menu, one for console−based program and one for GUI−based (Windows) program.

' [CRunJava.vbs] start a java class with a console

Dim WSHShell, FSO, javaclass, javacompletepath, cmdline

Set WSHShell = WScript.CreateObject("WScript.Shell")


Set FSO = WScript.CreateObject("Scripting.FileSystemObject")

If WScript.Arguments.Count = 0 Then

4.20 Detect the Microsoft JVM version installed


WScript.Echo "no argument on the command line."
Else
javaclass = WScript.Arguments(0)
If fso.GetExtensionName(javaclass) = "class" Then
javacompletepath = fso.GetAbsolutePathName(javaclass)
javapath = fso.GetParentFolderName(javacompletepath)
javaclass = fso.GetBaseName(javaclass)
' keep the console open
cmdline = "cmd /k java.exe −cp " &javapath &" " &javaclass
' close the console
' cmdline = "cmd /c java.exe −cp " &javapath &" " &javaclass
WSHShell.Run cmdline, 1, false

ElseIf fso.GetExtensionName(javaclass) = "jar" Then


javacompletepath = fso.GetAbsolutePathName(javaclass)
cmdline = "java.exe −jar " &javaclass
WSHShell.Run cmdline, 1, false
Else
WScript.Echo "Not a java class! (" &javaclass &")"
End if
End If

Set WSHShell = Nothing


Set FSO = Nothing
'WScript.Quit(0)

Note : A JAR can be made self executable (with double click), see this HowTo

4.23 Create an icon to launch java apps for Windows?


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0157.html

Let's say you have a class named myApp.class and it is located in the directory myJavaApp on
drive C:. Then create a Shortcut to the myApp.class. Next edit the properties of the Shortcut and
change the line

c:\myjavaapp\MyApp.class to javaw MyApp

In the properties tab panel, you also havethe possibility to assign an icon to the Shortcut. If you click
on the newly created icon, your Java application will start without opening a DOS box. If your
application is Text mode application use "java" instead of "javaw".

If the Microsoft JVM is used then use "wjview" (instead of "jview") to start a GUI Java application
from an icon.

4.24 Fix the "out of environment" error when setting a new


CLASSPATH
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0159.html

4.23 Create an icon to launch java apps for Windows?


DOS has a limit on available environment space. You can adjust this in CONFIG.SYS. If your
SHELL statement is set to COMMAND.COM, simply add/modify the SHELL parameter for adjusting
the environment size:

SHELL=C:\windows\command.com C:\windows /p /E:4096

will set off 4 Kb for environment variables.

Command line in DOS has a limit of 127 characters. If you need more room to lanch the JVM then
you have the following workaround.
• Use environment variable like
SET MYCLASSPATH = /files/classes/lib/examples.jar
SET MYARGS = −Djava.security.policy=/files/policy
java −cp %MYCLASSPATH% %MYARGS% myClass
• Use a BAT file.

4.25 Query Windows registry


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0480.html

We launch the REG utility and capture the output. The performance is poor so it's a good idea to
cache frequently used values.

Note : The Microsoft ® Windows NT ® Server 4.0 Resource Kit contains REG.EXE. In Windows 2000 and later REG.EXE is a native command.
The REG utility can be used to write values in the registry (reg add /? for more infos).

In this example,we query the registry to extract the personal folder path ("My Documents") and the
processor ID and its name.

import java.io.*;

public class RegQuery {

private static final String REGQUERY_UTIL = "reg query ";


private static final String REGSTR_TOKEN = "REG_SZ";
private static final String REGDWORD_TOKEN = "REG_DWORD";

private static final String PERSONAL_FOLDER_CMD = REGQUERY_UTIL +


"\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Explorer\\Shell Folders\" /v Personal";
private static final String CPU_SPEED_CMD = REGQUERY_UTIL +
"\"HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\""
+ " /v ~MHz";
private static final String CPU_NAME_CMD = REGQUERY_UTIL +
"\"HKLM\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\""
+ " /v ProcessorNameString";

public static String getCurrentUserPersonalFolderPath() {


try {
Process process = Runtime.getRuntime().exec(PERSONAL_FOLDER_CMD);
StreamReader reader = new StreamReader(process.getInputStream());

reader.start();
process.waitFor();
reader.join();

4.25 Query Windows registry


String result = reader.getResult();
int p = result.indexOf(REGSTR_TOKEN);

if (p == −1)
return null;

return result.substring(p + REGSTR_TOKEN.length()).trim();


}
catch (Exception e) {
return null;
}
}

public static String getCPUSpeed() {


try {
Process process = Runtime.getRuntime().exec(CPU_SPEED_CMD);
StreamReader reader = new StreamReader(process.getInputStream());

reader.start();
process.waitFor();
reader.join();

String result = reader.getResult();


int p = result.indexOf(REGDWORD_TOKEN);

if (p == −1)
return null;

// CPU speed in Mhz (minus 1) in HEX notation, convert it to DEC


String temp = result.substring(p + REGDWORD_TOKEN.length()).trim();
return Integer.toString
((Integer.parseInt(temp.substring("0x".length()), 16) + 1));
}
catch (Exception e) {
return null;
}
}

public static String getCPUName() {


try {
Process process = Runtime.getRuntime().exec(CPU_NAME_CMD);
StreamReader reader = new StreamReader(process.getInputStream());

reader.start();
process.waitFor();
reader.join();

String result = reader.getResult();


int p = result.indexOf(REGSTR_TOKEN);

if (p == −1)
return null;

return result.substring(p + REGSTR_TOKEN.length()).trim();


}
catch (Exception e) {
return null;
}
}

static class StreamReader extends Thread {


private InputStream is;
private StringWriter sw;

4.25 Query Windows registry


StreamReader(InputStream is) {
this.is = is;
sw = new StringWriter();
}

public void run() {


try {
int c;
while ((c = is.read()) != −1)
sw.write(c);
}
catch (IOException e) { ; }
}

String getResult() {
return sw.toString();
}
}

public static void main(String s[]) {


System.out.println("Personal directory : "
+ getCurrentUserPersonalFolderPath());
System.out.println("CPU Name : " + getCPUName());
System.out.println("CPU Speed : " + getCPUSpeed() + " Mhz");
}
}

See also this HowTo and this one.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

4.26 Quickly retrieve available Java JVM on a workstation


(Windows)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0525.html

Use regedit utility to query the Windows registry, the result is written into a file.

start /w regedit /e jre.txt


"HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"

The content of jre.txt on my machine :

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment]


"CurrentVersion"="1.5"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.4]


"JavaHome"="C:\\Program Files\\Java\\j2re1.4.1_02"
"RuntimeLib"="C:\\Program Files\\Java\\j2re1.4.1_02\\bin\\client\\jvm.dll"
"MicroVersion"="1"

4.26 Quickly retrieve available Java JVM on a workstation (Windows)


[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.4.1_02]
"JavaHome"="C:\\Program Files\\Java\\j2re1.4.1_02"
"MicroVersion"="1"
"RuntimeLib"="C:\\Program Files\\Java\\j2re1.4.1_02\\bin\\client\\jvm.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.5]


"JavaHome"="C:\\Program Files\\Java\\jre1.5.0"
"RuntimeLib"="C:\\Program Files\\Java\\jre1.5.0\\bin\\client\\jvm.dll"
"MicroVersion"="0"

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.5.0]


"JavaHome"="C:\\Program Files\\Java\\jre1.5.0"
"MicroVersion"="0"
"RuntimeLib"="C:\\Program Files\\Java\\jre1.5.0\\bin\\client\\jvm.dll"

A CMD file for Windows to display the default JRE used :

@echo off
::Find the current (most recent) Java version
start /w regedit /e reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment"
type reg1.txt | find "CurrentVersion" > reg2.txt
if errorlevel 1 goto ERROR
for /f "tokens=2 delims==" %%x in (reg2.txt) do set JavaTemp=%%~x
if errorlevel 1 goto ERROR
echo Java Version = %JavaTemp%
del reg1.txt
del reg2.txt

::Get the home directory of the most recent Java


start /w regedit /e reg1.txt "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\%Ja
type reg1.txt | find "JavaHome" > reg2.txt
if errorlevel 1 goto ERROR
for /f "tokens=2 delims==" %%x in (reg2.txt) do set JavaTemp=%%~x
if errorlevel 1 goto ERROR
echo Java home path (per registry) = %JavaTemp%
del reg1.txt
del reg2.txt

pause

The above script returns the default JVM if the PATH variable does not override it!

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

4.27 Get the Windows "My Documents" path


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0572.html

This value is stored in the registry and there is no easy way to get it with regular Java unless you
execute an external utility, see this HowTo.

As an alternative, we can use a method provided by the JFileChooser class.

4.27 Get the Windows "My Documents" path


import javax.swing.JFileChooser;
javax.swing.filechooser.FileSystemView;

public class GetMyDocuments {


public static void main(String args[]) {
JFileChooser fr = new JFileChooser();
FileSystemView fw = fr.getFileSystemView();
System.out.println(fw.getDefaultDirectory());
}
}

4.28 Get a return code from a VBS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0575.html

You can't detect directly if Windows service is running or not in Java.

However, it's easy to do from a VBS. You execute the script from Java, wait for its completion and
capture the return code.

Obviously, this is useful only on the Windows plateform.

import java.io.File;
import java.io.FileWriter;

public class VBSUtils {


private VBSUtils() { }

public static boolean isServiceRunning(String serviceName) {


try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Set sh = CreateObject(\"Shell.Application\") \n"


+ "If sh.IsServiceRunning(\""+ serviceName +"\") Then \n"
+ " wscript.Quit(1) \n"
+ "End If \n"
+ "wscript.Quit(0) \n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("wscript " + file.getPath());
p.waitFor();
return (p.exitValue() == 1);
}
catch(Exception e){
e.printStackTrace();
}
return false;
}

public static void main(String[] args){


//
// DEMO
//
String result = "";
msgBox("Check if service 'Themes' is running (should be yes)");

4.28 Get a return code from a VBS


result = isServiceRunning("Themes") ? "" : " NOT ";
msgBox("service 'Themes' is " + result + " running ");

msgBox("Check if service 'foo' is running (should be no)");


result = isServiceRunning("foo") ? "" : " NOT ";
msgBox("service 'foo' is " + result + " running ");
}

public static void msgBox(String msg) {


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

4.29 List currently running processes (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0593.html

4.29.1 Using TASKLIST.EXE

The Microsoft TASKLIST.EXE is used to dump the list of the currently running processes. It is
similar to tasklist window but for the console. From a Java program, we are launching
TASKLIST.EXE and capture its output.

Note : TASKLIST.EXE is not included the HOME edition of XP. But you can download it from Web,
for example : http://www.computerhope.com/download/winxp.htm.

import java.io.*;
import java.util.*;

public class WindowsUtils {


public static List listRunningProcesses() {
List<String> processes = new ArrayList<String>();
try {
String line;
Process p = Runtime.getRuntime().exec("tasklist.exe /nh");
BufferedReader input = new BufferedReader
(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
if (!line.trim().equals("")) {
// keep only the process name
processes.add(line.substring(0, line.indexOf(" ")));
}

}
input.close();
}
catch (Exception err) {
err.printStackTrace();
}
return processes;
}

public static void main(String[] args){


List<String> processes = listRunningProcesses();
String result = "";

4.29 List currently running processes (Windows)


// display the result
Iterator<String> it = processes.iterator();
int i = 0;
while (it.hasNext()) {
result += it.next() +",";
i++;
if (i==10) {
result += "\n";
i = 0;
}
}
msgBox("Running processes : " + result);
}

public static void msgBox(String msg) {


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "WindowsUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

4.29.2 Using a VBS

Another technique to build the required VBScript on−the−fly, execute it and capture its output.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.util.*;

public class VBSUtils {


private VBSUtils() { }

public static List<String> listRunningProcesses() {


List<String> processList = new ArrayList<String>();
try {

File file = File.createTempFile("realhowto",".vbs");


file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Set WshShell = WScript.CreateObject(\"WScript.Shell\")\n"


+ "Set locator = CreateObject(\"WbemScripting.SWbemLocator\")\n"
+ "Set service = locator.ConnectServer()\n"
+ "Set processes = service.ExecQuery _\n"
+ " (\"select name from Win32_Process\")\n"
+ "For Each process in processes\n"
+ "wscript.echo process.Name \n"
+ "Next\n"
+ "Set WSHShell = Nothing\n";

fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
processList.add(line);
}
input.close();

4.29.2 Using a VBS


}
catch(Exception e){
e.printStackTrace();
}
return processList;
}

public static void main(String[] args){


List<String> processes = listRunningProcesses();
String result = "";

Iterator<String> it = processes.iterator();
int i = 0;
while (it.hasNext()) {
result += it.next() +",";
i++;
if (i==10) {
result += "\n";
i = 0;
}
}
msgBox("Running processes : " + result);
}

public static void msgBox(String msg) {


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

4.30 Windows registry vs. Java JDK/JRE installation


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0604.html

The JDK itself does not use the windows registry to run.

It is the JRE that uses the system registry to run in some situations like an Applet or a program
started with the WebStart technolgy.

Finally, the JRE will only use the registry if it is run from the Windows system directory (ex .
C:/winnt/system32/java.exe). This would happen if the user just types "java" on the commandline in
some random directory, because the system directory is always in the user's path. In this situation,
the java.exe will locate the current Java installation by looking at the registry key

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\CurrentVersion]

and then get the path of the JRE from the corresponding key

[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.5\JavaHome]

Beware that some software (eg. Oracle) installs themself at the beginning of the PATH definition, so
it's their Java installation that will be found first.

You can run the absolute path to the java.exe file, as in

4.30 Windows registry vs. Java JDK/JRE installation


"C:\Program Files\Java\jre1.5.0\bin\java.exe" MyClass

It will not use the registry, and it will be guaranteed to use jre1.5.0.

So for a regular Java SE program, it is safe to specify the complete path to the JRE to launch it.

But for the Applet/Plugin or WebStart−based programs, the registry is always used to determine the
current JRE.

4.31 Use a JAR/ZIP/CAB file with an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0153.html

[JAR format]
JAR (Java ARchive) is a platform−independent file format that allows you to bundle a Java applet
and its requisite components (.class files, images and sounds) into a single JAR file. JAR supports
compression, which reduces the file size, further improving the download time.

The applet author can digitally sign individual entries in a JAR file to authenticate their origin (using
the JAVAKEY utility). However, to sign JAR to be used with a "real−world" browser (eg. Netscape),
you must use Netscape's utilities ZIGbert or GUI JAR Archiver to sign it. These utilities can be freely
downloaded from the Netscape Web site. For more infos about signing Applet for Netscape, check
this JAVA How−to.

The browser need to be JDK1.1 compatible to handle JAR file.

If a JAR file is used with an Applet, the browser will look first into the JAR to load all classes. If the
search fails in the JAR file, then the browser looks in the applet's base directory. To specify the use
of a JAR file with an applet:

<APPLET CODE=a.class
ARCHIVE="abc.jar"
WIDTH=100
HEIGHT=100>
</APPLET>

In theory, you can specify many JARs in one ARCHIVE tag. But the current version of Netscape will
only load the first JAR and ignore the others.

Microsoft IEv4 can handle multiple JAR files.

In an application, simply include the JAR in the CLASSPATH :

java −classpath c:\jdk1.1.3\lib\classes.zip;.;.\HelloWorld.jar HelloWorld

To create a JAR file (compressed), use the JAR utility included with JDK1.1

jar cvf abc.jar a.class b.class c.class

According to some JAVA developers, JAR in CLASSPATH needs to be uncompressed (JDK1.1). To create uncompressed JAR:

4.31 Use a JAR/ZIP/CAB file with an Applet


jar cvfO myArchive.jar *.class

[ZIP format]
JDK1.0.2 introduces the ZIP "un−compressed" format. To create an archive, simply use a ZIP tool
that supports the long filename format and specify the ZERO compression mode. You can use
Sun's JAR utility (included with JDK1.1) to create a JDK1.0.2 compatible ZIP file:

jar cvfO myArchive.zip *.class

or check for InfoZIP at http://www.cdrom.com/pub/infozip/

To use a ZIP archive, simply use the HTML ARCHIVE tag

<APPLET CODE="a.class"
ARCHIVE="abc.zip"
WIDTH=618
HEIGHT=410>
</APPLET>

[CAB format]
CAB (for CABINET) is used only by Microsoft Internet Explorer. It offers compression (like the JAR
but the ZIP format is un−compressed). To create a CAB file, use the CABARC utility from Microsoft :

CABARC n myArchive.cab *.*

to create myArchive.cab.

It is possible sign a CAB file using the Authenticode mechanism, check the Microsoft Web site for
more infos.

To associate a CAB file with an Applet, simply use the HTML :

<APPLET CODE="a.class"
WIDTH=100
HEIGHT=100>
<PARAM NAME="cabbase"
VALUE="abc.cab">
</APPLET>

the cabbase parameter will be interpreted only by MSIE, non−MS browsers browser will simply
ignore it.

An Applet can support ZIP and CAB format by using the following HTML:

<APPLET
CODEBASE="."
ARCHIVE=abc.zip
CODE=a.class
width=610
height=600 >
<PARAM NAME="cabbase" VALUE="abc.cab">
</APPLET>

while Netscape will use the ZIP file and ignore de CAB parameter, MSIE will use CAB and ignore
the ZIP file.

4.31 Use a JAR/ZIP/CAB file with an Applet


Written and compiled by Réal Gagnon ©1998−2000 mailto:real@rgagnon.com

[ home ]

4.32 Make ZIP/JAR file always accessible from applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0154.html

[Netscape 4]
Manual method
Copy the ZIP/JAR file in the PLUGINS directory and remove the reference in the ARCHIVE
parameter of the APPLET tag.

For example, to be able use SWING classes from Netscape, copy SWING.JAR and ROSE.JAR in
the PLUGINS directory and restart Netscape.

Automatic method
Automatic installation can be done with Netscape using the SmartUpdate mechanism. The JAR
must be signed with the Netscape Signing Tool.Check the following links for more infos:
http://developer.netscape.com/docs/manuals/communicator/jarman/
http://developer.netscape.com/docs/manuals/signedobj/overview.html

4.33 Make a JAR executable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0166.html

In the manifest file of a JAR, it is possible to specify the class to be used when the JVM is lauched
with the JAR as parameter. The class must have a main().

Try with this simple class

import java.awt.*;
import java.awt.event.*;

public class MyClass {


public static void main(String[] args) {
Frame f = new Frame();
f.addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
f.add(new Label("Hello world"));
f.setSize(200,200);
f.setVisible(true);
}
}

Then create this manifest file (manifest.mft) with any text editor.

4.32 Make ZIP/JAR file always accessible from applet


Manifest−Version: 1.0
Main−Class: MyClass
Class−path: .

Main−Class specifies the entry point with the main(String args[]) method.

The Class−path is used to specify the dependency of this jar (if any). You add the directories and
jars separated by a space. It is important because when running a jar , the CLASSPATH definition
(as defined by the environnement variable) is overridden.

Next, you include the manifest file in the JAR (MyJar.jar) with the MyClass class.

jar cvfm myjar.jar manifest.mft *.class

Then you are able to start the MyClass.class by double−clicking on the MyJar.jar file (if the JRE is
correctly installed) or by typing

java −jar myjar.jar

If you need to pass parameters, use the −D switch before the −jar switch and use the getProperty()
method to get the value.

The file association mechanism is made during the installation of the JRE.

You can verify that everything is ok with the following command from a DOS Shell

>assoc .jar
.jar=jarfile

>ftype jarfile
jarfile="C:\Program Files\Java\jre1.5.0_10\bin\javaw.exe" −jar "%1" %*

If the association is broken or you need to change the JRE used then by using the assoc/ftype
utilities, you can modify the association easily (use /? to display the syntax of the assoc and ftype
utilities).

NOTE: On WinXp (or better), your user account needs to be at the Admin level.

On Windows (NT or better), you can also make JARs run from the command−line by setting the
PATHEXT environment variable, for example
SET PATHEXT=.EXE;.BAT;.CMD;.JAR

Then if you have the jar file MyJar.jar accessible via the PATH environment variable, typing "MyJar"
on the DOS command line will invoke "javaw −jar MyJar.jar" .

4.34 Accessing jars from within a jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0319.html

Supposed we have a jar called Main.jar for the application. This application needs Second.jar and
Third.jar . In the manifest file of the first jar (Main.jar), you adjust the Class−Path setting :

4.34 Accessing jars from within a jar


Manifest−Version: 1.0
Main−Class: MyClass
Class−Path: Second.jar Third.jar

The value of the Class−Path attribute specifies the relative URLs of the extensions or libraries that
this application or extension needs. URLs are separated by one or more spaces. The application or
extension class loader uses the value of this attribute to construct its internal search path.

You can use the −i option to speed up your application's class loading time:
jar −i main.jar

This will build an an INDEX.LIST file in the META−INF directory which will enable the application
class loader to download the right jar files when it is searching for classes or resources.

4.35 Access a JAR outside the CLASSPATH


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0409.html

import java.net.*;
import java.io.*;

public class ExtraLoader {

public static void main(String[] args) {


try {
URL urlA =
new File("C:/xtras/xercesImpl.jar").toURL();
URL urlB =
new File("C:/xtras/xmlParserAPIs.jar").toURL();
URL[] urls = { urlA,urlB };
URLClassLoader ulc = new URLClassLoader(urls);
//
Class c = Class.forName
("org.apache.xerces.dom.ChildNode", true, ulc);
//
System.out.println(c.getName());
}
catch(Exception e) {
e.printStackTrace();
}
}
}

4.36 Extract a file from a Jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0429.html

The following snippet extract a file (mydb.mdb) from a jar.

import java.io.*;
import java.util.jar.*;
import java.util.zip.*;

4.35 Access a JAR outside the CLASSPATH


public class ExtractFromJAR {

public void extractMyMDBromJAR(String dest){


try {
String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().
substring(6);
JarFile jar = new JarFile(home);
ZipEntry entry = jar.getEntry("mydb.mdb");
File efile = new File(dest, entry.getName());

InputStream in =
new BufferedInputStream(jar.getInputStream(entry));
OutputStream out =
new BufferedOutputStream(new FileOutputStream(efile));
byte[] buffer = new byte[2048];
for (;;) {
int nBytes = in.read(buffer);
if (nBytes <= 0) break;
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String args []){


new ExtractFromJAR().extractMyMDBFromJAR(".");
}

Grab this auto−run Jar if you want to try it.

To create an auto−run JAR, first create a manifest.mft

Manifest−Version: 1.0
Classpath: .\mydb.jar
Main−Class: ExtractFromJAR

Create the JAR

C:\jdk141\bin\jar cvfm mydb.jar manifest.mft ExtractFromJAR.class mydb.mdb

Run it ... and the mydb.mdb file should appear in the current directory.

java −jar mydb.jar

(A tip from Fred Hommersom) Your code reads:


String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().substring(6);

I got a problem when the jar file was located in C:\Program Files\xyz due to the embedded space.
So I modified the code to

4.35 Access a JAR outside the CLASSPATH


String home = getClass().getProtectionDomain()
.getCodeSource().getLocation()
.getPath().replaceAll("%20", " ");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

4.37 Determine if running from JAR


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0391.html

package com.rgagnon;

public class HelloClass {


public static void main(String[] args) {
new HelloClass().say();
}

public void say() {


String className = this.getClass().getName().replace('.', '/');
String classJar =
this.getClass().getResource("/" + className + ".class").toString();
if (classJar.startsWith("jar:")) {
System.out.println("*** running from jar!");
}
System.out.println(classJar);
}
}

The output

>jar cvfm Hello.jar manifest.mft com\rgagnon\HelloClass.class


added manifest
adding: com/rgagnon/HelloClass.class (in=1059) (out=601) (deflated 43%)

>java com.rgagnon.HelloClass
file:/C:/DEV/WORK/JAVA/com/rgagnon/HelloClass.class

>java −jar Hello.jar


*** running from jar!
jar:file:/C:/DEV/WORK/JAVA/Hello.jar!/com/rgagnon/HelloClass.class

See these related HowTo's : 1 2

4.38 Get list of classes in package (in a Jar)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0513.html

import java.util.jar.*;
import java.util.*;
import java.io.*;

4.37 Determine if running from JAR


public class PackageUtils {

private static boolean debug = true;

public static List getClasseNamesInPackage


(String jarName, String packageName){
ArrayList classes = new ArrayList ();

packageName = packageName.replaceAll("\\." , "/");


if (debug) System.out.println
("Jar " + jarName + " looking for " + packageName);
try{
JarInputStream jarFile = new JarInputStream
(new FileInputStream (jarName));
JarEntry jarEntry;

while(true) {
jarEntry=jarFile.getNextJarEntry ();
if(jarEntry == null){
break;
}
if((jarEntry.getName ().startsWith (packageName)) &
(jarEntry.getName ().endsWith (".class")) ) {
if (debug) System.out.println
("Found " + jarEntry.getName().replaceAll("/", "\\."));
classes.add (jarEntry.getName().replaceAll("/", "\\."));
}
}
}
catch( Exception e){
e.printStackTrace ();
}
return classes;
}

/**
*
*/
public static void main (String[] args){
List list = PackageUtils.getClasseNamesInPackage
("C:/j2sdk1.4.1_02/lib/mail.jar", "com.sun.mail.handlers");
System.out.println(list);
/*
output :

Jar C:/j2sdk1.4.1_02/lib/mail.jar looking for com/sun/mail/handlers


Found com.sun.mail.handlers.text_html.class
Found com.sun.mail.handlers.text_plain.class
Found com.sun.mail.handlers.text_xml.class
Found com.sun.mail.handlers.image_gif.class
Found com.sun.mail.handlers.image_jpeg.class
Found com.sun.mail.handlers.multipart_mixed.class
Found com.sun.mail.handlers.message_rfc822.class
[com.sun.mail.handlers.text_html.class,
com.sun.mail.handlers.text_xml.class, com
.sun.mail.handlers.image_jpeg.class,
, com.sun.mail.handlers.message_rfc822.class]

*/
}
}

4.37 Determine if running from JAR


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

4.39 Add version to Jar packaging


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0388.html

Let's say we have the following class (package is mandatory)

package com.rgagnon;

public class Hello {


public static void main(String[] args) {
new Hello().say("Hello World!");
}

public void say(String s) {


System.out.println(s);
}
}

First create a MANIFEST.MF file :

Manifest−Version: 1.0
Main−Class: com.rgagnon.Hello

Then build the executable Jar and run it.

>jar cvfm hello.jar MANIFEST.MF com\rgagnon\Hello.class

>java −jar hello.jar


Hello World!

Now modify the manifest to include versioning information.

Manifest−Version: 1.0
Main−Class: com.rgagnon.Hello
Specification−Version: 2.1
Implementation−Version: 1.1

Modify the class to display the version.

package com.rgagnon;

public class Hello {


public static void main(String[] args) {
new Hello().say("Hello World!");
}

Hello() {
Package p = this.getClass().getPackage();
System.out.println("Hello Specification Version : "
+ p.getSpecificationVersion());
System.out.println("Hello Implementation Version : "

4.39 Add version to Jar packaging


+ p.getImplementationVersion());
}

public void say(String s) {


System.out.println(s);
}
}

Compile and rebuild the Jar and execute

> jar cvfm hello.jar MANIFEST.MF com\rgagnon\Hello.class

> java −jar hello.jar


Specification Version : 2.1
Implementation Version : 1.1
Hello World!

See also this Howto.

This example opens a given Jar and outputs its version information.

package com.rgagnon.howto;

import java.util.jar.*;

public class JarUtils {


public static String getJarImplementationVersion(String jar)
throws java.io.IOException
{
JarFile jarfile = new JarFile(jar);
Manifest manifest = jarfile.getManifest();
Attributes att = manifest.getMainAttributes();
return att.getValue("Implementation−Version");
}

public static String getJarSpecificationVersion(String jar)


throws java.io.IOException
{
JarFile jarfile = new JarFile(jar);
Manifest manifest = jarfile.getManifest();
Attributes att = manifest.getMainAttributes();
return att.getValue("Specification−Version");
}
public static void main(String[] args) throws java.io.IOException{
String javaMailJar = "C:/Program Files/Java/jre1.5.0/lib/mail.jar";

System.out.println("Specification−Version: "
+ JarUtils.getJarSpecificationVersion(javaMailJar));
System.out.println("Implementation−Version: "
+ JarUtils.getJarImplementationVersion(javaMailJar));
/*
* output :
* Specification−Version: 1.3
* Implementation−Version: 1.3.1
*/
}
}

4.39 Add version to Jar packaging


4.40 Use ANT to Build a JAR with version/build number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0532.html

• Download ANT from http://ant.apache.org/bindownload.cgi


• Unzip into the root of C: (Windows), rename the folder to \Ant
• Create a file call antenv.cmd. Before using ANT, you must execute this file to set up the
environment. You may need to adjust the values according to your installation!
set ANT_HOME=c:\ant
set JAVA_HOME=C:\Progra~1\Java\jdk1.5.0
set PATH=%ANT_HOME%\bin;%JAVA_HOME%\bin;%path%
• Create a simple Hello class as shown below (you need have a package).
package howto;
public class Hello {
public static void main( String[] args ){
System.out.println( "Hello World" );
}
}
• Execute your antenv.cmd to set the environment
• Compile your Hello class and make a jar to check if your environment is ok.
> javac howto/Hello.java
> jar −cvf hello.jar howto/Hello.class
added manifest
adding: howto/hello.class(in = 415) (out= 284) (deflated 31%)
> java −cp hello.jar howto.Hello
Hello World
• Create a build.xml which is the default ant build file ...
• ... and load it into your favorite editor. Type the following ant script and save it.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>
</project>

Go back to the DOS shell and launch Ant with

> ant compile


Buildfile: build.xml

compile:
[javac] Compiling 1 source file
• Go back to the editor and add the jar building command. The target compile is also executed
since the target jar depends on it.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">


<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
/>
</target>
</project>
• Execute your Ant script :
> ant jar
Buildfile: build.xml

4.40 Use ANT to Build a JAR with version/build number


compile:

jar:
[jar] Building jar: /Dev/hello.jar

BUILD SUCCESSFUL
Total time: 2 seconds
$ jar −tvf hello.jar
jar −tvf hello.jar
0 Wed May 03 17:06:32 EST 2006 META−INF/
55 Wed May 03 17:06:32 EST 2006 META−INF/MANIFEST.MF
55 Wed May 03 17:06:32 EST 2006 howto/
335 Wed May 03 16:36:16 EST 2006 howto/Hello.class
• Try your new Jar file
> java −cp Hello.jar howto.Hello
Hello World
• Make your Jar auto−executable by specifying the Main class into a MANIFEST.MF file to be
included in the Jar. Add the following lines to build.xml
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">


<delete file="hello.jar"/>
<delete file="MANIFEST.MF"/>
<manifest file="MANIFEST.MF">
<attribute name="Built−By" value="${user.name}"/>
<attribute name="Main−Class" value="howto.Hello"/>
</manifest>

<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>
</project>
• Now you can launch Hello with only
> ant jar
...
> java −jar hello.jar
Hello World
• Add a build number with the Ant task buildnumber . Ant will create (if necessary) and increment a
property in a file called build.num (so you need to keep it!). Then a property, build.number, is
available in your Ant script. The version number is also a property. Here it is hard−coded in the
script but you can read it from a file.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar" depends="compile">


<delete file="hello.jar"/>
<delete file="MANIFEST.MF"/>
<property name="version.num" value="1.00"/>
<buildnumber file="build.num"/>

<manifest file="MANIFEST.MF">
<attribute name="Built−By" value="${user.name}"/>
<attribute name="Main−Class" value="howto.Hello"/>

4.40 Use ANT to Build a JAR with version/build number


<attribute name="Implementation−Version"
value="${version.num}−b${build.number}"/>
</manifest>

<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>
</project>
• If you examine the MANIFEST.MF, you now see a new entry
Implementation−Version: 1.00−b1
• and after the next build operation, the entry will be
Implementation−Version: 1.00−b2
• Modify the Hello class to read the Implementation−Version information and display it.
package howto;

public class Hello {


public static void main( String[] args ){
System.out.println( "Hello World ");
System.out.println("version : " +
Hello.class.getPackage().getImplementationVersion() );
}
}
• Finally we add a target to cleanup and the main target to build everything to the build.xml file.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>

<target name="jar">
<delete file="hello.jar"/>
<property name="version.num" value="1.00"/>
<buildnumber file="build.num"/>

<manifest file="MANIFEST.MF">
<attribute name="Built−By" value="${user.name}"/>
<attribute name="Main−Class" value="howto.Hello"/>
<attribute name="Implementation−Version"
value="${version.num}−b${build.number}"/>
</manifest>

<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>

<target name="cleanup">
<delete>
<fileset dir="." includes="**/*.class"/>
<fileset file="MANIFEST.MF"/>
</delete>
</target>

<target name="buildHello" depends="compile,jar,cleanup" />


</project>
• Build and launch the Hello class
> ant buildHello
...

4.40 Use ANT to Build a JAR with version/build number


> java −jar hello.jar
Hello World
version : 1.00−b3

b3 == build #3 (if it's your third build !)

Build number is great but a Built date is useful too!

...
<target name="jar">
<delete file="hello.jar"/>
<property name="version.num" value="1.00"/>
<buildnumber file="build.num"/>
<tstamp>
<format property="TODAY" pattern="yyyy−MM−dd HH:mm:ss" />
</tstamp>

<manifest file="MANIFEST.MF">
<attribute name="Built−By" value="${user.name}"/>
<attribute name="Main−Class" value="howto.Hello"/>
<attribute name="Implementation−Version"
value="${version.num}−b${build.number}"/>
<attribute name="Built−Date" value="${TODAY}"/>
</manifest>

<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>

See also this Howto .

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

4.41 Include all jars in the classpath definition


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0587.html

Specifying all the required jar in the classpath can be a pain. Here some techniques to set the
classpath definition automatically.

4.42 Windows batch file


For Windows 2000 (or better), we need a set of 3 CMD files to scan a given directory and build the
classpath defintion with all the jars found.

main.cmd

@echo off
call buildclasspath.cmd .\lib

4.41 Include all jars in the classpath definition


Echo The Classpath definition is %CLASSPATH%
...
java MyClass

buildclasspath.cmd

set _CLASSPATH=%CLASSPATH%

set CLASSPATH=%1
for %%i in ( %1\*.jar ) do call buildclasspath_append.cmd %%~fsi

if "%_CLASSPATH%" == "" goto END


set CLASSPATH=%_CLASSPATH%;%CLASSPATH%

:END

buildclasspath_append.cmd

set CLASSPATH=%CLASSPATH%;%1

With XP (or better), it's simpler ... a single batch file can do the job.

@echo off
setlocal ENABLEDELAYEDEXPANSION
if defined CLASSPATH (set CLASSPATH=%CLASSPATH%;.) else (set CLASSPATH=.)
FOR /R .\lib %%G IN (*.jar) DO set CLASSPATH=!CLASSPATH!;%%G
Echo The Classpath definition is %CLASSPATH%
...
java MyClass

4.43 JDK6
According to http://java.sun.com/javase/6/docs/technotes/tools/windows/java.html, there is a new
way to include jars in a given directory without explicitly to specify each one of them.

As a special convenience, a class path element containing a


basename of * is considered equivalent to specifying a list
of all the files in the directory with the extension .jar
or .JAR (a java program cannot tell the difference between
the two invocations).

For example, if directory foo contains a.jar and b.JAR, then


the class path element foo/* is expanded to a A.jar:b.JAR,
except that the order of jar files is unspecified. All jar files
in the specified directory, even hidden ones, are included in
the list. A classpath entry consisting simply of * expands to a
list of all the jar files in the current directory. The CLASSPATH
environment variable, where defined, will be similarly expanded.

Note : There is a bug when using this feature with JAVAW, see
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6510337

Note : Use quote to avoid problem during the wildcard expansion, ex. javac −cp "C:\mylib\*"
HelloWorld.java

4.43 JDK6
4.44 JAR (and ANT)
The best solution when you have a jar is to try to include the required jars into the manifest
declaration.

Manifest−Version: 1.0
Class−Path:
customer_client.jar
mailer_client.jar
signon_client.jar

The manifest file format restrictions mandated by the JDK requires the use of a space ' ' character
as the line continuation character, so ensure that your editor is not set up to trim trailing spaces on
saves and exits.

The line with the Class−Path: header must end with a space character and each of the lines
referencing the client jar's should start and end with a space ' ' character and the manifest file as a
whole must end with a blank line.

Remember that when you launch an application with


java −jar myjar.jar

the CLASSPATH definition (as defined by the environment variable) is overriden by the "class−path"
defined the jar's manifest.

See http://java.sun.com/docs/books/tutorial/deployment/jar/downman.html

Ant can be used to build your Jar and built the manifest class−path definition.

<target name="MyJar" depends="dist, compile" description="generate jar" >


<jar destfile="${dist}/${jar}">
<manifest>
<attribute name="Main−Class" value="${Main_Class}"/>
<attribute name="Class−Path" value=". lib/utils.jar lib/client.jar" />
</manifest>
</jar>
</target>

It's possible (but not so simple) to do it automatically without specifying each jar one by one :

<path id="build.classpath">
<fileset dir="${basedir}"/>
<include name="lib/*.jar"/>
</fileset>
</path>

<pathconvert property="manifest.classpath" pathsep=" ">


<path refid="build.classpath"/>
<mapper>
<chainedmapper>
<flattenmapper/>
<globmapper from="*.jar" to="lib/*.jar"/>
</chainedmapper>
</mapper>
</pathconvert>

4.44 JAR (and ANT)


<target depends="compile" name="buildjar">
<jar jarfile="${basedir}/${test.jar}">
<fileset dir="${build}" />
<manifest>
<attribute name="Main−Class" value="com.mycompany.TestMain"/>
<attribute name="Class−Path" value="${manifest.classpath}"/>
</manifest>
</jar>
</target>

Latest Ant version (1.7) includes a task called ManifestClassPath which converts a classpath into a
space−separated list of items used to set the Manifest Class−Path attribute. See
http://ant.apache.org/manual/CoreTasks/manifestclasspath.html

<path id="build−classpath">
<fileset dir="${build.dir}">
<include name="*.jar"/>
</fileset>
</path>

<manifestclasspath property="lib.list" jarfile="${build.dir}/${jar.file}">


<classpath refid="build−classpath" />
</manifestclasspath>

<jar>
...
<manifest>
<attribute name="Main−Class" value="com.mycompany.TestMain"/>
<attribute name="Class−Path" value=". ${lib.list}"/>
</manifest>
...
</jar>

4.45 Detect the browser/JVM type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0160.html

One way is to instanciate a known browser−specific method and catch the Exception if not found

import java.applet.*;

public class BrowserDetector extends Applet {


public void init() {
if ( isNetscape() )
System.out.println("This browser is a Netscape Browser.");
if ( isMicrosoft() )
System.out.println("This browser is a Microsoft Browser.");
}

public static boolean isNetscape() {


try {
Class.forName("netscape.applet.MozillaAppletContext");
}
catch (ClassNotFoundException e) {
System.out.println("This browser is not a Netscape Browser.");
return false;
}

4.45 Detect the browser/JVM type


return true;
}

public static boolean isMicrosoft() {


try {
Class.forName("com.ms.applet.GenericAppletContext");
}
catch (ClassNotFoundException e) {
System.out.println("This browser is not a Microsoft Browser.");
return false;
}
return true;
}
}

Or by examining the string representation of the getAppletContext() method

String theBrowser = "APPLICATION";


String appletContext = getAppletContext().toString();
if (appletContext.startsWith("sun.applet.AppletViewer"))
theBrowser = "APPLETVIEWER";
else if (appletContext.startsWith("netscape.applet."))
theBrowser = "NETSCAPE";
else if (appletContext.startsWith("com.ms.applet."))
theBrowser = "MICROSOFT";
else if (appletContext.startsWith("sunw.hotjava.tags.TagAppletPanel"))
theBrowser = "HOTJAVA";
else if (appletContext.startsWith( "sun.plugin.navig.win32.AppletPlugin"))
theBrowser = "NETSCAPEPLUGIN";
else if (appletContext.startsWith( "sun.plugin.ocx.ActiveXApplet"))
theBrowser = "MICROSOFTPLUGIN;
else if (appletContext.startsWith
( "sun.plugin.viewer.context.IExplorerAppletContext")
theBrowser = "MICROSOFTPLUGINJRE1.4;

For an application, by looking at the string representation of the getDefaultToolkit() method, we


detect the JVM type

String theJVM = "";


String toolkit = Toolkit.getDefaultToolkit().toString();

if (theBrowser.equals("APPLICATION") {
if (toolkit.startsWith( "sun.awt.windows.WToolkit"))
theJVM = "JAVA";
else if (toolkit.startsWith( "com.ms.awt.WToolkit"))
theJVM = "JVIEW";
}

For example, our MyApplet.class exists in three versions. One is using Microsoft−specific classes,
the other is a JDK1.1 applet and finally a version for JDK102−only browser. The idea is to put all the
required classes in an ARCHIVE file. By using a javascript entities, we decide which archive to use.
During layout time, the javascript entity is remplaced by the right archive name.

<HTML></HTML><HEAD>
<SCRIPT>
function isBrowser(b,v) {
browserOk = false;
versionOk = false;
browserOk = (navigator.appName.indexOf(b) != −1);
versionOk = (v <= parseInt(navigator.appVersion));
return browserOk &versionOk;

4.45 Detect the browser/JVM type


}

archiveToBeUsed = "java102.jar";

if (isBrowser("Microsoft", 4)) {
archiveToBeUsed = "ie4.jar";
}
else {
if isBrowser("Netscape", 4) {
archiveToBeUsed = "n4.jar";
}
}

</SCRIPT></HEAD><BODY>
<APPLET CODE ="MyApplet.class"
HEIGHT=100
WIDTH=400
ARCHIVE=}; >
</APPLET>
</BODY></HTML>

NOTE: You may need to use the document.write() method to generate the right APPLET tag instead of a the Javascript entity to be compatible
with Netscape and IE.

4.46 Detect if Java is enabled from HTML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0161.html

For a Javascript solution, check this How−to

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="MyApplet.class"
NAME="myApplet"
HEIGHT=400 WIDTH=400 ALT="Oups! You don't have JAVA enabled">
<A HREF="nojava.html">Oups! You don't have JAVA enabled, click here.</A>
</APPLET>
</BODY></HTML>

4.47 See the Java Console Window Log (Java plugin)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0533.html

The Java Console Window Log is also stored on disk. On the Windows plateform, it's in the folder :

C:\Documents and Settings\


<username>\
Application Data\
Sun\
Java\
Deployment\
log

It's a file with the extension .trace

4.46 Detect if Java is enabled from HTML


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

4.46 Detect if Java is enabled from HTML


5 Internationalization
5.1 java−inter

5.2 Load resources based upon client environment at startup


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0133.html

There are two ways to include resources based on the current Locale. One way is to use Properties
files and the other are classes extending the ListResourceBundle base class. You need to follow a
naming standard so that the JVM retrieves the right resources bundle.

Note that if a resource is missing for the current locale then the default definition is used.

[International.java (main program)]

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;

public class International extends JFrame


implements ActionListener
{
JLabel aLabel;
JLabel vLabel;
JCheckBox aCheckbox;
JButton aButton;
JButton vButton;
JTextField aTextField;
NumberFormat nf;

public void initGUI(){


setLayout(new FlowLayout());

// String
aLabel = new JLabel
(MyResources.rb.getString("aLabel"));
add(aLabel);

// Object
aCheckbox =
(JCheckBox)MyResources.rb.getObject("aCheckbox");
add(aCheckbox);

// String concatenation with MessageFormat


Date d = new Date();
MessageFormat mf = new MessageFormat
(MyResources.rb.getString("aButton"));
aButton = new JButton
(mf.format(new Object [] { d }));
add(aButton);

5 Internationalization
// Number format output
double dn = 3.1416;
nf = (NumberFormat)
(MyResources.rb.getObject("aNumber"));
aTextField = new JTextField(6);
add(aTextField);
aTextField.setText(nf.format(dn));

// Number input validation


vButton =
(JButton)MyResources.rb.getObject("vButton");
add(vButton);
vButton.addActionListener(this);

vLabel = new JLabel("validation message ...");


add(vLabel);

setSize(400,400);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == vButton) {
try {
nf.parse(aTextField.getText());
vLabel.setText(MyResources.rb.getString("numOK"));
vLabel.invalidate();
this.validate();
}
catch (ParseException pe) {
pe.printStackTrace();
vLabel.setText(MyResources.rb.getString("numERR"));
vLabel.invalidate();
this.validate();
}
}
}

public static void main(String args[]) {


System.out.println("Current Local : " + Locale.getDefault());
Thread t = new Thread () {
public void run() {
International frame = new International();
frame.initGUI();
frame.setVisible(true);
}
};

SwingUtilities.invokeLater(t);
}
}

[MyResources.java (default resources)]

import java.util.*;
import javax.swing.*;
import java.text.*;

public class MyResources extends ListResourceBundle {


public static ResourceBundle rb =
ResourceBundle.getBundle("MyResources");

public Object [][] getContents() {


return contents;

5 Internationalization
}

static final Object[][] contents = {


{ "myLabel" , "A Label" } ,
{ "aCheckbox", new JCheckBox("Yes") } ,
{ "aButton" , "Today {0,date,long}"},
{ "aNumber" , new DecimalFormat("0.####")},
{ "vButton" , new JButton("Validate number")},
{ "numOK" , "Valid!" },
{ "numERR" , "Invalid"}
};
}

[MyResources_en.java (english language resources)]


The classname format is [name][language ID][country code].java.
You can retrieve a list of language IDs and country codes at the Unicode organization Web site

import java.util.*;

public class MyResources_en extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}
static final Object[][] contents = {
{ "aLabel" , "a Label (en)" }
};
}

[MyResources_fr.java (french language resources)]

import java.util.*;
import javax.swing.*;

public class MyResources_fr extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "aLabel" , "une étiquette (fr)" } ,
{ "aCheckbox", new JCheckBox("Oui (fr)")} ,
{ "vButton" , new JButton("Validation du nombre")},
{ "numOK" , "Valide!"},
{ "numERR", "Invalide"}
};
}

[MyResources_fr_CA.java (french language (for Canada) resources)]

import java.util.*;

public class myResources_fr_CA extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "aLabel" , "une étiquette (fr CA)" } ,
};
}

5 Internationalization
This example uses ListResourceBundle classes to store the required resources. It is possible to
substitute them for Properties files without any change to the code. The properties files must have
the .properties extension.

See this How−to.

5.3 Load resources dynamically


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0134.html

This HowTo lets you select a language and change its GUI to reflect the choice.

We are using a special class, a ListResourceBundle, to store our resources. We have a class per
Locale. If a specific resource is not in a specific Locale ListResourceBundle then the default
resource is used.

To use a properties file instead of a class to store resources then look at this HowTo.

[InternationalDynamic.java (main program)]

import java.util.*;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class InternationalDynamic extends JFrame


implements ActionListener
{

static Locale[] localesSupported = {


Locale.US, Locale.FRANCE, Locale.GERMANY
};

int localeChoosen = 0;
Locale localeCurrent;
ResourceBundle rb;

ButtonGroup bg;
JButton btnQuit;
JRadioButton r0, r1, r2;
JLabel today;
boolean defaultDone = false;

public void initLocale(){


localeCurrent = localesSupported[localeChoosen];
this.setLocale(localeCurrent);
rb = ResourceBundle.getBundle("ResourcesDynamic", localeCurrent);
}

public void initText() {


setTitle (rb.getString("title"));
r0.setText(rb.getString("r0"));
r1.setText(rb.getString("r1"));
r2.setText(rb.getString("r2"));
btnQuit.setText(rb.getString("btnQuit"));

5.3 Load resources dynamically


Date d = new Date();
MessageFormat mf = new MessageFormat
(rb.getString("today"), localeCurrent);
today.setText(mf.format(new Object [] { d }));
}

public void initGUI(){


setLayout(new FlowLayout());

// RADIO buttons
bg = new ButtonGroup();
r0 = new JRadioButton();
r1 = new JRadioButton();
r2 = new JRadioButton();
bg.add(r0);
bg.add(r1);
bg.add(r2);
add(r0);
add(r1);
add(r2);

// default RADIO button


if (!defaultDone) {
String rDef = rb.getString("rDefault");
if (rDef.equals("r0"))
r0.setSelected(true);
else if (rDef.equals("r1"))
r1.setSelected(true);
else
r2.setSelected(true);
defaultDone = true;
}
else {
if (localeChoosen == 0)
r0.setSelected(true);
else if (localeChoosen == 1)
r1.setSelected(true);
else
r2.setSelected(true);
}

// QUIT button
btnQuit = new JButton();
add(btnQuit);

// today label
today = new JLabel();
add(today);

//
r0.addActionListener(this);
r1.addActionListener(this);
r2.addActionListener(this);
btnQuit.addActionListener(this);

setSize(400,100);
setVisible(true);
}

public void actionPerformed(ActionEvent ae){


if (ae.getSource() == btnQuit) {
System.exit(0);
}

5.3 Load resources dynamically


else if (ae.getSource() == r0) localeChoosen = 0;
else if (ae.getSource() == r1) localeChoosen = 1;
else if (ae.getSource() == r2) localeChoosen = 2;
initLocale();
initText();
pack();
}

public static void main(String args[]) {


System.out.println("Current Locale : " + Locale.getDefault());
Thread t = new Thread () {
public void run() {
InternationalDynamic i = new InternationalDynamic();
i.initLocale();
i.initGUI();
i.initText();
i.pack();
}
};
SwingUtilities.invokeLater(t);
}
}

[ResourcesDynamic.java (default resources)]

import java.util.*;

public class ResourcesDynamic extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "title", "Example" },
{ "r0" , "United States" } ,
{ "r1", "France" } ,
{ "r2" , "Germany"},
{ "rDefault" , "r0" },
{ "btnQuit" , "Quit"},
{ "today" , " (def) {0,date,long}"},
};
}

[ResourcesDynamic_en.java (english language resources)]

import java.util.*;

public class ResourcesDynamic_en extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "title", "Example" },
{ "r0" , "United States" } ,
{ "r1", "France" } ,
{ "r2" , "Germany"},
{ "rDefault" , "r0" },
{ "btnQuit" , "Quit"},
{ "today" , " (en) {0,date,long}"},
};
}

5.3 Load resources dynamically


[ResourcesDynamic_fr.java (french language resources)]

import java.util.*;

public class ResourcesDynamic_fr extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}

static final Object[][] contents = {


{ "title", "Exemple" },
{ "r0" , "Etats−Unis" } ,
{ "r1", "France" } ,
{ "r2", "Allemagne" },
{ "rDefault", "r1" },
{ "btnQuit", "Quitter" },
{ "today" , " (fr) {0,date, dd/MM/yyyy}"},
};
}

[ResourcesDynamic_de.java (german language resources)]

import java.util.*;

public class ResourcesDynamic_de extends ListResourceBundle {


public Object [][] getContents() {
return contents;
}
static final Object[][] contents = {
{ "title", "Beispiel" },
{ "r0" , "Vereinigte Staaten" } ,
{ "r1", "Frankreich" } ,
{ "r2", "Deutschland" },
{ "rDefault", "r2" },
{ "btnQuit", "verlassen"},
{ "today" , " (de) {0,date,dd.MM.yyyy}"},
};
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

5.4 Load resources via a resources file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0135.html

With the previous JAVA How−to, the resources were stored in classes. The drawback is when there
is a modification, we must recompile the class. With a resources file, we simply add or modify the
resource in a special file with a regular text editor. The JDK provides a class,
PropertyResourceBundle, to use properties file very easily. In fact, from the programmer's point of
view, there is no difference if the resources are stored in classes or properties files.

The ResourceBundle will look first for classes and if not found, it will look for properties files. We
don't have to specify filenames, the ResourceBundle will construct the filename using the same

5.4 Load resources via a resources file


mechanism used for classes. The file must have the extension .properties.

The ResourceBundle try to load the properties file from the current classpath.

If the properties are stored in subdirectory , use "." instead of "/".

For example, let's say that the properties file is in a subdirectory called "subdir" (from the current
directory). Then you can load the ResourcesDynamic resources file with

ResourceBundle.getBundle("subdir.ResourcesDynamic", localeCurrent);

[InternationalDynamic.java]

import java.util.*;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class InternationalDynamic extends JFrame


implements ActionListener
{

static Locale[] localesSupported = {


Locale.US, Locale.FRANCE, Locale.GERMANY
};

int localeChoosen = 0;
Locale localeCurrent;
ResourceBundle rb;

ButtonGroup bg;
JButton btnQuit;
JRadioButton r0, r1, r2;
JLabel today;
boolean defaultDone = false;

public void initLocale(){


localeCurrent = localesSupported[localeChoosen];
this.setLocale(localeCurrent);
rb = ResourceBundle.getBundle("res.ResourcesDynamic", localeCurrent);
}

public void initText() {


setTitle (rb.getString("title"));
r0.setText(rb.getString("r0"));
r1.setText(rb.getString("r1"));
r2.setText(rb.getString("r2"));
btnQuit.setText(rb.getString("btnQuit"));
Date d = new Date();
MessageFormat mf = new MessageFormat
(rb.getString("today"), localeCurrent);
today.setText(mf.format(new Object [] { d }));
}

public void initGUI(){


setLayout(new FlowLayout());

// RADIO buttons
bg = new ButtonGroup();

5.4 Load resources via a resources file


r0 = new JRadioButton();
r1 = new JRadioButton();
r2 = new JRadioButton();
bg.add(r0);
bg.add(r1);
bg.add(r2);
add(r0);
add(r1);
add(r2);

// default RADIO button


if (!defaultDone) {
String rDef = rb.getString("rDefault");
if (rDef.equals("r0"))
r0.setSelected(true);
else if (rDef.equals("r1"))
r1.setSelected(true);
else
r2.setSelected(true);
defaultDone = true;
}
else {
if (localeChoosen == 0)
r0.setSelected(true);
else if (localeChoosen == 1)
r1.setSelected(true);
else
r2.setSelected(true);
}

// QUIT button
btnQuit = new JButton();
add(btnQuit);

// today label
today = new JLabel();
add(today);

//
r0.addActionListener(this);
r1.addActionListener(this);
r2.addActionListener(this);
btnQuit.addActionListener(this);

setSize(400,100);
setVisible(true);
}

public void actionPerformed(ActionEvent ae){


if (ae.getSource() == btnQuit) {
System.exit(0);
}
else if (ae.getSource() == r0) localeChoosen = 0;
else if (ae.getSource() == r1) localeChoosen = 1;
else if (ae.getSource() == r2) localeChoosen = 2;
initLocale();
initText();
pack();
}

public static void main(String args[]) {


System.out.println("Current Locale : " + Locale.getDefault());

5.4 Load resources via a resources file


Thread t = new Thread () {
public void run() {
InternationalDynamic i = new InternationalDynamic();
i.initLocale();
i.initGUI();
i.initText();
i.pack();
}
};
SwingUtilities.invokeLater(t);
}
}

[RresourcesDynamic.properties]

title=Example
r0=United States
r1=France
r2=Germany
rDefault=r0
btnQuit=Quit
today=(def) {0,date,long}

[RresourcesDynamic_en.properties]

title=Example
r0=United States
r1=France
r2=Germany
rDefault=r0
btnQuit=Quit
today=(en) {0,date,long}

[ResourcesDynamic_fr.properties]

title=Exemple
r0=Etats−Unis
r1=France
r2=Allemagne
rDefault=r1
btnQuit=Quitte
today=(fr) {0,date, dd/MM/yyyy}

[ResourcesDynamic_de.properties]

title=Beispiel
r0=Vereinigte Staaten
r1=Frankreich
r2=Deutschland
rDefault=r2
btnQuit=Verlassen
today=(de) {0,date,dd.MM.yyyy}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

5.4 Load resources via a resources file


5.5 Display "special character" using Unicode
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0136.html

The copyright symbol © :

String COPYRIGHT = "\u00a9"";

The registered symbol ® :

String REGISTERED = "\u00ae";

The euro−currency sign € :

String EURO = "\u20ac"

For example :

import java.awt.*;
public class TestUnicode extends java.applet.Applet {

public static final String COPYRIGHT = "\u00a9";


public static final String REGISTERED = "\u00ae";
public static final String EURO = "\u20ac";

public void init () {


setLayout(new FlowLayout());
Label a = new Label(COPYRIGHT + " R\u00e9al Gagnon");
Label b = new Label(REGISTERED + " R\u00e9al's Software "
+ " price : 100 " + EURO);
add(a);
add(b);
}
}

Output :
Java not enabled!

A list of Unicode characters is available at the Unicode organization Web site.

Here a quick list for accentued letters :

á \u00e0 Á \u00c0
à \u00e1 À \u00c1
â \u00e2 Â \u00c2
é \u00e9 É \u00c9
è \u00e8 È \u00c8
ê \u00ea Ê \u00ca
î \u00ee Î \u00ce
ç \u00e7 Ç \u00c7

5.5 Display "special character" using Unicode


5.6 Display chinese/japanese characters
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0137.html

A useful link to integrate international characters set in Netscape is


http://developer.netscape.com/software/jdk/i18n.html and check also
http://www.geocities.com/Tokyo/Pagoda/1675/ for a more complete overview.

5.7 Localize a JOptionPane dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0138.html

This example will show 2 radio buttons, one for english messages and buttons and the other one for
french. Press the button to display a localized JOptionPane according to the radio button selected.

Create 2 properties files, one for english , one for french.

[JOptionPane_en.properties]
Yes=Yes
No=No
Cancel=Cancel
SaveMsg=Do you want to save your data

[JOptionPane_fr.properties]
Yes=Oui
No=Non
Cancel=Annuler
SaveMsg=Voulez−vous sauvegarder vos donnees

Then

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class MessageBoxExample extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;
String msg ;

public MessageBoxExample() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

5.6 Display chinese/japanese characters


button = new JRadioButton("Francais");
button.setActionCommand("fr");
button.addActionListener(this);
group.add(button);
add(button);

go = new JButton("Do it");


go.addActionListener(this);
add(go);

locale = Locale.US;
}

public void setUILanguage() {


ResourceBundle rb;
rb = ResourceBundle.getBundle("JOptionPane", locale);

UIManager.put("OptionPane.yesButtonText", rb.getString("Yes"));
UIManager.put("OptionPane.noButtonText", rb.getString("No"));
UIManager.put("OptionPane.cancelButtonText", rb.getString("Cancel"));
msg = rb.getString("SaveMsg");
}

public void actionPerformed(ActionEvent e) {


int result;

if (e.getSource() instanceof JRadioButton) {


if (e.getActionCommand().equals("en"))
locale = Locale.US;
else
locale = Locale.FRANCE;
setUILanguage();
}
else {
// the button action
result = JOptionPane.showConfirmDialog(this,msg);
System.out.println(result);
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
MessageBoxExample panel = new MessageBoxExample();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

5.6 Display chinese/japanese characters


5.8 Validate/Convert a number using the current Locale()
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0139.html

Depending on the International setting, numbers with comma as decimal separator may be
permitted. The NumberFormat class can handle this based on the current Locale().

NumberFormat nf = NumberFormat.getInstance();
Number n = nf.parse(((TextField)theComponent).getText());
BigDecimal aDecimal = new BigDecimal(n.doubleValue());

5.9 Localize a JFileChooser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0299.html

Modern Swing release have now built−in ready−to−use translations for the JFileChooser. The
language is choosen based on the current Locale. So you don't have to do anything to display the
JFileChooser in the right language.

The user interface elements provided by the J2SE Runtime Environment 5.0, include Swing dialogs,
messages written by the runtime environment to the standard output and standard error streams, as
well as messages produced by the tools provided with the JRE. These user interface elements are
localized into the following languages:

Sun Supported Locales

This example will show 2 radio buttons, one for english, one for french. Press the button to display a
localized JFileChooser according to the radio button selected.

Create 2 properties files, one for english , one for french (these files are incomplete but should be
enough to get you started).

[JFileChooser_en.properties]

Title=Real's JFileChooser
lookInLabelText=Current
filesOfTypeLabelText=File type
upFolderToolTipText=go up

[JFileChooser_fr.properties]

Title=JFileChooser de R\u00e9al
lookInLabelText=Courant
filesOfTypeLabelText=Type de fichier
upFolderToolTipText=Remonte

Then

[LocalizeJFileChooser.java]

5.8 Validate/Convert a number using the current Locale()


import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class LocalizeJFileChooser extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;
String msg ;

protected JFileChooser z_chooser;


String z_choosertitle;

public LocalizeJFileChooser() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

button = new JRadioButton("Francais");


button.setActionCommand("fr");
button.addActionListener(this);
group.add(button);
add(button);

go = new JButton("Do it");


go.addActionListener(this);
add(go);

locale = Locale.US;

public void setUILanguage() {


ResourceBundle rb;
rb = ResourceBundle.getBundle("JFileChooser", locale);

z_choosertitle = rb.getString("Title");

UIManager.put
("FileChooser.lookInLabelText",
rb.getString("lookInLabelText"));
UIManager.put
("FileChooser.filesOfTypeLabelText",
rb.getString("filesOfTypeLabelText"));
UIManager.put
("FileChooser.upFolderToolTipText",
rb.getString("upFolderToolTipText"));
/*
do the same with :
FileChooser.fileNameLabelText
FileChooser.homeFolderToolTipText
FileChooser.newFolderToolTipText
FileChooser.listViewButtonToolTipTextlist
FileChooser.detailsViewButtonToolTipText

5.8 Validate/Convert a number using the current Locale()


FileChooser.saveButtonText=Save
FileChooser.openButtonText=Open
FileChooser.cancelButtonText=Cancel
FileChooser.updateButtonText=Update
FileChooser.helpButtonText=Help
FileChooser.saveButtonToolTipText=Save
FileChooser.openButtonToolTipText=Open
FileChooser.cancelButtonToolTipText=Cancel
FileChooser.updateButtonToolTipText=Update
FileChooser.helpButtonToolTipText=Help

Almost all Swing widgets can be customize this way. You can
examine the Swing sources to get these values or check
http://www.gargoylesoftware.com/papers/plafdiff.html for
a list of them.

*/

public void actionPerformed(ActionEvent e) {


int result;

if (e.getSource() instanceof JRadioButton) {


if (e.getActionCommand().equals("en"))
locale = Locale.US;
else
locale = Locale.FRANCE;
setUILanguage();
}
else {
z_chooser = new JFileChooser();
z_chooser.setCurrentDirectory(new java.io.File("."));
z_chooser.setDialogTitle(z_choosertitle);
if (z_chooser.showOpenDialog(this) !=
JFileChooser.APPROVE_OPTION)
return;
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
LocalizeJFileChooser panel = new LocalizeJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

5.8 Validate/Convert a number using the current Locale()


5.10 Disable localization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0418.html

By default, the JVM uses the current locale as defined by the OS. To bypass this configuration, you
specify on the command line the locale to be used :

java −Duser.language=en −Duser.region=US MyApplication

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

5.11 Generate the Javadoc "en français"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0437.html

The javadoc utility uses the regular Java mechanism to internationalize its output. The tools.jar in
the lib directory contains the resource bundle standard.properties used by Javadoc to generated the
labels. To add a new language, you need to create the appropriate resource bundle, in our case for
french, we need a file called standard_fr.properties.

The new file must be in the package com.sun.tools.doclets.standard.resources.

Extract from tools.jar, the standard.properties files (keep the directory structure). Copy it under the
name standard_fr.properties. Translate it (or you can download my "incomplete" version here).

[standard.properties (extract)]

doclet.Window_Split_Index={0}\: {1}−Index
doclet.Packages=Packages
doclet.SerialData=Serial Data\:
doclet.Since=Since\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Subinterfaces of {0} in {1}
doclet.Frame_Version=Frame version
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)

[standard_fr.properties (extract)]

doclet.Window_Split_Index={0}\: {1}−Index
doclet.Packages=Paquetages
doclet.SerialData=Donn\u00E9e s\u00E9rialis\u00E9e\:
doclet.Since=Depuis\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Sous−interfaces de {0} dans {1}
doclet.Frame_Version=Version avec cadres
doclet.Generated_Docs_Untitled=Documentation g\u00E9n\u00E9r\u00E9e

Once everything translated, put your standard_fr.properties into the tools.jar making sure that the
file is located in the right package (along standard.properties in

5.10 Disable localization


com.sun.tools.doclets.standard.resources).

To generate in french, use the −locale switch on the command line

javadoc −locale fr ....

NOTE : Make sure the −locale switch is the first one.

Using Ant,

<javadoc
locale="fr"
sourcefiles="c:/client/Client.java"
destdir="javadoc/Client"
author="true"
version="true"
use="true"
private="true"
windowtitle="Client">
<doctitle><![CDATA[<h1>Client</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright &#169; 2003 Real's Howto.</i>]]></bottom>
</javadoc>

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

5.12 Sort a String array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0343.html

Sort utilities are now part of latest JDK versions.

Case sensitive

java.util.Arrays.sort(myArray);

Case insensitive

java.util.Arrays.sort(myArray, String.CASE_INSENSITIVE_ORDER);

Sort with international characters.

Take the following example :

import java.util.*;
import java.io.*;

public class TestSort1 {

String [] words = { "Réal", "Real", "Raoul", "Rico" };

public static void main(String args[]) {

5.12 Sort a String array


new TestSort1().doit();
}

public void doit() {


try {
// to be able output french character at the console
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
//
w.write("Before :\n");
for(int i=0; i < 4 ; i++) {
w.write(words[i] + " ");
}

java.util.Arrays.sort(words);

w.write("\nAfter :\n");
for(int i=0; i < 4 ; i++) {
w.write(words[i] + " ");
}
w.write("\n");
w.flush();
w.close();
}
catch(Exception e){}
}
}

The output is :

Before :
Réal Real Raoul Rico
After :
Raoul Real Rico RéaAl

which is wrong since we expect to find "Réal" after "Real". To solve the problem , replace

java.util.arrays.sort(words);

by

java.util.arrays.sort(words, java.text.collator.getInstance(Locale.FRENCH));

and the output will be :

Before :
Réal Real Raoul Rico
After :
Raoul Real Réal Rico

Or you can do it the long way :

...
Locale loc = Locale.FRENCH;
sortArray(Collator.getInstance(loc), words);
...

public static void sortArray(Collator collator, String[] strArray) {


String tmp;

5.12 Sort a String array


if (strArray.length == 1) return;
for (int i = 0; i < strArray.length; i++) {
for (int j = i + 1; j < strArray.length; j++) {
if( collator.compare(strArray[i], strArray[j] ) > 0 ) {
tmp = strArray[i];
strArray[i] = strArray[j];
strArray[j] = tmp;
}
}
}
}

5.13 Accentuated characters in Properties/ResourceBundle file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0492.html

The rules are

• Only use ISO Latin 1 characters in the Properties/ResourceBundle files


• For other characters use the \u.... notation
• To avoid having to type all the \u... notation manually, use the native2ascii tool (included with
the SDK).

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

5.14 Compare accentuated letters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0496.html

class Test {
public static void main(String args[]) {

String s1 = "état";
String s2 = "famille";

// (javadoc)
// The result of String.compareTo() is a negative integer
// if this String object lexicographically precedes the
// argument string. The result is a positive integer if
// this String object lexicographically follows the argument
// string. The result is zero if the strings are equal;
// compareTo returns 0 exactly when the equals(Object)
// method would return true.

// here we are expecting "é" < "f"


if (s1.compareTo(s2) > 0) {
// s1 lexicographically follows s2 which is not true!
System.out.println("not ok s1 > s2 ");
}

5.13 Accentuated characters in Properties/ResourceBundle file


// (javadoc)
// Collator.compare() compares the source string to the target string
// according to the collation rules for this Collator.
// Returns an integer less than, equal to or greater than zero
// depending on whether the source String is less than,
// equal to or greater than the target string.
java.text.Collator frCollator =
java.text.Collator.getInstance(java.util.Locale.FRANCE);
frCollator.setStrength(java.text.Collator.CANONICAL_DECOMPOSITION);
// or frCollator.setStrength(java.text.Collator.SECONDARY);
// to be non case sensitive
if (frCollator.compare(s1, s2) < 0) {
// s2 lexicographically follows s1
System.out.println("ok s1 < s2 ");
}
}
}

Equality

class Test {
public static void main(String args[]) {

String s1 = "état";
String s2 = "État";

// here we are expecting "état" == "État"


if (s1.compareTo(s2) != 0) {
System.out.println("not ok s1 != s2 ");
}

java.text.Collator frCollator =
java.text.Collator.getInstance(java.util.Locale.FRANCE);
frCollator.setStrength(java.text.Collator.SECONDARY);
if (frCollator.compare(s1, s2) == 0) {
// s2 lexicographically follows s1
System.out.println("ok s1 == s2 ");
}
}
}

NOTE: Also, another possibility is to convert to uppercase/lowercase both items to be compared.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

5.15 Unaccent letters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0456.html

The following snippet removes from a String accentued letters and replace them by their regular
ASCII equivalent.

This can be useful before inserting data into a database to made sorting easier.

5.15 Unaccent letters


Technique 1
It's a simple using the sun.text.Normalizer class. However, since the class is in sun.* package, it is
considered outside of the Java platform, can be different across OS platforms (Solaris, Windows,
Linux, Macintosh, etc.) and can change at any time without notice with SDK versions (1.2, 1.2.1,
1.2.3, etc). In general, writing java programs that rely on sun.* is risky: they are not portable, and
are not supported.

For an alternative to the sun.text.Normalizer class, you may to take a look at IBM's ICU4J project on SourceForge.

We are calling the normalize() with the option DECOMP (for decomposition, see Unicode
Normalization). So if we pass à, the method returns a + ` . Then using a regular expression, we
clean up the string to keep only valid US−ASCII characters.

JDK1.4

import sun.text.Normalizer;

public class Accent {


public static String value = "é à î _ @";

public static void main(String args[]) throws Exception{


System.out.println(formatString(value));
// output : e a i _ @
}

public static String formatString(String s) {


String temp = Normalizer.normalize(s, Normalizer.DECOMP, 0);
return temp.replaceAll("[^\\p{ASCII}]","");
}

A note from ajmacher:

The Normalizer API changed in JDK6... it can now be found in java.text.Normalizer and its usage is
slightly different (but enough to break it), so Technique 1 will cause compiler errors in JDK6. Try :

java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFD);

Technique 2
As an alternative, replaceAll() and regular expressions on a String can also be used :

public class Test {


public static void main(String args[]) {
String s = "È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô";

s = s.replaceAll("[èéêë]","e");
s = s.replaceAll("[ûù]","u");
s = s.replaceAll("[ïî]","i");
s = s.replaceAll("[àâ]","a");
s = s.replaceAll("Ô","o");

s = s.replaceAll("[ÈÉÊË]","E");
s = s.replaceAll("[ÛÙ]","U");
s = s.replaceAll("[ÏÎ]","I");
s = s.replaceAll("[ÀÂ]","A");
s = s.replaceAll("Ô","O");

5.15 Unaccent letters


System.out.println(s);
// output : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o
}
}

Technique 3
While the two techniques above are ok... there are a little bit slow.

The following HowTo is faster because we using one String to contain all the possible characters to
be converted and a String with the ASCII equivalent. So we need to detect the position in the first
String and then do a lookup in the second String.

public class AsciiUtils {


private static final String PLAIN_ASCII =
"AaEeIiOoUu" // grave
+ "AaEeIiOoUuYy" // acute
+ "AaEeIiOoUuYy" // circumflex
+ "AaOo" // tilde
+ "AaEeIiOoUuYy" // umlaut
+ "Aa" // ring
+ "Cc" // cedilla
;

private static final String UNICODE =


"\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"
+"\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD"
+"\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177"
+"\u00C3\u00E3\u00D5\u00F5"
+"\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF"
+"\u00C5\u00E5"
+"\u00C7\u00E7"
;

// private constructor, can't be instanciated!


private AsciiUtils() { }

// remove accentued from a string and replace with ascii equivalent


public static String convertNonAscii(String s) {
StringBuffer sb = new StringBuffer();
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
int pos = UNICODE.indexOf(c);
if (pos > −1){
sb.append(PLAIN_ASCII.charAt(pos));
}
else {
sb.append(c);
}
}
return sb.toString();
}

public static void main(String args[]) {


String s =
"The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
System.out.println(AsciiUtils.convertNonAscii(s));
// output :
// The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c
}
}

5.15 Unaccent letters


Thanks to MV Bastos for the "tilde" bug fix!

5.16 Output french characters to the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0046.html

Since Java string are Unicode encoded, you must specified a different encoding when printing to a
DOS console. This is done via the OutputStreamWriter class.

import java.io.*;

public class DosString {


public static void main(String args[]){
String javaString =
"caractères français : à é \u00e9"; // Unicode for "é"
try {
// output to the console
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
w.write(javaString);
w.flush();
w.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

An alternative is to start the JVM and pass on the command line the default file encoding to be
used. Then you will be able to use regular System.out.println().

java −Dfile.encoding=Cp850 MyApp

Alternate technique

import java.io.*;

public class test {


public static void main(String[] args) {
PrintStream ps = null;
String javaString =
"caractères français : à é \u00e9"; // Unicode for "é"

try {
ps = new PrintStream(System.out, true, "Cp850");
}
catch (UnsupportedEncodingException error) {
System.err.println(error);
System.exit(0);
}
ps.println(javaString);
}
}

Note : List of supported encodings here

5.16 Output french characters to the console


5.17 Get the default character set of the JVM
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0505.html

public class Hello {


public static void main(String args[]) throws Exception{
// not crossplateform safe
System.out.println(System.getProperty("file.encoding"));
// jdk1.4
System.out.println(
new java.io.OutputStreamWriter(
new java.io.ByteArrayOutputStream()).getEncoding()
);
// jdk1.5
System.out.println(java.nio.charset.Charset.defaultCharset().name());
}
}

Output example (winXP)

>java Hello
Cp1252
Cp1252
windows−1252

See also java encoding table for the encoding sets supported.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

5.18 Convert OEM (DOS) file to Ansi (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0524.html

We are using an InputStreamReader which convert the specified input encoding to Unicode and an
OutputStreamWriter which from Unicode to the specified output encoding.

This can be useful when migrating data from a legacy database (ex. Clipper, dBase) to newer
DBMS (ex. mySQL, Sybase).

import java.io.*;

public class OemToAnsi {

public static void main(String args[]) throws Exception{


if (args.length != 2) {
System.out.println(
"Usage : java OemToAnsi inputdosfile outputansifile"
);

5.17 Get the default character set of the JVM


System.out.println(
" note : codepage input Cp850 codepage output Cp1252"
);
System.exit(1);
}
// input
FileInputStream fis = new FileInputStream(args[0]);
BufferedReader r =
new BufferedReader(new InputStreamReader(fis, "Cp850"));
// output
FileOutputStream fos = new FileOutputStream(args[1]);
Writer w =
new BufferedWriter(new OutputStreamWriter(fos, "Cp1252"));
String oemString = "";
while ( (oemString= r.readLine()) != null) {
w.write(oemString);
w.flush();
}
w.close();
r.close();
System.exit(0);
}
}

See also this related HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

5.19 Detect non−ASCII character in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0536.html

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharacterCodingException;

public class TestAscii {

public static void main (String args[])


throws Exception {
// this String throws an Exception, it contains an accentued letter
String test = "Réal";
// this String is OK
//String test = "Real";

byte bytearray [] = test.getBytes();


System.out.println("Test string : " + test);

CharsetDecoder d = Charset.forName("US−ASCII").newDecoder();
try {
CharBuffer r = d.decode(ByteBuffer.wrap(bytearray));
r.toString();
}

5.19 Detect non−ASCII character in a String


catch(CharacterCodingException e) {
System.out.println("only regular ASCII characters please!");
// interrupt the processing
throw new Exception(e);
}
System.out.println("Ok, it's ASCII only!");
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

5.19 Detect non−ASCII character in a String


6 IO
6.1 java−io

6.2 Redirect output(stdout/stderr) to a frame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0028.html

[JDK1.1]

import java.awt.*;
import java.awt.event.*;
import java.io.*;

public class RedirectedFrame extends Frame {


TextArea aTextArea = new TextArea();
PrintStream aPrintStream =
new PrintStream(
new FilteredStream(
new ByteArrayOutputStream()));

boolean logFile;

RedirectedFrame(boolean logFile) {
this.logFile = logFile;
System.setOut(aPrintStream);
System.setErr(aPrintStream);
setTitle("Error message");
setSize(500,300);
setLayout(new BorderLayout());
add("Center" , aTextArea);
displayLog();
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
}
);
}

class FilteredStream extends FilterOutputStream {


public FilteredStream(OutputStream aStream) {
super(aStream);
}

public void write(byte b[]) throws IOException {


String aString = new String(b);
aTextArea.append(aString);
}

public void write(byte b[], int off, int len) throws IOException {
String aString = new String(b , off , len);
aTextArea.append(aString);
if (logFile) {

6 IO
FileWriter aWriter = new FileWriter("error.log", true);
aWriter.write(aString);
aWriter.close();
}
}
}

public void displayLog() {


Dimension dim = getToolkit().getScreenSize();
Rectangle abounds = getBounds();
Dimension dd = getSize();
setLocation((dim.width − abounds.width) / 2,
(dim.height − abounds.height) / 2);
setVisible(true);
requestFocus();
}

public static void main(String s[]){


try {
// force an exception for demonstration purpose
Class.forName("unknown").newInstance();
}
catch (Exception e) {
// for applet, always RedirectedFrame(false)
RedirectedFrame r = new RedirectedFrame(true);
e.printStackTrace();
}
}
}

Check also this simple Swing solution.

6.3 Redirect printStackTrace() to a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0029.html

import java.io.*;

public class TestStack2String {


public static void main(String s[]){
try {
// force an exception for demonstration purpose
Class.forName("unknown").newInstance();
// or this could be changed to:
// throw new Exception();

}
catch (Exception e) {
System.out.println(stack2string(e));
}
}

public static String stack2string(Exception e) {


try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return "−−−−−−\r\n" + sw.toString() + "−−−−−−\r\n";
}

6.3 Redirect printStackTrace() to a String


catch(Exception e2) {
return "bad stack2string";
}
}
}

6.4 Output french characters to the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0046.html

Since Java string are Unicode encoded, you must specified a different encoding when printing to a
DOS console. This is done via the OutputStreamWriter class.

import java.io.*;

public class DosString {


public static void main(String args[]){
String javaString =
"caractères français : à é \u00e9"; // Unicode for "é"
try {
// output to the console
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
w.write(javaString);
w.flush();
w.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

An alternative is to start the JVM and pass on the command line the default file encoding to be
used. Then you will be able to use regular System.out.println().

java −Dfile.encoding=Cp850 MyApp

Alternate technique

import java.io.*;

public class test {


public static void main(String[] args) {
PrintStream ps = null;
String javaString =
"caractères français : à é \u00e9"; // Unicode for "é"

try {
ps = new PrintStream(System.out, true, "Cp850");
}
catch (UnsupportedEncodingException error) {
System.err.println(error);
System.exit(0);
}
ps.println(javaString);

6.4 Output french characters to the console


}
}

Note : List of supported encodings here

6.5 Clear the console and control attributes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0047.html

On Win9x, this can be done with the driver ANSI.SYS is loaded via the CONFIG.SYS file.

For example, on Win9x installation, you need something like this in the CONFIG.SYS :

device=c:\windows\command\ansi.sys

Then you send the appropriate escape codes to the console

public class AnsiConsole {


public static void main(String args[]) {
String ANSI_CLS = "\u001b[2J";
String ANSI_HOME = "\u001b[H";
String ANSI_BOLD = "\u001b[1m";
String ANSI_AT55 = "\u001b[10;10H";
String ANSI_REVERSEON = "\u001b[7m";
String ANSI_NORMAL = "\u001b[0m";
String ANSI_WHITEONBLUE = "\u001b[37;44m";

System.out.println(ANSI_CLS);
System.out.println
(ANSI_AT55 + ANSI_REVERSEON + "Hello world" + ANSI_NORMAL);
System.out.println
(ANSI_HOME + ANSI_WHITEONBLUE + "Hello world" + ANSI_NORMAL);
System.out.print
(ANSI_BOLD + "Press a key..." + ANSI_NORMAL);
try {System.in.read();}catch(Exception e){}
System.out.println(ANSI_CLS);
}
}

NOTE: Check this "old" text file to have an overview of ANSI.SYS's Escape Sequences.

NT's CMD.EXE does not support ANSI escape sequences. The Good news is that you can use
COMMAND.COM instead. To use ANSI.SYS, add the following lines in the CONFIG.NT file:

dosonly
device=c:\winnt\system32\ansi.sys

But the bad news is that you are restricted this way to run only DOS−based application so it won't
work for Java stuff!!!

So the only solution left for NT (unless you write some JNI functions, see this HowTo) is to use
brute force.

for (int i=0; i<25; i++)


System.out.println();

6.5 Clear the console and control attributes


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.6 Print text to a printer easily


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0051.html

A quick and simple way to output some text to a printer is to print to OS logical device attached a
printer. For example, on a Windows machine :

import java.io.*;
public class SimplePrinting {
public static void main(String[] args) {
try {
FileWriter out = new FileWriter("lpt1");
out.write("Hello world");
out.write(0x0D); // CR
out.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}

6.7 Print without a Dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0350.html

JobAttributes theJobAttribs = new JobAttributes();


PageAttributes thePageAttribs = new PageAttributes();

theJobAttribs.setDialog(JobAttributes.DialogType.NONE);
theJobAttribs.setPrinter("HP DeskJet 610C"); // the printer to be used
PrintJob myJob = getToolkit().getPrintJob(this, "PrintJob",
theJobAttribs, thePageAttribs);

if (myJob != null) {
Graphics g = myJob.getGraphics();

if (g != null) {
String s = myArea.getText(); // what you like to print
printText(myJob, g, s);
g.dispose();
}
myJob.end();
}

6.6 Print text to a printer easily


6.8 Simple input from the keyboard
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0053.html

First method

import java.io.*;
public class TestReadLine {
public static void main (String args[]) {
StreamTokenizer Input=new StreamTokenizer(System.in);
try {
System.out.print(" Your first name : ");
Input.nextToken();
System.out.println("Hi " + Input.sval + "!");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Second method JDK1.0.2

java.io.DataInputStream in =
new java.io.DataInputStream(System.in);
String aLine = in.readLine();

Third method JDK1.1


In you program, use EasyInput.inputStr("<prompt>") to input a String or
EasyInput.InputInt("<prompt>") for an integer.

public class EasyInput {


public static int inputInt(String s) {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print(s);
int i =0;
try {
i = Integer.parseInt(input.readLine());
}
catch (Exception e) {
e.printStackTrace();
}
return i;
}

public static String inputStr(String s) {


String aLine = "";
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print(s);
try {
aLine = input.readLine();
}
catch (Exception e) {
e.printStackTrace();
}
return aLine;
}

6.8 Simple input from the keyboard


public static void main(String s[]) {
while(true) {
int y = inputInt(" Year: ");
int m = inputInt("Month: ");
int d = inputInt(" Day: ");
String you = inputStr("Your name: ");
System.out.println(you + " " + y + m + d);
}
}
}

NOTE: JDK 1.5 provides the Scanner class to do this, see this HowTo.

6.9 Initialize and write to a serial port


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0062.html

This is for JAVA application only (JDK1.1).

(Win)Initialization is done via the MODE.COM utility. Then to write, simply open a stream using the
OS logical name attached to the serial port. You can use the same technique to print to the printer
port (in this case the local name would be "LPTx:").

public class SerialTest {


public static void main( String args[]) {
Runtime rt = Runtime.getRuntime();
Process p = null;
String portname = "com1:";
// for Win95 : c:\\windows\\command.com
// c:\\windows\\command\\mode.com
String cmd[] = {
"c:\\winnt\\system32\\cmd.exe", "/c",
"start", "/min",
"c:\\winnt\\system32\\mode.com", portname,
"baud=9600", "parity=n", "data=8",
"stop=1",
};
try {
p = rt.exec( cmd );
if( p.waitFor() != 0 ) {
System.out.println("Error executing command: " + cmd );
System.exit( −1 );
}
byte data[] =
"Writing a byte stream out of a serial port.".getBytes();
FileOutputStream fos = new FileOutputStream( portname );
BufferedOutputStream bos = new BufferedOutputStream( fos );
fos.write( data, 0, data.length );
fos.close();
}
catch( Exception e ) {
e.printStackTrace();
}
}
}

6.9 Initialize and write to a serial port


6.10 Redirect to a NULL device
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0453.html

This can be useful if you want to suppress all output.

// Unix style
PrintStream nps = new PrintStream(new FileOutputStream("/dev/null"));
System.setErr(nps);
System.setOut(nps);

//Windows style
PrintStream nps = new PrintStream(new FileOutputStream("NUL:"));
System.setErr(nps);
System.setOut(nps);

//One−liner style : subclass OutputStream to override the write method ...


System.setOut(new java.io.PrintStream(new java.io.OutputStream() {
public void write(int b){}}));

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.11 Get the volume label


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0455.html

This will retrieve the hard disk volume label :

import java.io.*;
import javax.swing.filechooser.*;

public class VolumeLabel {


private VolumeLabel() { }

public static void main(String[] args) {


System.out.println("\"" + get(args[0]) + "\"");
}

public static String get(String path) {


FileSystemView view = FileSystemView.getFileSystemView();
File dir = new File(path);
String name = view.getSystemDisplayName(dir);
if (name == null) { return null; }
name = name.trim();
if (name == null || name.length() < 1) {
return null;
}
int index = name.lastIndexOf(" (");
if (index > 0) {
name = name.substring(0, index);
}

6.10 Redirect to a NULL device


return name;
}
}

The output

Running from c:\temp

>java VolumeLabel c:
"temp"

>java VolumeLabel c:\


"HARDDISK1"

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.12 Easy keyboard input (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0491.html

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches
whitespace. The resulting tokens may then be converted into values of different types using the
various next methods.

import java.util.*;

class TestScanner {
public static void main(String args[]) {
String input = "10:11:12";
Scanner sc = new Scanner(input).useDelimiter(":");
while (sc.hasNextInt()) {
int i = sc.nextInt();
System.out.println(i);
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.13 Open or close a CD/DVD drive


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0574.html

Java provides no way to interact with a cd drive.

One easy way on the Windows plateform is to call a VBS script.

6.12 Easy keyboard input (JDK1.5)


In this HowTo, we are creating a temporary vbs file and execute it. This technique is useful to do
something that a regular Java can't do because it's too specific to OS where the Java is running.
The vbs file is created in the "temporary" folder and is deleted by the JVM at the end.

import java.io.File;
import java.io.FileWriter;

public class CDUtils {


private CDUtils() { }

public static void open(String drive) {


try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);
String vbs = "Set wmp = CreateObject(\"WMPlayer.OCX\") \n"
+ "Set cd = wmp.cdromCollection.getByDriveSpecifier(\""
+ drive + "\") \n"
+ "cd.Eject";
fw.write(vbs);
fw.close();
Runtime.getRuntime().exec("wscript " + file.getPath()).waitFor();
// thanks to TrueJavaProgammer for the waitFor() tip!
// Runtime.getRuntime().exec("wscript " + file.getPath()).waitFor();
// Thread.sleep(2000);
}
catch(Exception e){
e.printStackTrace();
}
}

public static void close(String drive) {


try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new FileWriter(file);
// to close a CD, we need eject two times!
String vbs = "Set wmp = CreateObject(\"WMPlayer.OCX\") \n"
+ "Set cd = wmp.cdromCollection.getByDriveSpecifier(\""
+ drive + "\") \n"
+ "cd.Eject \n "
+ "cd.Eject ";
fw.write(vbs);
fw.close();
Runtime.getRuntime().exec("wscript " + file.getPath()).waitFor();
// thanks to TrueJavaProgammer for the waitFor() tip!
// Runtime.getRuntime().exec("wscript "+ file.getPath());
// Thread.sleep(2000);
}
catch(Exception e){
e.printStackTrace();
}
}

public static void main(String[] args){


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, "Press OK to open CD", "CDUtils",
javax.swing.JOptionPane.DEFAULT_OPTION);
CDUtils.open("D:\\");
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, "Press OK to close CD", "CDUtils",
javax.swing.JOptionPane.DEFAULT_OPTION);

6.12 Easy keyboard input (JDK1.5)


CDUtils.close("D:\\");
}
}

NOTE : Windows Media Player version 7 or later is required

6.14 Get faster console output (System.out.println()


replacement)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0603.html

If your program is doing a lot printing to the console using System.out.println() then it is possible to
get a good performance boost by using an alternative to do the console output.

By default, System.out.print() is only line−buffered and does a lot work related to Unicode handling.
Because of its small buffer size, System.out.println() is not well suited to handle many repetitive
outputs in a batch mode. Each line is flushed right away. If your output is mainly ASCII−based then
by removing the Unicode−related activities, the overall execution time will be better.

Consider this program :

import java.io.BufferedWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

public class Test {


public static void main(String...args) throws Exception {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
System.out.print("abcdefghijk ");
System.out.print(String.valueOf(i));
System.out.print('\n');
}
System.err.println("Loop time: " +
(System.currentTimeMillis() − start));
}
}

The result is

>java Test >NUL


Loop time: 7000

Now, rewrite this program to use a 512−bytes buffer and specify the ASCII as character−encoding
to be used.

import java.io.BufferedWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

public class Test {


public static void main(String...args) throws Exception {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new

6.14 Get faster console output (System.out.println() replacement)


FileOutputStream(java.io.FileDescriptor.out), "ASCII"), 512);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
out.write("abcdefghijk ");
out.write(String.valueOf(i));
out.write('\n');
}
out.flush();
System.err.println("Loop time: " +
(System.currentTimeMillis() − start));
}

The result is

>java Test >NUL


Loop time: 672

Note that your result will vary depending on your machine/java version but the performance gain
should in the same magnitude.

6.15 Execute an external program


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0014.html

Be sure to read this Javaworld article. It describes the various pitfalls related to the Runtime.exec()
method.

6.16 Using Runtime.exec()


This example will capture the output (from stdio) of an external program.

import java.io.*;
public class CmdExec {

public static void main(String argv[]) {


try {
String line;
Process p = Runtime.getRuntime().exec
(System.getenv("windir") +"\\system32\\"+"tree.com /A");
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
}
catch (Exception err) {
err.printStackTrace();
}
}
}

6.15 Execute an external program


6.17 Windows CMD (or BAT) file and retrieve the errorlevel or
exitcode
// win xp
import java.io.*;
public class CmdExec {
public static void main(String argv[]) {
try {
String line;
Process p = Runtime.getRuntime().exec("test.cmd");
p.waitFor();
System.out.println(p.exitValue());
}
catch (Exception err) {
err.printStackTrace();
}
}
}

test.cmd (set the errorlevel manually)

@echo hello world


@exit 42

test.cmd (set the errorlevel 1 (problem detected)

@java −garbage

test.cmd (set the errorlevel 0 (execution Ok)

@java −version

6.18 Launch a Unix script


String[] cmd = {"/bin/sh", "−c", "ls > hello"};
Runtime.getRuntime().exec(cmd);

6.19 Using the ProcessBuilder


Since 1.5, the ProcessBuilder class provides more controls overs the process to be started. It's
possible to set a starting directory.

import java.io.*;
import java.util.*;

public class CmdProcessBuilder {


public static void main(String args[])
throws InterruptedException,IOException
{
List<String> command = new ArrayList<String>();
command.add(System.getenv("windir") +"\\system32\\"+"tree.com");
command.add("/A");

ProcessBuilder builder = new ProcessBuilder(command);


Map<String, String> environ = builder.environment();
builder.directory(new File(System.getenv("temp")));

6.17 Windows CMD (or BAT) file and retrieve the errorlevel or exitcode
System.out.println("Directory : " + System.getenv("temp") );
final Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Program terminated!");
}
}

6.20 Windows rundll32 utility


Windows File association
Any program using the Windows file association mechanism can be started with the rundll32 utility.

// "file" is the filename of the data file


// ex. myresume.doc
// to start Word if the doc extension is associated with it.
Runtime.getRuntime().exec
("rundll32 SHELL32.DLL,ShellExec_RunDLL " + file.getAbsolutePath());

See also this HowTo about the new Desktop API, the recommended solution (but you need
JDK1.6).
See also this one to open the default browser.

The following example start a Dial−up connection on the Win plateform :

[Dialup.java]
public class Dialup {
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime()
.exec("rundll32.exe rnaui.dll,RnaDial MyConnection");
p.waitFor();
System.out.println("Done.");
}
}

The "MyConnection" is the DUN and it's case sensitive.

You still need to press ENTER to CONNECT, there is an option in the Connection properties to
connect automatically.

On NT and W2K, rnaui.dll is not available. Use rasdial.exe instead.

rasdial "connection name"


rasdial "connection name" /d to drop
rasdial /? for more options

6.21 PDF (Windows only)


public class ShowPDF {
public static void main(String[] args) throws Exception {
Process p =
Runtime.getRuntime()

6.20 Windows rundll32 utility


.exec("rundll32 url.dll,FileProtocolHandler c:/pdf/mypdf.pdf");
p.waitFor();
System.out.println("Done.");
}
}

6.22 PDF (Mac only)


public class ShowPDF {
public static void main (String[] args) throws Exception{
Process p = Runtime.getRuntime().exec("open /Documents/mypdf.pdf");
}
}

More runddl32 examples

6.23 Path to executable with spaces in them


You can include a path for the program to be executed. On the Win plateform, you need to put the
path in quotes if the path contains spaces.

public class Test {


public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec(
"\"c:/program files/windows/notepad.exe\"");
p.waitFor();
}
}

If you need to pass arguments, it's safer to a String array especially if they contain spaces.

String[] cmd = { "myProgram.exe", "−o=This is an option" };


Runtime.getRuntime().exec(cmd);

If using the start command and the path of the file to be started contains a space then you must
specified a title to the start command.

String fileName = "c:\\Applications\\My Documents\\test.doc";


String[] commands = {"cmd", "/c", "start", "\"DummyTitle\"",fileName};
Runtime.getRuntime().exec(commands);

6.24 VBSCRIPT
// Win9x
Runtime.getRuntime().exec("start myscript.vbs");

// WinNT
Runtime.getRuntime().exec("cmd /c start myscript.vbs");

or

// with a visible console


Runtime.getRuntime().exec("cscript myscript.vbs");

// with no visible console


Runtime.getRuntime().exec("wscript myscript.vbs");

6.22 PDF (Mac only)


6.25 HTML Help (Windows only)
Runtime.getRuntime().exec("hh.exe myhelpfile.chm");

6.26 Start Excel


import java.io.IOException;

class StartExcel {
public static void main(String args[])
throws IOException
{
Runtime.getRuntime().exec("cmd /c start excel.exe");
}
}

To load a worksheet

import java.io.IOException;

class StartExcel {
public static void main(String args[])
throws IOException
{
String fileName = "c:\\temp\\xls\\test2.xls";
String[] commands = {"cmd", "/c", "start", "\"DummyTitle\"",fileName};
Runtime.getRuntime().exec(commands);
}
}

It's important to pass a dummy title to the Windows start command where there is a possibility that
the filename contains a space. It's a feature.

6.27 Launch the application associated with a file extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0579.html

JDK1.6
The java.awt.Desktop class uses your host operating system's file associations to launch
applications associated with specific file types.

First it's a good idea to check if the Desktop operations are supported on the running plateform.

import java.awt.*;
...

if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
for (Desktop.Action action : Desktop.Action.values()) {
System.out.println("action " + action + " supported? "
+ desktop.isSupported(action));
}
}

6.25 HTML Help (Windows only)


The possible actions are
• BROWSE. launching the user−default browser to show a specified URI
• MAIL. launching the user−default mail client with an optional mailto URI;
• OPEN. launching a registered application to open a specified file.
• EDIT. launching a registered application to edit a specified file.
• PRINT. launching a registered application to print a specified file.

then

// application associated to a file extension


public static void open(File document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.open(document);
}

public static void print(File document) throws IOException {


Desktop dt = Desktop.getDesktop();
dt.print(document);
}

// default browser
public static void browse(URI document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.browse(document);
}

// default mail client


// use the mailto: protocol as the URI
// ex : mailto:elvis@heaven.com?SUBJECT=Love me tender&BODY=love me sweet
public static void mail(URI document) throws IOException {
Desktop dt = Desktop.getDesktop();
dt.mail(document);
}

See the javadoc at http://java.sun.com/javase/6/docs/api/java/awt/Desktop.html

See also this HowTo and this one.

6.28 Launch an application from another application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0394.html

While you can exec("java myaotherapp"), it is more appropriate to instanciate and called the main
method of the other application.

For example, take this simple application :

public class Program2 {


public static void main(String arg[]) {
System.out.println("Hello from Program2");
}
}

To call the above application from another

6.28 Launch an application from another application


public class Program1a {
public static void main(String arg[]) {
System.out.println("Hello from Program1a");
new Thread(){
public void run() {
Program2.main(new String[]{});}
}.start();
}

The above example is used when the class is hard−coded.

The dynamic version is little more tricky.

public class Program1b {


public static void main(String arg[]) {
System.out.println("Hello from Program1b");
new Program1b().execute("Program2");
}

public void execute(String name) {


Class params[] = {String[].class};
// if you need parameters
// String[] args = new String[] { "Hello", "world" };
// Class params[] = new Class[] { args.getClass() });
try {
Class.forName(name).
getDeclaredMethod("main", params).
invoke(null, new Object[] {new String[] {}});
}
catch(Exception e){ e.printStackTrace();}
}
}

Launch many programs using Thread and use join() to wait for the completion.

[Program2.java]
public class Program2 {
public static void main(String arg[]) {
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
}
}

[Program1a.java]
public class Program1a {
public static void main(String arg[]) throws Exception{
System.out.println("Hello from Program1a");
Thread t1 = new Thread(){
public void run() {
Program2.main(new String[]{});}
};
t1.start();
t1.join();
System.out.println("Hello from Program1a");
}
}

6.28 Launch an application from another application


The output :

C:\>java Program1a
Hello from Program1a
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program1a

6.29 Start the default browser from an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0071.html

In this snippet, we initialize a Listbox from a file containing some URLs. When we double click an
item, the default browser is started with the selected HTML page as parameter. This example is
Windows oriented since I have used the start command which supports the file association.

[urlList.txt]

http://www.rgagnon.com/javadetails/java−0001.html|JAVA How−to 1
http://www.rgagnon.com/javadetails/java−0002.html|JAVA How−to 2
http://www.rgagnon.com/javadetails/java−0003.html|JAVA How−to 3
http://www.rgagnon.com/javadetails/java−0004.html|JAVA How−to 4
http://www.rgagnon.com/javadetails/java−0005.htmL|JAVA How−to 5

[StartBrowser.java]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;

public class StartBrowser {


public static void main(String s[]) {
AFrame f = new AFrame();
}
}

class AFrame extends Frame implements ActionListener {


List lbx;
String url[] = new String[50];

public AFrame() {
// dispaly setup
setTitle("URL selection");
setSize(400,400);
lbx = new List();
add(lbx);
initLbx();
// action on listbox double click
lbx.addActionListener(this);
// to close the Frame
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {

6.29 Start the default browser from an application


System.exit(0);
}
}
);
setVisible(true);
}

public void actionPerformed (ActionEvent ae) {


String theUrl = url[lbx.getSelectedIndex()];
// start the default browser (Win95 platform)
// on listbox double click

String cmdLine = "start " + theUrl;


// on NT, you need to start cmd.exe because start is not
// an external command but internal, you need to start the
// command interpreter
// String cmdLine = "cmd.exe /c " + cmdLine;
try {
Process p = Runtime.getRuntime().exec(cmdLine);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void initLbx() {


int i = 0;
try {
String aLine = "";
BufferedReader in
= new BufferedReader(new FileReader("urlList.txt"));
while(null != (aLine = in.readLine())) {
java.util.StringTokenizer st =
new java.util.StringTokenizer(aLine, "|");
url[i++] = st.nextToken();
lbx.addItem(st.nextToken());
// lbx.add(st.nextToken()); in JDK1.2
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}

Another way on Windows platform to start the default browser is ;

Runtime.getRuntime().exec
("rundll32 url.dll,FileProtocolHandler " + theUrl);

You may have difficulty to open a URL ending with .htm. All you need is to replace the last m with
%6D, like

rundll32 url.dll,FileProtocolHandler http://www.rgagnon.com/howto.htm

for

rundll32 url.dll,FileProtocolHandler http://www.rgagnon.com/howto.ht%6D

JDK1.6 has java.awt.Desktop.open(File)

6.29 Start the default browser from an application


See http://java.sun.com/javase/6/docs/api/java/awt/Desktop.html

JDIC provides the equivalent API for 1.4 and later.

See https://jdic.dev.java.net

try {
Desktop.browse(new URL("http://www.rgagnon.com");

}
catch (MalformedURLException e1) {
e1.printStackTrace();
}
catch (DesktopException e2) {
e2.printStackTrace();
}

See also this HowTo.

6.30 Execute a Windows Shortcut (.lnk)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0571.html

A Shortcut is stored in a file with the extension lnk.

// we assume that the .lnk is in the current directory


String currentDir = new File(".").getCanonicalPath();

try {
Runtime.getRuntime().exec
("cmd /c start " + currentDir + "/viewLog.lnk");
}

catch (Exception e){


JOptionPane.showMessageDialog
(null, e.getMessage(),"Oups", JOptionPane.ERROR_MESSAGE);
}

6.31 Create a file association with a Java program


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0592.html

In this example, a file with the extension .xox will be defined and associated with a java program
(display the first 10 lines of selected .xox file).

First the java program to be associated with the .xox file type.

import java.io.*;

public class Head {


static final int MAX_LINES = 10;
public static void main(String args[]) throws Exception{

6.30 Execute a Windows Shortcut (.lnk)


String line = null;
int i = 0 ;
FileInputStream fin = new FileInputStream(args[0]);
BufferedReader myInput = new BufferedReader
(new InputStreamReader(fin));
while ( (line = myInput.readLine()) != null) {
System.out.println(line);
i++;
if (i == MAX_LINES) break;
}
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("*** Press any key...");
input.readLine();
}
}

With Windows, two commands are used to define a file association, assoc and ftype. You need
to execute these commands from an account with Administrator privilege.

To know more about these commands, type assoc /? or ftype /? .

First we define the .xox file type.

The assoc command sets up an association between a file name extension and a file type.

>assoc .xox=Xoxfile
.xox=Xoxfile

Then we specify which program is used to handle the Xoxfile type of file.

The ftype command sets up an association between a file type name, and a string to be used to
execute it.

In this example, we specify the Java JVM to be used, the classpath to load the Head.class plus
the parameter (the selected .xox file).

>ftype Xoxfile=C:\Program Files\Java\jre1.5.0\bin\java −cp c:\dev\work Head %1


Xoxfile=C:\Program Files\Java\jre1.5.0\bin\java −cp c:\dev\work Head %1

Now, if you double−click on a file with .xox extension, a Dos shell is opened, the Head class is
launched with the clicked filename as a parameter and the first 10 line are displayed.

To make the file association works from a command line, you define the environment variable
PATHEXT to include the .xox extension.

>set pathext=.xox;%pathext%
PATHEXT=.XOX;.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH

then you will be able, from a Dos shell, to type only the name of .xox file and the associated
program will be launched with that file as a parameter.

See also this HowTo.

6.30 Execute a Windows Shortcut (.lnk)


6.32 Capture the output from a VBS
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0576.html

This HowTo query the Windows Registry for a specific key. The VBS prints the result and from
Java, we capture this output.

Since we need the output, we must use the VBS interpreter for the console mode
(CSCRIPT.EXE).

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;

public class VBSUtils {


private VBSUtils() { }

public static String readWindowRegistry(String key) {


String result = "";
try {

File file = File.createTempFile("realhowto",".vbs");


file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Dim WSHShell \n"


+ "Set WSHShell = WScript.CreateObject(\"WScript.Shell\") \n"
+ "WScript.Echo _ \n"
+ "WSHShell.RegRead(\"" + key + "\") \n"
+ "Set WSHShell = Nothing \n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

public static void main(String[] args){


//
// DEMO
//
String result = "";
msgBox("Get the path of Acrobat reader from the registry");
result = readWindowRegistry
("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\AcroRd32.exe\\");

6.32 Capture the output from a VBS


msgBox("Acrobat Reader is located in " + result);
}

public static void msgBox(String msg) {


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

6.33 Get a return code from a VBS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0575.html

You can't detect directly if Windows service is running or not in Java.

However, it's easy to do from a VBS. You execute the script from Java, wait for its completion and
capture the return code.

Obviously, this is useful only on the Windows plateform.

import java.io.File;
import java.io.FileWriter;

public class VBSUtils {


private VBSUtils() { }

public static boolean isServiceRunning(String serviceName) {


try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Set sh = CreateObject(\"Shell.Application\") \n"


+ "If sh.IsServiceRunning(\""+ serviceName +"\") Then \n"
+ " wscript.Quit(1) \n"
+ "End If \n"
+ "wscript.Quit(0) \n";
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("wscript " + file.getPath());
p.waitFor();
return (p.exitValue() == 1);
}
catch(Exception e){
e.printStackTrace();
}
return false;
}

public static void main(String[] args){


//
// DEMO
//
String result = "";
msgBox("Check if service 'Themes' is running (should be yes)");
result = isServiceRunning("Themes") ? "" : " NOT ";
msgBox("service 'Themes' is " + result + " running ");

6.33 Get a return code from a VBS


msgBox("Check if service 'foo' is running (should be no)");
result = isServiceRunning("foo") ? "" : " NOT ";
msgBox("service 'foo' is " + result + " running ");
}

public static void msgBox(String msg) {


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

6.34 Execute a CMD file stored in a JAR


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0600.html

In this example, a CMD file is stored a JAR file. The Java code extracts the file as a ressource,
launch a Windows CMD Shell and write the content to the stdin without any temporary file.

In this How−to, the CMD included is used to trigger the default Windows screen saver.

scrnsave.scr /s

import java.io.*;

public class StartScreenSaver {


public static void main(String args[]) throws IOException {
new StartScreenSaver().doit();
}

public void doit() throws IOException{


String line;
OutputStream stdin = null;
InputStream stderr = null;
InputStream stdout = null;

try {
// that our CMD file in our JAR
InputStream is =
getClass().getResource("/screensaver.cmd").openStream();
BufferedReader brCmdLine =
new BufferedReader(new InputStreamReader(is));

// launch CMD and grab stdin/stdout and stderr


Process process = Runtime.getRuntime ().exec ("cmd");
stdin = process.getOutputStream ();
stderr = process.getErrorStream ();
stdout = process.getInputStream ();

// "write" the CMD file into stdin


while ((line = brCmdLine.readLine()) != null) {
line += "\n";
stdin.write(line.getBytes() );
}
stdin.flush();
stdin.close();

// clean up if any output in stdout

6.34 Execute a CMD file stored in a JAR


BufferedReader brCleanUp =
new BufferedReader (new InputStreamReader (stdout));
while ((line = brCleanUp.readLine ()) != null) {
//System.out.println ("[Stdout] " + line);
}
brCleanUp.close();

// clean up if any output in stderr


brCleanUp =
new BufferedReader (new InputStreamReader (stderr));
while ((line = brCleanUp.readLine ()) != null) {
//System.out.println ("[Stderr] " + line);
}
brCleanUp.close();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
stdout.close();
stderr.close();
}
}
}

Get the JAR here.

6.35 Read the content of a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0052.html

This following example is for an application.

On the command line, give the filename to be displayed.

import java.io.*;
public class Cat {
public static void main (String args[]) {
String thisLine;
for (int i=0; i < args.length; i++) {
try {
FileInputStream fin = new FileInputStream(args[i]);
// JDK1.1+
BufferedReader myInput = new BufferedReader
(new InputStreamReader(fin));
while ((thisLine = myInput.readLine()) != null) {
System.out.println(thisLine);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

6.35 Read the content of a file


With an Applet, we can only open file on the same server that the Applet is coming from.

import java.applet.*;
import java.net.*;
import java.io.*;
public class MyApplet extends Applet {
public void init() {
readFile("mydatafile.txt");
}
public void readFile(String f) {
try {
String aLine = "";
URL source = new URL(getCodeBase(), f);
BufferedReader br =
new BufferedReader
(new InputStreamReader(source.openStream()));
while(null != (aLine = br.readLine())) {
System.out.println(aLine);
}
br.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}

The next Applet reads a data file and inserts the data in a Choice component.

import java.applet.*;
import java.awt.*;
import java.net.*;
import java.io.*;

public class ReadDataInChoice extends Applet {


Choice myChoice;

public void init() {


myChoice = new java.awt.Choice();
add(myChoice);
readFile("dataforchoice.txt");
}
public void readFile(String f) {
try {
String anItem = "";
URL source = new URL(getCodeBase(), f);
BufferedReader in =
new BufferedReader(new InputStreamReader(source.openStream()));
while(null != (anItem = in.readLine())) {
myChoice.add(anItem);
}
in.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}

6.35 Read the content of a file


[dataforchoice.txt]

item 1
item 2
item 3
item 4
item 5
ITEM 6

Try it here.

The following method read a data file and return the content as a String. We use a StringBuffer to
optimize string concatenation operations.

private static String readFile(String filename) throws IOException {


String lineSep = System.getProperty("line.separator");
BufferedReader br = new BufferedReader(new FileReader(filename));
String nextLine = "";
StringBuffer sb = new StringBuffer();
while ((nextLine = br.readLine()) != null) {
sb.append(nextLine);
//
// note:
// BufferedReader strips the EOL character
// so we add a new one!
//
sb.append(lineSep);
}
return sb.toString();
}

See this HowTo to read a File which is inside a JAR.

6.36 Read a text file from a jar


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0077.html

import java.io.*;
import java.util.*;

public class FileUtils{

public static List<String> readTextFromJar(String s) {


InputStream is = null;
BufferedReader br = null;
String line;
ArrayList<String> list = new ArrayList<String>();

try {
is = FileUtils.class.getResourceAsStream(s);
br = new BufferedReader(new InputStreamReader(is));
while (null != (line = br.readLine())) {
list.add(line);
}
}
catch (Exception e) {
e.printStackTrace();

6.36 Read a text file from a jar


}
finally {
try {
if (br != null) br.close();
if (is != null) is.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
return list;
}

public static void main(String args[]) throws IOException{


List<String> list = FileUtils.readTextFromJar("/datafile1.txt");
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}

list = FileUtils.readTextFromJar("/test/datafile2.txt");
it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
}

Create 2 datafiles.

datafile1.txt in the same directory as FileUtils.class (in the root) and datafile2.txt in a subdirectory
called test

[datafile1.txt]

datafile1 line 1
datafile1 line 2
datafile1 line 3
datafile1 line 4
datafile1 line 5

[/test/datafile2.txt]

datafile2 line 1
datafile2 line 2
datafile2 line 3
datafile2 line 4
datafile2 line 5

Create the jar with

>"C:\Program Files\Java\jdk1.5.0\bin\jar" −cf MyJar.jar


FileUtils.class datafile.txt test/datafile.txt

Try it :

C> java −cp MyJar.jar FileUtils

The output should be like :

6.36 Read a text file from a jar


datafile1 line 1
datafile1 line 2
datafile1 line 3
datafile1 line 4
datafile1 line 5
datafile2 line 1
datafile2 line 2
datafile2 line 3
datafile2 line 4
datafile2 line 5

Get the JAR here

With an Applet, it's the same technique

import java.applet.*;
import java.io.*;

public class ReadFromJar extends Applet{

public void init(){


readTextFromJar("datafile1.txt");
readTextFromJar("test/datafile2.txt");
}

public void readTextFromJar(String s) {


String thisLine;
try {
InputStream is = getClass().getResourceAsStream(s);
BufferedReader br = new BufferedReader
(new InputStreamReader(is));
while ((thisLine = br.readLine()) != null) {
System.out.println(thisLine);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Create the JAR

>"C:\Program Files\Java\jdk1.5.0\bin\jar" −cf


MyJarApplet.jar ReadFromJar.class datafile1.txt test/datafile2.txt

The html

<HTML><HEAD></HEAD><BODY>
<APPLET CODE=ReadFromJar.class width=1 height=1 archive=MyJarApplet.jar>
</APPLET>
See java console for output</BODY></HTML>

Try it here

6.36 Read a text file from a jar


6.37 Extract a file from a Jar
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0429.html

The following snippet extract a file (mydb.mdb) from a jar.

import java.io.*;
import java.util.jar.*;
import java.util.zip.*;

public class ExtractFromJAR {

public void extractMyMDBromJAR(String dest){


try {
String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().
substring(6);
JarFile jar = new JarFile(home);
ZipEntry entry = jar.getEntry("mydb.mdb");
File efile = new File(dest, entry.getName());

InputStream in =
new BufferedInputStream(jar.getInputStream(entry));
OutputStream out =
new BufferedOutputStream(new FileOutputStream(efile));
byte[] buffer = new byte[2048];
for (;;) {
int nBytes = in.read(buffer);
if (nBytes <= 0) break;
out.write(buffer, 0, nBytes);
}
out.flush();
out.close();
in.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String args []){


new ExtractFromJAR().extractMyMDBFromJAR(".");
}

Grab this auto−run Jar if you want to try it.

To create an auto−run JAR, first create a manifest.mft

Manifest−Version: 1.0
Classpath: .\mydb.jar
Main−Class: ExtractFromJAR

Create the JAR

C:\jdk141\bin\jar cvfm mydb.jar manifest.mft ExtractFromJAR.class mydb.mdb

6.37 Extract a file from a Jar


Run it ... and the mydb.mdb file should appear in the current directory.

java −jar mydb.jar

(A tip from Fred Hommersom) Your code reads:


String home = getClass().getProtectionDomain().
getCodeSource().getLocation().toString().substring(6);

I got a problem when the jar file was located in C:\Program Files\xyz due to the embedded space.
So I modified the code to

String home = getClass().getProtectionDomain()


.getCodeSource().getLocation()
.getPath().replaceAll("%20", " ");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.38 Read a data file with floats


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0078.html

[ReadingFloat.java]

public class ReadingFloat {


public static float[] readFile(String file, String delimiter)
throws Exception {
return(readValues(new java.io.FileInputStream(file), delimiter));
}

public static float[] readURL(String url, String delimiter)


throws Exception {
java.net.URL addr = new java.net.URL(url);
return(readValues(addr.openStream(), delimiter));
}

public static float[] readValues(java.io.InputStream in, String delimiter)


throws java.io.FileNotFoundException,
java.io.IOException,
java.lang.NumberFormatException {
String thisLine;
java.io.BufferedInputStream s = new java.io.BufferedInputStream(in);
java.io.BufferedReader myInput = new java.io.BufferedReader
(new java.io.InputStreamReader(s));
int j = 0;
float[] values = new float[10];

while ((thisLine = myInput.readLine()) != null) {


// scan it line by line
java.util.StringTokenizer st =
new java.util.StringTokenizer(thisLine, delimiter);
while(st.hasMoreElements())
values[j++] = Float.valueOf(st.nextToken()).floatValue();

6.38 Read a data file with floats


}
return(values);
}

public static void main(String arg[]) {


new ReadingFloat().demo();
}

public void demo() {


try {
// we assume 10 floats (max)to be read
float results [] = readFile("floatwithdelimitercolon.dat", ",");
for(int i = 0; i < results.length; i++ ) {
System.out.println(results[i]);
}
System.out.println();
results = readFile("floatwithdelimiterspace.dat", " ");
for(int i = 0; i lt; results.length; i++ ) {
System.out.println(results[i]);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

[floatwithdelimitercolon.dat]

1.2,1.3,1.6,1.78,1.2345
2.2,2.3,2.6,2.78,2.2345

[floatwithdelimiterspace.dat]

1.2 1.3 1.6 1.78 1.2345


2.2 2.3 2.6 2.78 2.2345

6.39 Write to the end of a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0054.html

[JDK1.0.2]

import java.io.*;
public class appendtext {
public static void main(String args[]){
try {
PrintStream out =
new PrintStream(new AppendFileStream("myfile"));
out.print("A new line of text");
out.close();
}
catch(Exception e) {
System.out.println(e.toString());
}
}
}

6.39 Write to the end of a file


class AppendFileStream extends OutputStream {
RandomAccessFile fd;
public AppendFileStream(String file) throws IOException {
fd = new RandomAccessFile(file,"rw");
fd.seek(fd.length());
}
public void close() throws IOException {
fd.close();
}
public void write(byte[] b) throws IOException {
fd.write(b);
}
public void write(byte[] b,int off,int len) throws IOException {
fd.write(b,off,len);
}
public void write(int b) throws IOException {
fd.write(b);
}
}

[JDK1.1]

FileOutputStream fos = new FileOutputStream("myfile", true);

to open in Append mode

6.40 Write "real" ascii file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0058.html

Java uses Unicode character encoding internally. To pass information to outside world, it may be
necessary to use different encoding.

For example, DOS application may use MS ISO−Latin 1(or Codepage 850) to represent french
characters like é or à.

Before writting to a file or in a database record it is necessary to change the default String encoding.
This done via the InputStreamReader class for input and OutputStreamWriter for output.

InputStreamReader converts from the specified input encoding to Unicode while the
OutputStreamWriter converts from Unicode to the specified output encoding.

import java.io.*;
import java.awt.*;

public class DosString {


public static void main(String args[]){
String javaString = "é \u00e9"; // Unicode for "é"

try {
// output : Unicode to Cp850 (MS−DOS Latin−1)
FileOutputStream fos = new FileOutputStream("out.dat");
Writer w =
new BufferedWriter(new OutputStreamWriter(fos, "Cp850"));
w.write(JavaString);

6.40 Write "real" ascii file


w.flush();
w.close();

// input`: Cp850 to Unicode


FileInputStream fis = new FileInputStream("out.dat");
BufferedReader r =
new BufferedReader(new InputStreamReader(fis, "Cp850"));
String dosString = r.readLine();
r.close();
Frame f = new Frame();
f.setSize(100,100);
f.add(new Label(dosString));
f.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

NOTE: When the character encoding is not specified, the default encoding is used. You can find out the current default encoding by looking at
file.encoding property with System.getProperty("file.encoding"); .

6.41 Copy a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0064.html

[Old technique (pre JDK1.4)]

import java.io.*;

public class FileUtils{


public static void copyFile(File in, File out) throws Exception {
FileInputStream fis = new FileInputStream(in);
FileOutputStream fos = new FileOutputStream(out);
try {
byte[] buf = new byte[1024];
int i = 0;
while ((i = fis.read(buf)) != −1) {
fos.write(buf, 0, i);
}
}
catch (Exception e) {
throw e;
}
finally {
if (fis != null) fis.close();
if (fos != null) fos.close();
}
}

public static void main(String args[]) throws Exception{


FileUtils.copyFile(new File(args[0]),new File(args[1]));
}
}

[JDK1.4 using the java.nio package (faster)]

6.41 Copy a file


import java.io.*;
import java.nio.channels.*;

public class FileUtils{


public static void copyFile(File in, File out)
throws IOException
{
FileChannel inChannel = new
FileInputStream(in).getChannel();
FileChannel outChannel = new
FileOutputStream(out).getChannel();
try {
inChannel.transferTo(0, inChannel.size(),
outChannel);
}
catch (IOException e) {
throw e;
}
finally {
if (inChannel != null) inChannel.close();
if (outChannel != null) outChannel.close();
}
}

public static void main(String args[]) throws IOException{


FileUtils.copyFile(new File(args[0]),new File(args[1]));
}
}

NOTE:
In win2000 , the transferTo() does not transfer files > than 2^31−1 bytes. it throws an exception of "java.io.IOException: The parameter is
incorrect"
In solaris8 , Bytes transfered to Target channel are 2^31−1 even if the source channel file is greater than 2^31−1
In LinuxRH7.1 , it gives an error of java.io.IOException: Input/output error

ref : http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4643189

On the Windows plateform, you can't copy a file bigger than 64Mb, an Exception in thread "main"
java.io.IOException: Insufficient system resources exist to complete the requested service is thrown.

For a discussion about this see : http://forum.java.sun.com/thread.jspa?threadID=4396950

The workaround is to copy in a loop 64Mb each time until there is no more data.

Replace

...
try {
inChannel.transferTo(0, inChannel.size(),
outChannel);
}
...

by

...
try {
// magic number for Windows, 64Mb − 32Kb)
int maxCount = (64 * 1024 * 1024) − (32 * 1024);
long size = inChannel.size();
long position = 0;

6.41 Copy a file


while (position < size) {
position +=
inChannel.transferTo(position, maxCount, outChannel);
}
...

6.42 Use a "log file"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0063.html

/**
* Utilities log
*/
package rgagnon.utils;

import java.io.*;
import java.text.*;
import java.util.*;

public class SimpleLog {

private static String logFile = "/msglog.txt";


private final static DateFormat df = new SimpleDateFormat ("yyyy.mm.dd hh:mm:ss ");

private SimpleLog() { }

public static void setLogFilename(String filename) {


logFile = filename;
new File(filename).delete();

try {
write("LOG file : " + filename);
}
catch (Exception e) {
System.out.println(stack2string(e));
}

public static void write(String msg) {


write(logFile, msg);
}

public static void write(Exception e) {


write(logFile, stack2string(e));
}

public static void write(String file, String msg) {


try {
Date now = new Date();
String currentTime = Log.df.format(now);
FileWriter aWriter = new FileWriter(file, true);
aWriter.write(currentTime + " " + msg
+ System.getProperty("line.separator"));
System.out.println(currentTime + " " + msg);
aWriter.flush();
aWriter.close();
}
catch (Exception e) {

6.42 Use a "log file"


System.out.println(stack2string(e));
}
}

private static String stack2string(Exception e) {


try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return "−−−−−−\r\n" + sw.toString() + "−−−−−−\r\n";
}
catch(Exception e2) {
return "bad stack2string";
}
}
}

and then to use it

SimpleLog.write("i am here");

See also this HowTo and this one

6.43 Delete files with a certain extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0072.html

Define a special FilenameFilter :

import java.io.*;

public class ExtensionFilter implements FilenameFilter {


private String extension;
public ExtensionFilter( String extension ) {
this.extension = extension;
}

public boolean accept(File dir, String name) {


return (name.endsWith(extension));
}
}

and then

import java.io.*;

public class FileUtils{

public static void main(String args[]) throws Exception {


FileUtils.deleteFiles("c:/test/", ".gif");
}

public static void deleteFiles( String directory, String extension ) {


ExtensionFilter filter = new ExtensionFilter(extension);
File dir = new File(directory);

6.43 Delete files with a certain extension


String[] list = dir.list(filter);
File file;
if (list.length == 0) return;

for (int i = 0; i < list.length; i++) {


//file = new File(directory + list[i]);
file = new File(directory, list[i]);
System.out.print(file + " deleted : " + file.delete());
}
}
}
}

6.44 Insert a line in a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0073.html

The only way to insert a line in a text file is to read the original file and write the content in a
temporary file with the new line inserted. Then we erase the original file and rename the temporary
file to the original name.

In this example, you need to supply 3 arguments : the filename, a line number and the string to be
inserted at the line number specified.

java JInsert test.out 9 "HELLO WORLD"

will insert the string "HELLO WORLD" at line number 9 in the file "test.out".

of course you need more error checking...

[JDK1.1]
import java.io.*;

public class JInsert {


public static void main(String args[]){
try {
JInsert j = new JInsert();
j.insertStringInFile
(new File(args[0]),Integer.parseInt(args[1]), args[2]);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void insertStringInFile


(File inFile, int lineno, String lineToBeInserted)
throws Exception {
// temp file
File outFile = new File("$$$$$$$$.tmp");

// input
FileInputStream fis = new FileInputStream(inFile);
BufferedReader in = new BufferedReader
(new InputStreamReader(fis));

6.44 Insert a line in a file


// output
FileOutputStream fos = new FileOutputStream(outFile);
PrintWriter out = new PrintWriter(fos);

String thisLine = "";


int i =1;
while ((thisLine = in.readLine()) != null) {
if(i == lineno) out.println(lineToBeInserted);
out.println(thisLine);
i++;
}
out.flush();
out.close();
in.close();

inFile.delete();
outFile.renameTo(inFile);
}
}

6.45 Read a file into a variable in one shot


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0074.html

import java.io.*;

public class ReadFullyIntoVar {


public static void main(String argv[]){
try {
FileInputStream file = new FileInputStream (argv[0]);
DataInputStream in = new DataInputStream (file);
byte[] b = new byte[in.available ()];
in.readFully (b);
in.close ();
String result = new String (b, 0, b.length, "Cp850");
/* */
System.out.println(result);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

6.46 Serialize an object to a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0075.html

Suppose we have a class called Queue.class. We want to save the state of the Queue in a file.
Since our Queue extends the Vector class, the methods needed to serialize the object are already
done. All we need is an input or output stream.

First the Queue class

6.45 Read a file into a variable in one shot


import java.util.Vector;
import java.io.*;

public class Queue extends Vector {


/*
** FIFO, first in first out
*/
Queue() {
super();
}

void put(Object o) {
addElement(o);
}

Object get() {
if (isEmpty()) return null;
Object o = firstElement();
removeElement(o);
return o;
}

Object peek() {
if (isEmpty()) return null;
return firstElement();
}
}

To serialize (save the Queue state to a file) :

public static void main(String args[]) {


Queue theQueue;

theQueue = new Queue();


theQueue.put("element 1");
theQueue.put("element 2");
theQueue.put("element 3");
theQueue.put("element 4");
System.out.println(theQueue.toString());

// serialize the Queue


System.out.println("serializing theQueue");
try {
FileOutputStream fout = new FileOutputStream("thequeue.dat");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(theQueue);
oos.close();
}
catch (Exception e) { e.printStackTrace(); }
}

To unserialize (to load a previously saved Queue) :

public static void main(String args[]) {


Queue theQueue;

theQueue = new Queue();

// unserialize the Queue


System.out.println("unserializing theQueue");
try {
FileInputStream fin = new FileInputStream("thequeue.dat");

6.45 Read a file into a variable in one shot


ObjectInputStream ois = new ObjectInputStream(fin);
theQueue = (Queue) ois.readObject();
ois.close();
}
catch (Exception e) { e.printStackTrace(); }

System.out.println(theQueue.toString());
}

6.47 Redirect stdout to a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0061.html

[JDK1.1] application only

System.setOut(
new PrintStream(
new BufferedOutputStream(
new FileOutputStream("OUTPUT.DAT"))));

You may want to look at this How−to to redirect exception output to a Frame.

6.48 Get the "last modified" date from a file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0068.html

Simply use the lastModified() method from a file object. but the return value is system dependent
and should only be used to compare with other values returned by last modified. It should not be
interpreted as an absolute time.

String s1 = "file1.dat";
String s2 = "file2.dat";

File f1 = new File(s1);


File f2 = new File(s2);

if (f1.lastModified() < f2.lastModified())


System.out.println((s1 + " IS OLDER THAN " + S2);

6.49 Check if a file exists


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0070.html

import java.io.*;

public class FileTest {


public static void main(String args[]) {
File f = new File(args[0]);
System.out.println
(f + (f.exists()? " is found " : " is missing "));

6.47 Redirect stdout to a file


}
}

6.50 Get the current directory


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0076.html

import java.io.File;
public class CurrentDir {
public static void main (String args[]) {
File dir1 = new File (".");
File dir2 = new File ("..");
try {
System.out.println ("Current dir : " + dir1.getCanonicalPath());
System.out.println ("Parent dir : " + dir2.getCanonicalPath());
}
catch(Exception e) {
e.printStackTrace();
}
}
}

6.51 Get the "root" of an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0581.html

By root, we mean the starting directory.

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

public class DummyApp {


public static void main(String args[]) throws Exception{
DummyApp s = new DummyApp();
s.getRoot();
}

public void getRoot() throws IOException, URISyntaxException{


URL u = getClass().getProtectionDomain().getCodeSource().getLocation();
File f = new File(u.toURI());
System.out.println(f.getParent());
}
}

Running from a regular class

C:\Applications\dev\HowTo>java −cp . DummyApp


C:\Applications\dev

Running from a jar

6.50 Get the current directory


C:\Applications\dev\HowTo>jar cf DummyApp.jar DummyApp.*

C:\Applications\dev\HowTo>java −cp DummyApp.jar DummyApp


C:\Applications\dev\HowTo

See these related HowTo's : 1 2

6.52 Get the content of a directory with a Filter


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0055.html

First you create a class that implements java.io.FilenameFilter and then code the accept() method,
then call File.list() with the filter as a parameter. The returned array of strings has all the names that
passed through the accept()filter.

import java.io.File;
import java.io.FilenameFilter;

public class Filter implements FilenameFilter {


protected String pattern;
public Filter (String str) {
pattern = str;
}

public boolean accept (File dir, String name) {


return name.toLowerCase().endsWith(pattern.toLowerCase());
}

public static void main (String args[]) {


if (args.length != 1) {
System.err.println
("usage: java Filter <pattern list> ex. java Filter java");
return;
}

Filter nf = new Filter (args[0]);


// current directory
File dir = new File (".");
String[] strs = dir.list(nf);
for (int i = 0; i < strs.length; i++) {
System.out.println (strs[i]);
}
}
}

Here a version to support multiple filters.

import java.io.File;
import java.io.FilenameFilter;
import java.util.*;
import java.util.TreeSet.*;

public class Filter implements FilenameFilter {


protected Set extensionsSet;

public Filter (String [] extensions) {


extensionsSet = new TreeSet();

6.52 Get the content of a directory with a Filter


for (Iterator ext=Arrays.asList(extensions).iterator();
ext.hasNext();)
{
extensionsSet.add(ext.next().toString().toLowerCase().trim());
}
extensionsSet.remove("");
}

public boolean accept (File dir, String name) {


final Iterator exts = extensionsSet.iterator();
while (exts.hasNext()) {
if (name.toLowerCase().endsWith(exts.next().toString())) {
return true;
}
}
return false;
}

public static void main (String args[]) {


if (args.length < 1) {
System.err.println
("usage: java Filter <pattern list> ex. java Filter java txt");
return;
}
Filter nf = new Filter (args);
// current directory
File dir = new File (".");
String[] strs = dir.list(nf);
for (int i = 0; i < strs.length; i++) {
System.out.println (strs[i]);
}
}
}

If multiple extensions are to be checked then a regular expression can be used.

import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.*;

public class Filter implements FilenameFilter {

public boolean accept (File dir, String name) {


return Pattern.matches(".*\\.(jpg|jpeg|gif|png|bmp)", name);
// if only one extension to check : "\\.jpg"
}

public static void main (String args[]) {


if (args.length < 1) {
System.err.println
("usage: java Filter <directory> ex. java Filter c:\\temp");
return;
}
Filter nf = new Filter();
// current directory
File dir = new File (args[0]);
String[] strs = dir.list(nf);
for (int i = 0; i < strs.length; i++) {
System.out.println (strs[i]);
}
}

6.52 Get the content of a directory with a Filter


}

6.53 Get the content of a directory with subdirectories


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0056.html

import java.io.*;
import java.util.*;
public class DirUtils {

public static List recurseDir(String dir) {


String result, _result[];

result = recurseInDirFrom(dir);
_result = result.split("\\|");
return Arrays.asList(_result);
}

private static String recurseInDirFrom(String dirItem) {


File file;
String list[], result;

result = dirItem;

file = new File(dirItem);


if (file.isDirectory()) {
list = file.list();
for (int i = 0; i < list.length; i++)
result = result + "|"
+ recurseInDirFrom(dirItem + File.separatorChar + list[i]);
}
return result;
}

public static void main(String arg[]) {


if (arg.length > 0) {
System.out.println("recursive Dirs from " + arg[0]);
System.out.println(DirUtils.recurseDir(arg[0]));
}
else {
System.out.println("Usage :");
System.out.println(" java DirUtils c:\temp");
}

/*
output:

C:\Applications>java DirUtils c:\zip


recursive Dir from c:\zip
[c:\zip, c:\zip\AutoIt.exe, c:\zip\cc32d48.exe, c:\zip\CODE_UPLOAD
148812122001.zip, c:\zip\groups2.txt, c:\zip\httrack−3.23.exe, c:\
zip\mass20.zip, c:\zip\mp3,c:\zip\mp3\BonkEnc−1.0−beta1.exe, c:\zi
p\mp3\cdex_150b10_enu.exe, c:\zip\mp3\hh_install.exe, c:\zip\mp3\T
PlayerSetup.exe, c:\zip\mp3\Tunchy1017full.zip, c:\zip\mp3\TWMP3en
coder.exe, c:\zip\ok, c:\zip\ok\CmdHerePowertoySetup.exe, c:\zip\o
k\htmldoc−1.8.23−winfree.exe, c:\zip\ok\j2sdk−1_4_1_02−windows−i58
6.exe, c:\zip\ok\jdk141−hh.zip, c:\zip\ok\jsref13.zip, c:\zip\ok\T
weakUiPowertoySetup.exe, c:\zip\quickmail−2_1.zip, c:\zip\RealOneP
layerV2GOLD.exe, c:\zip\RESTorefile2514.EXE,c:\zip\Shockwave_Insta

6.53 Get the content of a directory with subdirectories


ller_Full.exe, c:\zip\Water.exe, c:\zip\winamp50_full.exe,c:\zip\w
olf, c:\zip\wolf\ok, c:\zip\wolf\ok\kf_box.zip, c:\zip\wolf\sp_off
lag_levels_1−4_final.zip, c:\zip\xpAntiSpy.zip]
*/
}
}

6.54 Make a directory


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0057.html

For application only, not Applet!

File td = new File("NewDirName");


td.mkDir();

6.55 Create a fixed−length file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0461.html

//
// usage : java CreateAFile 2048 twokbytes.dat
//
import java.io.FileOutputStream;
import java.io.IOException;

public class CreateAFile {


public static void main(String[] args) throws IOException {
byte[] buf = new byte[8192];
long n = Long.parseLong(args[0]);
FileOutputStream fos = new FileOutputStream(args[1]);
long m = n / buf.length;
for (long i = 0; i < m; i++) {
fos.write(buf, 0, buf.length);
}
fos.write(buf, 0, (int)(n % buf.length));
fos.close();
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.56 Delete a non−empty directory


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0483.html

Use the following recursive method.

6.54 Make a directory


import java.io.File;

class DeleteDir {
public static void main(String args[]) {
deleteDirectory(new File(args[0]));
}

static public boolean deleteDirectory(File path) {


if( path.exists() ) {
File[] files = path.listFiles();
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
return( path.delete() );
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.57 Create a temporary file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0484.html

import java.io.File;

...

File temp = File.createTempFile("real",".howto");


temp.deleteOnExit();

Creates an empty file in the default temporary−file directory, using the given prefix ("real") and suffix
(".howto"). Plus, the temporary file will be deleted when the virtual machine terminates. Deletion will
be attempted only for normal termination of the virtual machine.

(Javadoc) The prefix argument must be at least three characters long. It is recommended that the prefix be a short, meaningful string such as
"hjb" or "mail". The suffix argument may be null, in which case the suffix ".tmp" will be used. To create the new file, the prefix and the suffix may
first be adjusted to fit the limitations of the underlying platform.

If the prefix is too long then it will be truncated, but its first three characters will always be
preserved. If the suffix is too long then it too will be truncated, but if it begins with a period character
('.') then the period and the first three characters following it will always be preserved.

Once these adjustments have been made the name of the new file will be generated by
concatenating the prefix, five or more internally−generated characters, and the suffix.

The location of the directory used to hold temporary files is defined by the property java.io.tmpdir.
The default value can be changed with the command line used to launch the JVM :

6.57 Create a temporary file


java −Djava.io.tmpdir=C:\mydir myClass

or , on Windows, you can set the environment variable TMP to a different value.

On some plateform, the temporary directory returned by java.io.tmpdir do not include a trailing
slash. That is,

Win NT −−> C:\TEMP\


Win XP −−> C:\TEMP
Solaris −−> /var/tmp/
Linux −−> /var/tmp

It's not a bad idea to check if there is a trailing slash or not.

String tempdir = System.getProperty("java.io.tmpdir");

if ( !(tempdir.endsWith("/") || tempdir.endsWith("\\")) )
tempdir = tempdir + System.getProperty("file.separator");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.58 Detect file modification


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0490.html

For a single file, a thread is launched to check the lastModified value and compare it with the
previous value.

import java.util.*;
import java.io.*;

public abstract class FileWatcher extends TimerTask {


private long timeStamp;
private File file;

public FileWatcher( File file ) {


this.file = file;
this.timeStamp = file.lastModified();
}

public final void run() {


long timeStamp = file.lastModified();

if( this.timeStamp != timeStamp ) {


this.timeStamp = timeStamp;
onChange(file);
}
}

protected abstract void onChange( File file );


}

6.58 Detect file modification


import java.util.*;
import java.io.*;

class FileWatcherTest {
public static void main(String args[]) {
// monitor a single file
TimerTask task = new FileWatcher( new File("c:/temp/text.txt") ) {
protected void onChange( File file ) {
// here we code the action on a change
System.out.println( "File "+ file.getName() +" have change !" );
}
};

Timer timer = new Timer();


// repeat the check every second
timer.schedule( task , new Date(), 1000 );
}
}

For a directory, a thread is launched where we keep the Files in a Map, we check the current
lastModifed value of a given file and compare it with the value stored in the Map. Also a special
check is made to detect if a File is deleted.

import java.util.*;
import java.io.*;

public abstract class DirWatcher extends TimerTask {


private String path;
private File filesArray [];
private HashMap dir = new HashMap();
private DirFilterWatcher dfw;

public DirWatcher(String path) {


this(path, "");
}

public DirWatcher(String path, String filter) {


this.path = path;
dfw = new DirFilterWatcher(filter);
filesArray = new File(path).listFiles(dfw);

// transfer to the hashmap be used a reference and keep the


// lastModfied value
for(int i = 0; i <filesArray.length; i++) {
dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
}
}

public final void run() {


HashSet checkedFiles = new HashSet();
filesArray = new File(path).listFiles(dfw);

// scan the files and check for modification/addition


for(int i = 0; i < filesArray.length; i++) {
Long current = (Long)dir.get(filesArray[i]);
checkedFiles.add(filesArray[i]);
if (current == null) {
// new file
dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
onChange(filesArray[i], "add");
}
else if (current.longValue() != filesArray[i].lastModified()){

6.58 Detect file modification


// modified file
dir.put(filesArray[i], new Long(filesArray[i].lastModified()));
onChange(filesArray[i], "modify");
}
}

// now check for deleted files


Set ref = ((HashMap)dir.clone()).keySet();
ref.removeAll((Set)checkedFiles);
Iterator it = ref.iterator();
while (it.hasNext()) {
File deletedFile = (File)it.next();
dir.remove(deletedFile);
onChange(deletedFile, "delete");
}
}

protected abstract void onChange( File file, String action );


}

class DirFilterWatcher implements FileFilter {


private String filter;

public DirFilterWatcher() {
this.filter = "";
}

public DirFilterWatcher(String filter) {


this.filter = filter;
}

public boolean accept(File file) {


if ("".equals(filter)) {
return true;
}
return (file.getName().endsWith(filter));
}
}

import java.util.*;
import java.io.*;

class DirWatcherTest {
public static void main(String args[]) {
TimerTask task = new DirWatcher("c:/temp", "txt" ) {
protected void onChange( File file, String action ) {
// here we code the action on a change
System.out.println
( "File "+ file.getName() +" action: " + action );
}
};

Timer timer = new Timer();


timer.schedule( task , new Date(), 1000 );
}
}

See also this related howto.

6.58 Detect file modification


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.59 Get the default character set of the JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0505.html

public class Hello {


public static void main(String args[]) throws Exception{
// not crossplateform safe
System.out.println(System.getProperty("file.encoding"));
// jdk1.4
System.out.println(
new java.io.OutputStreamWriter(
new java.io.ByteArrayOutputStream()).getEncoding()
);
// jdk1.5
System.out.println(java.nio.charset.Charset.defaultCharset().name());
}
}

Output example (winXP)

>java Hello
Cp1252
Cp1252
windows−1252

See also java encoding table for the encoding sets supported.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.60 Parse a pathname


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0514.html

import java.io.File;

public class ParsePathname {

public ParsePathname() { }

public static void main(String[] args) throws Exception {


File f = new File
("c:/program files/adobe/Acrobat 5.0/Reader/acrord32.exe");
System.out.println("dir : " + f.getParent());
System.out.println("file : " + f.getName());
System.out.println("ext : " + getFileExtension(f.getName()));

6.59 Get the default character set of the JVM


System.out.println("url : " + f.toURL());
System.out.println("uri : " + f.toURI());
/*
output :
dir : c:\program files\adobe\Acrobat 5.0\Reader
file : acrord32.exe
ext : exe
url : file:/c:/program files/adobe/Acrobat 5.0/Reader/acrord32.exe
uri : file:/c:/program%20files/adobe/Acrobat%205.0/Reader/acrord32.exe
*/
}

public static String getFileExtension(String f) {


String ext = "";
int i = f.lastIndexOf('.');
if (i > 0 & i < f.length() − 1) {
ext = f.substring(i+1).toLowerCase();
}
return ext;
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.61 Handle Excel files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0516.html

There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about
OpenSource (and free) solutions.

6.62 JDBC−ODBC Excel driver


This solution lets you access your Excel worksheet with SQL SELECT statement. The required
ODBC driver is included in a regular Windows installation and the JDBC−ODBC bridge is used to
access the Excel DSN.

See this HowTo for an example.

6.63 JExcel
Java Excel API is a java API enabling developers to read, write, and modify Excel spreadsheets
dynamically. Any operating system which can run a Java virtual machine can both process and
deliver Excel spreadsheets. One nice thing about JExcelApi is that it has no dependencies on any
third party libraries.

Example : output an Excel file from a Servlet

import java.io.IOException;
import java.io.OutputStream;

6.61 Handle Excel files


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Sample extends HttpServlet {


public void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream out = null;
try {
response.setContentType("application/vnd.ms−excel");
response.setHeader
("Content−Disposition", "attachment; filename=sampleName.xls");
WritableWorkbook w =
Workbook.createWorkbook(response.getOutputStream());
WritableSheet s = w.createSheet("Demo", 0);
s.addCell(new Label(0, 0, "Hello World"));
w.write();
w.close();
}
catch (Exception e){
throw new ServletException("Exception in Excel Sample Servlet", e);
}
finally{
if (out != null)
out.close();
}
}
}

See http://jexcelapi.sourceforge.net/

6.64 POI
The POI project consists of APIs for manipulating various file formats based upon Microsoft's OLE 2
Compound Document format using pure Java. POI is your Java Excel solution as well as your Java
Word solution.

HSSF is the POI Project's pure Java implementation of the Excel '97(−2002) file format and it
provides a way to read spreadsheets create, modify, read and write XLS spreadsheets.

Since it's Jakarta project, POI has a dependencies with other JARs (commons,log4j,etc...).

Example : create an Excel file

HSSFWorkbook wb = new HSSFWorkbook();


HSSFSheet sheet = wb.createSheet("new sheet");

HSSFRow row = sheet.createRow((short)0);


row.createCell((short)0).setCellValue("HelloWorld");

FileOutputStream fileOut = new FileOutputStream("workbook.xls");


wb.write(fileOut);

6.64 POI
fileOut.close();

The name was originally an acronym for "Poor Obfuscation Implementation" (ref: Wikipedia).

See http://jakarta.apache.org/poi/

6.65 JXLS
jXLS is a project that allows creation of extremely complex Excel reports just in several lines of
code. It is based on Jakarta POI.

With jXLS, all you need is to create XLS template file with all required formatting, formulas etc using
specific notation to indicate placement of data and then write a couple lines of code to invoke jXLS
engine passing XLS template and the exported data as parameters.

Example :
The XLS Template

Employees
Name Age Payment Bonus
${employee.name} ${employee.age} ${employee.payment} ${employee.bonus}
$[SUM(@employee.payment@)]

with the code

Collection staff = new HashSet();


staff.add(new Employee("Derek", 35, 3000, 0.30));
staff.add(new Employee("Elsa", 28, 1500, 0.15));
Map beans = new HashMap();
beans.put("employee", staff);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS(templateFileName, beans, destFileName);

gives the result

Employees
Name Age Payment Bonus
Derek 35 3000 30,00%
Else 28 1500 15,00%
4500

See http://jxls.sourceforge.net/

6.66 xlSQL
xlSQL is a JDBC Driver for Excel and CSV data sources. Documents can be read and written with
SQL as if they were tables in a database.

You can export XLS to XML or SQL INSERT statements. xlSQL includes its own "zero−admin"
mySQL database. The documentation is minimal at this time.

See http://xlsql.sourceforge.net/

6.65 JXLS
6.67 JCOM
JCOM is a Java to COM bridge library. With JCOM you can call a COM object from Java as if it
were a Java object without having to deal with the internals of JNI. The documentation is minimal (in
Japanese!).

Example :

import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
import java.io.File;
import java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
System.out.println("EXCEL startup...");
// if already started, open new window
ExcelApplication excel = new ExcelApplication(rm);
excel.Visible(true);
// display any information
System.out.println("Version="+excel.Version());
System.out.println("UserName="+excel.UserName());
System.out.println("Caption="+excel.Caption());
System.out.println("Value="+excel.Value());

ExcelWorkbooks xlBooks = excel.Workbooks();


ExcelWorkbook xlBook = xlBooks.Add(); // create new book

// enumurate all files


System.out.println
("set infomation of files in current directory to cell ...");
ExcelWorksheets xlSheets = xlBook.Worksheets();
ExcelWorksheet xlSheet = xlSheets.Item(1);
ExcelRange xlRange = xlSheet.Cells();

xlRange.Item(1,1).Value("filename" );
xlRange.Item(2,1).Value("size" );
xlRange.Item(3,1).Value("last modified time");
xlRange.Item(4,1).Value("is directory");
xlRange.Item(5,1).Value("is file");
xlRange.Item(6,1).Value("can read");
xlRange.Item(7,1).Value("can write");

File path = new File("./");


String[] filenames = path.list();
for(int i=0; i<filenames.length; i++) {
File file = new File(filenames[i]);
System.out.println(file);
xlRange.Item(1,i+2).Value( file.getName() );
xlRange.Item(2,i+2).Value( (int)file.length() );
xlRange.Item(3,i+2).Value( new Date(file.lastModified()) );
xlRange.Item(4,i+2).Value( file.isDirectory()?"Yes":"No" );
xlRange.Item(5,i+2).Value( file.isFile()?"Yes":"No" );
xlRange.Item(6,i+2).Value( file.canRead()?"Yes":"No" );
xlRange.Item(7,i+2).Value( file.canWrite()?"Yes":"No" );
}
String expression = "=Sum(B2:B"+(filenames.length+1)+")";
System.out.println
("embed equation, calculate sum of filesize: "+expression);

6.67 JCOM
xlRange.Item(1,filenames.length+2).Value("sum");
xlRange.Item(2,filenames.length+2).Formula(expression);
xlRange.Columns().AutoFit(); // fit columns

// comment out, if print out.


// output default printer.
// System.out.println("print out...");
// xlSheet.PrintOut();

// comment out, if book save to file.


// if no path, save to(My Documents)
// System.out.println
// ("save to file... (My Documents)\\testExcel.xls");
// xlBook.SaveAs("testExcel.xls");

xlBook.Close(false,null,false);
excel.Quit();

System.out.println("thank you .");


}
catch(Exception e) { e.printStackTrace(); }
finally { rm.release(); }
}
}

See http://sourceforge.net/projects/jcom

See also this HowTo for an alternative package to access a COM package from Java.

6.68 OpenXLS Java Spreadsheet SDK


OpenXLS claims that it has the best compatibility with complex Excel files and able to handle any
kind of Excel file out there without corrupting it. This open source effort is the result of over 6 years
of development into it.

See http://www.extentech.com/estore/product_detail.jsp?product_group_id=228

Example (extract 3 images from a workbook, create a new workbook with them) :

doit("testImages.xls","Sheet1");

...

void doit(String finpath, String sheetname){


System.out.println("Begin parsing: " + workingdir + finpath);
WorkBookHandle tbo = new WorkBookHandle(workingdir + finpath);

try{
sheet = tbo.getWorkSheet(sheetname);
// read images from sheet 1 −− .gif, .png, .jpg
ImageHandle[] extracted = sheet.getImages();
// extract and output images
for(int t=0;t<extracted.length;t++) {
System.out.println("Successfully extracted: "
+ workingdir + "testImageOut_"
+ extracted[t].getName()+"."
+extracted[t].getType());
FileOutputStream outimg = new FileOutputStream
(workingdir + extracted[t].getName()+"."
+extracted[t].getType());

6.68 OpenXLS Java Spreadsheet SDK


extracted[t].write(outimg);
outimg.flush();
outimg.close();
}

tbo = new WorkBookHandle();


sheet = tbo.getWorkSheet("Sheet1");
CellHandle a1 = sheet.add
("New workbook with 3 images: a gif, a jpg, and a png", "A1");

// get gif image input stream


FileInputStream fin = new FileInputStream
(workingdir + "testImages.gif");

// add to sheet
ImageHandle giffy = new ImageHandle(fin, sheet);

// set picture size and location in sheet


giffy.setBounds(100, 100, 400, 200);
giffy.setName("giffy");
sheet.insertImage(giffy);

// add to sheet
for(int x=0;x<100;x++) {
fin = new FileInputStream(workingdir + "testImages.png");
ImageHandle jpgy = new ImageHandle(fin, sheet);
jpgy.setName("heart" + x);
// set the random x/y coords of picture
int ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setX(100 + ix);
ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setY(100 + ix);
sheet.insertImage(jpgy);
}
// get png image input stream
fin = new FileInputStream(workingdir + "testImages.jpg");
// add to sheet
ImageHandle pngy = new ImageHandle(fin, sheet);
// set just the x/y coords of picture
pngy.setX(10);
pngy.setY(200);
sheet.insertImage(pngy);
}
catch(Exception e){
System.err.println("testImages failed: " + e.toString());
}
testWrite(tbo, workingdir + "testImagesOut.xls");
WorkBookHandle newbook = new WorkBookHandle
(workingdir + "testImagesOut.xls",0);
System.out.println("Successfully read: " + newbook);
}

public void testWrite(WorkBookHandle b, String fout){


try{
java.io.File f = new java.io.File(fout);
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bbout = new BufferedOutputStream(fos);
bbout.write(b.getBytes());
bbout.flush();
fos.close();
}
catch (java.io.IOException e){
System.err.println("IOException in Tester. "+e);

6.68 OpenXLS Java Spreadsheet SDK


}
}

See also this HowTo for a way to create a simple XLS without any additional library.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

6.69 Handle CSV file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0591.html

6.70 com.Ostermiller.util CSV Utils


CSVPrinter/CSVParser/ExcelCSVPrinter/ExcelCSVParser
http://ostermiller.org/utils/CSV.html

6.71 opencsv
A simple csv parser library for Java
http://opencsv.sourceforge.net/

6.72 ServingXML
Framework for flat/XML data transformations. Supported transformations : flat−XML, XML−flat,
flat−flat, and XML−XML
http://servingxml.sourceforge.net/

6.73 Super CSV


This CSV reader/writer makes it easy to read/write objects/maps/string lists with automatic type
conversion and constraint checking.
http://supercsv.sourceforge.net/

6.74 csvreader
Library for reading and writing CSV and plain delimited text files. All kinds of CSV files can be
handled, text qualified, Excel formatted, etc.
http://www.csvreader.com/java_csv.php

6.75 CSVFile
A simple set of Java classes used to handle CSV
http://sourceforge.net/projects/csvfile

6.69 Handle CSV file


6.76 FlatPack
Flat file parser that handles CSV, fixed length and custom delimiters. Export a DataSet to a fixed
length or delimited format. FlatPack provides a sorting mechanism for your flat files.
http://flatpack.sourceforge.net/

6.77 Create an Excel file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0586.html

While you can use specialized packages to create native Excel file, an easy way to import data into
Excel is to create an HTML file and embed the date into a TABLE tag. You give to the file the XLS
extension and Excel will do the translation for you!

With a text editor or from a program, create a file named test.xls with this content

<TABLE>
<th><h4>Just testing</h4>
<TR><TD width="20">1</TD><TD width="30">2</TD><TD width="40">3</TD></TR>
<TR><TD>4</TD><TD>4</TD><TD>6</TD></TR>
<TR><TD>7</TD><TD>8</TD><TD>9</TD></TR>
<TR><TD>=SUM(A3:A5)</TD><TD>=SUM(B3:B5)</TD><TD>=SUM(C3:C5)</TD></TR>
</TABLE>

Now you can double click on the saved file to load it into Excel and the translation will be done.

This trick works with OpenOffice too.

From a server, remember to send the appropriate MIME TYPE : application/excel to the client.

See also this HowTo

6.78 Create or process a PDF file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0523.html

A nice OpenSource is http://www.lowagie.com/iText/ [ITEXT] . iText can deal with RTF and HTML
file too.

Nicely documented with many examples.


• Create a PDF
import java.io.FileOutputStream;
import java.io.IOException;

import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfWriter;

public class HelloWorld {


public static void main(String[] args) {
System.out.println("Hello World");

6.76 FlatPack
Document document = new Document();
try {
PdfWriter.getInstance(document,
new FileOutputStream("HelloWorld.pdf"));
document.open();
document.add(new Paragraph("Hello World"));
}
catch (DocumentException de) {
System.err.println(de.getMessage());
}
catch (IOException ioe) {
System.err.println(ioe.getMessage());
}
document.close();
}
}
• Add a watermark to an existing document.
import java.io.FileOutputStream;
import java.util.HashMap;

import com.lowagie.text.Element;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;

public class AddWatermarkPageNumbers {


public static void main(String[] args) {
System.out.println("Add watermarks and pagenumbers");
try {
PdfReader reader = new PdfReader("ChapterSection.pdf");
int n = reader.getNumberOfPages();
// create a stamper that will copy the document to a new file
PdfStamper stamp = new PdfStamper(reader,
new FileOutputStream("watermark_pagenumbers.pdf"));
// adding some metadata
HashMap moreInfo = new HashMap();
moreInfo.put("Author", "Bruno Lowagie");
stamp.setMoreInfo(moreInfo);
// adding content to each page
int i = 0;
PdfContentByte under;
PdfContentByte over;
Image img = Image.getInstance("watermark.jpg");
BaseFont bf =
BaseFont.createFont
(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
img.setAbsolutePosition(200, 400);
while (i < n) {
i++;
// watermark under the existing page
under = stamp.getUnderContent(i);
under.addImage(img);
// text over the existing page
over = stamp.getOverContent(i);
over.beginText();
over.setFontAndSize(bf, 18);
over.setTextMatrix(30, 30);
over.showText("page " + i);
over.setFontAndSize(bf, 32);
over.showTextAligned

6.76 FlatPack
(Element.ALIGN_LEFT, "DUPLICATE", 230, 430, 45);
over.endText();
}
// adding an extra page
stamp.insertPage(1, PageSize.A4);
over = stamp.getOverContent(1);
over.beginText();
over.setFontAndSize(bf, 18);
over.showTextAligned(Element.ALIGN_LEFT,
"DUPLICATE OF AN EXISTING PDF DOCUMENT", 30, 600, 0);
over.endText();
// adding a page from another document
PdfReader reader2 = new PdfReader("SimpleAnnotations1.pdf");
under = stamp.getUnderContent(1);
under.addTemplate
(stamp.getImportedPage(reader2, 3), 1, 0, 0, 1, 0, 0);
// closing PdfStamper will generate the new PDF file
stamp.close();
}
catch (Exception de) {
de.printStackTrace();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.79 Convert OEM (DOS) file to Ansi (Windows)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0524.html

We are using an InputStreamReader which convert the specified input encoding to Unicode and an
OutputStreamWriter which from Unicode to the specified output encoding.

This can be useful when migrating data from a legacy database (ex. Clipper, dBase) to newer
DBMS (ex. mySQL, Sybase).

import java.io.*;

public class OemToAnsi {

public static void main(String args[]) throws Exception{


if (args.length != 2) {
System.out.println(
"Usage : java OemToAnsi inputdosfile outputansifile"
);
System.out.println(
" note : codepage input Cp850 codepage output Cp1252"
);
System.exit(1);
}
// input
FileInputStream fis = new FileInputStream(args[0]);
BufferedReader r =

6.79 Convert OEM (DOS) file to Ansi (Windows)


new BufferedReader(new InputStreamReader(fis, "Cp850"));
// output
FileOutputStream fos = new FileOutputStream(args[1]);
Writer w =
new BufferedWriter(new OutputStreamWriter(fos, "Cp1252"));
String oemString = "";
while ( (oemString= r.readLine()) != null) {
w.write(oemString);
w.flush();
}
w.close();
r.close();
System.exit(0);
}
}

See also this related HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

6.80 Close a stream in a try/catch block


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0539.html

You close them in the finally clause using a special method.

public static boolean compareFile(File file1, File file2) {


BufferedInputStream in1 = null;
BufferedInputStream in2 = null;

try {
in1 = new BufferedInputStream(new FileInputStream(file1));
in2 = new BufferedInputStream(new FileInputStream(file2));

boolean result = true;


int i;
do {
i = in1.read();
result = (i == in2.read());
} while ( result && i != −1 );

return result;
}
catch (FileNotFoundException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
finally {
close(in1);
close(in2);
}

return false;

6.80 Close a stream in a try/catch block


}

private static void close( InputStream is ) {


if ( is != null ) {
try {
is.close();
}
catch ( IOException ioe ) {
ioe.printStackTrace();
}
}
}

6.81 Rename a file extension


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0541.html

public static boolean renameFileExtension


(String source, String newExtension)
{
String target;
String currentExtension = getFileExtension(source);

if (currentExtension.equals("")){
target = source + "." + newExtension;
}
else {
target = source.replaceAll("." + currentExtension, newExtension);
}
return new File(source).renameTo(new File(target));
}

public static String getFileExtension(String f) {


String ext = "";
int i = f.lastIndexOf('.');
if (i > 0 && i < f.length() − 1) {
ext = f.substring(i + 1).toLowerCase();
}
return ext;
}

6.82 Remove HTML tags from a file to extract only the TEXT
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0424.html

import java.io.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;

public class Html2Text extends HTMLEditorKit.ParserCallback {


StringBuffer s;

public Html2Text() {}

public void parse(Reader in) throws IOException {

6.81 Rename a file extension


s = new StringBuffer();
ParserDelegator delegator = new ParserDelegator();
// the third parameter is TRUE to ignore charset directive
delegator.parse(in, this, Boolean.TRUE);
}

public void handleText(char[] text, int pos) {


s.append(text);
}

public String getText() {


return s.toString();
}

public static void main (String[] args) {


try {
// the HTML to convert
FileReader in = new FileReader("java−new.html");
Html2Text parser = new Html2Text();
parser.parse(in);
in.close();
System.out.println(parser.getText());
}
catch (Exception e) {
e.printStackTrace();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

6.83 Get the Mime Type from a File


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0487.html

6.83.1 Using javax.activation.MimetypesFileTypeMap

activation.jar is required, it can be downloaded from


http://java.sun.com/products/javabeans/glasgow/jaf.html.

The MimetypesFileMap class is used to map a File to a Mime Type. Mime types supported are
defined in a ressource file inside the activation.jar.

import javax.activation.MimetypesFileTypeMap;
import java.io.File;

class GetMimeType {
public static void main(String args[]) {
File f = new File("gumby.gif");
System.out.println("Mime Type of " + f.getName() + " is " +
new MimetypesFileTypeMap().getContentType(f));
// expected output :
// "Mime Type of gumby.gif is image/gif"
}

6.83 Get the Mime Type from a File


}

The built−in mime−type list is very limited but a mechanism is available to add very easily more
Mime Types/extensions.

The MimetypesFileTypeMap looks in various places in the user's system for MIME types file entries.
When requests are made to search for MIME types in the MimetypesFileTypeMap, it searches
MIME types files in the following order:

1. Programmatically added entries to the MimetypesFileTypeMap instance.


2. The file .mime.types in the user's home directory.
3. The file <java.home>/lib/mime.types.
4. The file or resources named META−INF/mime.types.
5. The file or resource named META−INF/mimetypes.default (usually found only in the
activation.jar file).

This method is interesting when you need to deal with incoming files with the filenames normalized.
The result is very fast because only the extension is used to guess the nature of a given file.

6.83.2 Using java.net.URL

Warning : this method is very slow!.

Like the above method a match is done with the extension. The mapping between the extension
and the mime−type is defined in the file [jre_home]\lib\content−types.properties

import java.net.*;

public class FileUtils{


public static String getMimeType(String fileUrl)
throws java.io.IOException, MalformedURLException
{
String type = null;
URL u = new URL(fileUrl);
URLConnection uc = null;
uc = u.openConnection();
type = uc.getContentType();
return type;
}

public static void main(String args[]) throws Exception {


System.out.println(FileUtils.getMimeType("file://c:/temp/test.TXT"));
// output : text/plain
}
}

6.83.3 Using JMimeMagic

Checking the file extension is not a very strong way to determine the file type. A more robust
solution is possible with the JMimeMagic library. JMimeMagic is a Java library (LGLP licence) that
retrieves file and stream mime types by checking magic headers.

// snippet for JMimeMagic lib


// http://sourceforge.net/projects/jmimemagic/

Magic parser = new Magic() ;

6.83.2 Using java.net.URL


// getMagicMatch accepts Files or byte[],
// which is nice if you want to test streams
MagicMatch match = parser.getMagicMatch(new File("gumby.gif"));
System.out.println(match.getMimeType()) ;

Thanks to Jean−Marc Autexier and sygsix for the tip!

6.83.4 Using mime−util

Another tool is mime−util. This tool can detect using the file extension or the magic header
technique.

// snippet for mime−util lib


// http://sourceforge.net/projects/mime−util

public static final String UNKNOWN_MIME_TYPE="application/x−unknown−mime−type";


...
String mimeType = MimeUtil.getMagicMimeType(file);
if(mimeType == null) mimeType = UNKNOWN_MIME_TYPE;

The nice thing about mime−util is that there is no dependency (with others Apache packages) so it
is very lightweight.

6.83.5 Using Droid

DROID (Digital Record Object Identification) is a software tool to perform automated batch
identification of file formats.

DROID uses internal and external signatures to identify and report the specific file format versions
of digital files. These signatures are stored in an XML signature file, generated from information
recorded in the PRONOM technical registry. New and updated signatures are regularly added to
PRONOM, and DROID can be configured to automatically download updated signature files from
the PRONOM website via web services.

It can be invoked from two interfaces, a Java Swing GUI or a command line interface.

http://droid.sourceforge.net/wiki/index.php/Introduction

6.83.6 Aperture framework

Aperture is an open source library and framework for crawling and indexing information sources
such as file systems, websites and mail boxes.

The Aperture code consists of a number of related but independently usable parts:

• Crawling of information sources: file systems, websites, mail boxes


• MIME type identification
• Full−text and metadata extraction of various file formats
• Opening of crawled resources

For each of these parts, a set of APIs has been developed and a number of implementations is
provided.

http://aperture.wiki.sourceforge.net/Overview

6.83.4 Using mime−util


6.84 Create a compressed (ZIP) file
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0065.html

/*
** a simple ZIP tool
**
** ex. java Zip file.1 file.2 > file.zip
**
*/
import java.io.*;
import java.util.zip.*;

class Zip {
public static void main(String args[]) throws IOException {
byte b[] = new byte[512];
ZipOutputStream zout = new ZipOutputStream(System.out);
for(int i = 0; i < args.length; i ++) {
InputStream in = new FileInputStream(args[i]);
ZipEntry e = new ZipEntry(args[i].replace(File.separatorChar,'/'));
zout.putNextEntry(e);
int len=0;
while((len=in.read(b)) != −1) {
zout.write(b,0,len);
}
zout.closeEntry();
print(e);
}
zout.close();
}

public static void print(ZipEntry e){


PrintStream err = System.err;
err.print("added " + e.getName());
if (e.getMethod() == ZipEntry.DEFLATED) {
long size = e.getSize();
if (size > 0) {
long csize = e.getCompressedSize();
long ratio = ((size−csize)*100) / size;
err.println(" (deflated " + ratio + "%)");
}
else {
err.println(" (deflated 0%)");
}
}
else {
err.println(" (stored 0%)");
}
}
}

NOTE: There no way to directly add or modify an entry to a ZIP file after its creation. To do so, rename the old ZIP to a temporary filename.
Expand the contents of the old ZIP, create the new ZIP, add the original contents plus the new files and delete the old ZIP when done.

6.84 Create a compressed (ZIP) file


6.85 Display compressed (ZIP) file content
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0066.html

/*
** a simple viewZIP tool
**
** ex. java ViewZip file.zip
**
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.text.*;

class ViewZip {
public static void main(String args[]) throws IOException {
InputStream in = new BufferedInputStream(new FileInputStream(args[0]));
ZipInputStream zin = new ZipInputStream(in);
ZipEntry e;
System.err.println("Size\t Date Time Method Ratio Name");
System.err.println("−−−−\t −−−− −−−− −−−−−− −−−−− −−−−");
while((e=zin.getNextEntry())!= null) {
zin.closeEntry();
print(e);
}
zin.close();
}

public static void print(ZipEntry e) {


PrintStream err = System.err;
err.print(e.getSize() + "\t");

DateFormat df = new SimpleDateFormat ("yyyy.mm.dd hh:mm:ss");


Date d = new Date(e.getTime());

err.print(df.format(d) + " ");


if (e.getMethod() == ZipEntry.DEFLATED) {
err.print("deflated ");
long size = e.getSize();
if (size > 0) {
long csize = e.getCompressedSize();
long ratio = ((size−csize)*100) / size;
if (ratio < 10) {
err.write(' ');
}
err.print(ratio + "% ");
}
else {
err.print(" 0% ");
}
}
else {
err.println(" (stored 0 %");
}

err.println(e.getName());
}
}

6.85 Display compressed (ZIP) file content


6.86 Expand the compressed (ZIP) file
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0067.html

/*
** a simple unZIP tool
**
** ex. java UnZip file.zip file1 to unzip file 1 from file.zip
** java UnZip file.zip to unzip file.zip
**
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.text.*;

class UnZip {
public static void main(String args[]) throws IOException {
InputStream in =
new BufferedInputStream(new FileInputStream(args[0]));
ZipInputStream zin = new ZipInputStream(in);
ZipEntry e;

while((e=zin.getNextEntry())!= null) {
if (args.length > 1) {
if (e.getName().equals(args[1])) {
unzip(zin, args[1]);
break;
}
}
unzip(zin, e.getName());
}
zin.close();
}

public static void unzip(ZipInputStream zin, String s)


throws IOException {
System.out.println("unzipping " + s);
FileOutputStream out = new FileOutputStream(s);
byte [] b = new byte[512];
int len = 0;
while ( (len=zin.read(b))!= −1 ) {
out.write(b,0,len);
}
out.close();
}
}

6.87 Emit a beep


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0001.html

There are three ways to emit a beep in Java.


• Use an AU audio file
For Java, AU files need to be created at a sample rate of 8000. Any sample rate beyound that will not work. See also this How−to.

6.86 Expand the compressed (ZIP) file


• Print the ASCII Bell character to the console
public class TestBeep {
public static main(String args[]) {
// ASCII bell
System.out.print("\007");
System.out.flush();
}
}

The buzzer on the motherboard is used.


• Starting with JDK 1.1, use the beep method in the Toolkit
import java.awt.*;
public class Beep {
public static void main(String args[]) {
Toolkit.getDefaultToolkit().beep();
}
}

(Windows) The sound used is determined from the setting found in Control Panel/Sounds and
Devices/Sounds/Sound Scheme/"Default Beep". If no sound file is selected then the beep() will
be a silence.

6.88 Emit a Tone


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0499.html

import javax.sound.sampled.*;

//jdk1.3
public class Tone {
public static float SAMPLE_RATE = 8000f;
public static void sound(int hz, int msecs)
throws LineUnavailableException {
byte[] buf = new byte[1];
AudioFormat af = new AudioFormat(SAMPLE_RATE,8,1,true,false);
SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
sdl.open(af);
sdl.start();
for (int i=0; i<msecs*8; i++) {
double angle = i / (SAMPLE_RATE / hz) * 2.0 * Math.PI;
buf[0] = (byte)(Math.sin(angle) * 110.0);
sdl.write(buf,0,1);
}
sdl.drain();
sdl.stop();
sdl.close();
}

public static void main(String[] args) {


try {

Tone.sound(1000,100);
Tone.sound(100,1000);
Tone.sound(5000,100);
} catch (LineUnavailableException lue) {
System.out.println(lue);
}

6.88 Emit a Tone


}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

6.89 Play an audio file from an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0006.html

With Applet, the getAudioClip method() from the Applet package is used to play sound file. Starting
with JDK1.2, getAudioClip() is now a static method. So it may be possible to use it without an Applet
(i.e. in a regular Java application) with

java.applet.Applet.getAudioClip(URLofMySound);

Note: Since JDK1.2, Java can play WAV directly, see


http://java.sun.com/docs/books/tutorial/sound/playing.html.

Another way is to use the undocumented sun.audio package.

import sun.audio.*;
...
...
AudioPlayer p=AudioPlayer.player;
try{
AudioStream as =
new AudioStream(new FileInputStream("aSound.au"));
p.start(as);
}
catch(IOException err){
err.printStackTrace();
}

To play a sound from a JAR file (the .AU file in the JAR must be accessible via the CLASSPATH of
course!) :

import java.io.*;
import java.net.*;

import sun.audio.*;

public class AppAudio {


public static void main(String args[]) throws Throwable {
InputStream in = AppAudio.class.getResourceAsStream(args[0]);
AudioStream as = new AudioStream(in);
AudioPlayer.player.start(as);
Thread.sleep(5000);
}
}

Since JDK1.3, you have also the javax.sound package, see this HowTo.

6.89 Play an audio file from an application


Written and compiled Réal Gagnon ©2007 real@rgagnon.com
http://www.rgagnon.com

6.89 Play an audio file from an application


7 JDBC
7.1 java−jdbc

7.2 Connect to a database via JDBC−ODBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0107.html

You have to keep in mind that the bridge JDBC−ODBC is only useful in an Application, you can't
use it with JAVA Applet because ODBC requires some DLL on the client machine (forbidden for
security reason).

import java.net.URL;
import java.sql.*;

class JDBCapp {

static Connection theConn;

public static void main (String args[]) {


try {
// connection to an ACCESS MDB
theConn = MyConnection.getConnection();

ResultSet rs;
Statement stmt;
String sql;

sql = "select objet from Email";


stmt = theConn.createStatement();
rs = stmt.executeQuery(sql);

while (rs.next()) {
System.out.println(rs.getString("objet"));
}
rs.close();
stmt.close();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (theConn != null) theConn.close();
}
catch (Exception e) {
}
}

}
}

class MyConnection {
public static Connection getConnection() throws Exception {
Driver d = (Driver)Class.forName

7 JDBC
("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
Connection c = DriverManager.getConnection(
"jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=c:/tech97.mdb"
);
return c;
/*
To use an already defined ODBC Datasource :

String URL = "jdbc:odbc:myDSN";


Connection c = DriverManager.getConnection(URL, "user", "pwd");

*/
}
}

7.3 SELECT data from a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0108.html

Note:the MyConnection class was used to connect to the DB

With a Prepared Statement (only 1 row)

String id = cust_id.getText();
try {
PreparedStatement prepstmt;
boolean found = false;
prepstmt = theConn.prepareStatement
("select custName, CustAddr from tCust where custId = ?");
prepstmt.setString(1, id);

ResultSet rs;
rs = prepstmt.executeQuery();

found = rs.next();
if (found)
System.out.println(rs.getString(1));
else
System.out.println("Customer " + id + " not found!");
prepstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

With a Statement (many rows)

String name = cust_name.getText();


try {
Statement stmt;
String sql;

sql = "select custName from tCust where custName = "


+= "'" + name + "'";
stmt = theConn.createStatement();

ResultSet rs;
rs = stmt.executeQuery();

7.3 SELECT data from a table


while (rs.next()) {
System.out.println(rs.getString("custName"));
}
rs.close();
stmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

You need to be aware to the snippet above contains a SQL Injection vulnerability. String concatentation of this form can only be used if you first
validate the fields to include only alphanumeric characters. Even, then it is generally considered bad practice when prepared statements solve
this problem more cleanly. This is especially when you in a Web application environnement.

Thanks to Lawrence Angrave for the warning.

7.4 INSERT data into a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0109.html

Note:the MyConnection class was used to connect to the DB

Statement stmt;
String sql;
int rows;

sql = "INSERT INTO tCust "


+ "(custId, custName, custAddr) "
+ "VALUES "
+ "('" + custId + "',"
+ "('" + custName + "',"
+ "('" + custAddr + "')";

stmt = theConn.createStatement();
rows = stmt.executeUpdate(sql);
theConn.dbConn.commit();
stmt.close();

You need to be aware to the snippet above contains a SQL Injection vulnerability. String concatentation of this form can only be used if you first
validate the fields to include only alphanumeric characters. Even, then it is generally considered bad practice when prepared statements solve
this problem more cleanly. This is especially when you in a Web application environnement.

Thanks to Lawrence Angrave for the warning.

Before inserting data containing quotes, you may need to double them (so "Real's HowTo" −>
"Real''s HowTo"). You can use the following function to "prepare" your string.
public static String convertString(String source) {
StringBuffer sb = new StringBuffer();

for(int i = 0; i < source.length(); i++){


sb.append(source.charAt(i));
if(source.charAt(i)=='\'') sb.append('\'')
}
return sb.toString();

7.4 INSERT data into a table


}

Or you can use a PreparedStatement to insert data containing QUOTES

PreparedStatement stmt = null;


String sql;
int rows;

try {
sql = "INSERT INTO tCust"
+ "(custName) "
+ "VALUES "
+ "(?)";
stmt = theConn.prepareStatement(sql);
stmt.setString(1, "Name with \" are permitted!");
rows = stmt.executeUpdate();
theConn.commit();
stmt.close();
System.out.println(sql);
}
catch (Exception e){
e.printStackTrace();
}

The character "\" can be difficult to use in an INSERT statement since "\" is considered as an
escape character in Java (and probably by the database also).

stmt.executeUpdate("INSERT INTO mytable VALUES('\\')");

may generate a SQL Exception even if the "\" is escaped for Java because you need to escape it
again for the database. At the end, you need to use "\\\\" to INSERT a simple "\".

stmt.executeUpdate("INSERT INTO mytable VALUES('\\\\')");

7.5 MODIFY data in a table


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0110.html

Note:the MyConnection class was used to connect to the DB

PreparedStatement prepstmt;
try {
prepstmt = theConn.prepareStatement
("UPDATE tCust SET custName = ? "+
" WHERE custId = ?");
prepstmt.setString(1,"Smith");
prepstmt.setString(2, cust_id.getText());
prepstmt.executeUpdate();

theConn.commit();
prepstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

7.5 MODIFY data in a table


7.6 DELETE data in a table
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0111.html

Note:the MyConnection class was used to connect to the DB

PreparedStatement prepstmt;
try {
prepstmt = theConn.prepareStatement
("DELETE FROM tCust "+
" WHERE custId = ?");

prepstmt.setString(1,cust_id.getText());
prepstmt.executeUpdate();

theConn.commit();
prepstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

7.7 Test for an empty ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0116.html

boolean found;
ResultSet rs;
...
// execute the query and then
found = rs.next();
if (found)
System.out.println("Record found");
else
System.out.println("RECORD NOT FOUND");

A nicer way to do the same would be

ResultSet rs;
...
if (rs.next()) {
do {
System.out.println("Record found");
} while (rs.next());
}
else {
System.out.println("Record not found");
}

7.6 DELETE data in a table


7.8 Store and retrieve an object from a table
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0117.html

Assume that we have a table called "Employee", with only one field called "emp" and "long binary"
or "blob" as data type. We want to insert an instance of the class "Employee" into the table
"Employee". The object "Employee" will be serialized into the table "Employee" ( ideally the table
"Employee" should have an index key, something like emp_id, but for the example there is none).

import java.net.URL;
import java.sql.*;
import java.io.*;

class JDBCapp {
static MyConnection theConn;

public static void main (String args[]) {


JDBCapp j = new JDBCapp();
j.connectToDB();
j.insertIntoEmp();
j.selectFromEmp();
}

public void connectToDB() {


theConn = new MyConnection();
theConn.connect("your_db_profile", "username", "password");
}

public void insertIntoEmp() {


Employee employee = new Employee(42,"Real Gagnon", 98000);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(employee);
// serialize the employee object into a byte array
byte[] employeeAsBytes = baos.toByteArray();
PreparedStatement pstmt =
theConn.dbConn.prepareStatement
("INSERT INTO EMPLOYEE (emp) VALUES(?)");
ByteArrayInputStream bais =
new ByteArrayInputStream(employeeAsBytes);
// bind our byte array to the emp column
pstmt.setBinaryStream(1,bais, employeeAsBytes.length);
pstmt.executeUpdate();
theConn.dbConn.commit();
pstmt.close();
}
catch(Exception e) {
e.printStackTrace();
}
}

public void selectFromEmp() {


boolean found;
try {
Statement stmt = theConn.dbConn.createStatement();
ResultSet rs =
stmt.executeQuery("SELECT emp FROM Employe");
// loop through the result set
while (rs.next()) {

7.8 Store and retrieve an object from a table


// fetch the serialized object to a byte array
byte[] st = (byte[])rs.getObject(1);
// or byte[] st = rs.getBytes(1);
// or Blob aBlob = rs.getBlob(1);
// byte[] st = aBlob.getBytes(0, (int) aBlob.length());
ByteArrayInputStream baip =
new ByteArrayInputStream(st);
ObjectInputStream ois =
new ObjectInputStream(baip);
// re−create the object
Employee emp = (Employee)ois.readObject();
// display the result for demonstration
System.out.println(emp.name);
}
stmt.close();
rs.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}

class Employee implements Serializable {


int ID;
String name;
double salary;

public Employee(int ID, String name, double salary) {


this.ID = ID;
this.name = name;
this.salary = salary;
}
}

class MyConnection {
Connection dbConn = null;
void connect(String db, String user, String passw) {
try {
Driver d =
(Driver)Class.forName
("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
String URL = "jdbc:odbc:" + db;
dbConn =
DriverManager.getConnection(URL, user, passw);
}
catch (Exception e) {
e.printStackTrace();
}
}

void disconnect() {
try {
dbConn.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

7.8 Store and retrieve an object from a table


7.9 Retrieve an Image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0118.html

// column is column index in ResultSet containing the image,


// we assume that the type is LONGVARBINARY
Image myImage = null;
InputStream stream = rset.getBinaryStream(column);
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
int a1 = stream.read();
while (a1 >= 0) {
output.write((char)a1);
a1 = stream.read();
}
myImage =
Toolkit.getDefaultToolkit().createImage(output.toByteArray());
output.close();
}
catch(Exception e){}

7.10 Insert an Image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0119.html

File file = new File("myimage.gif");


FileInputStream fis = new FileInputStream(file);
PreparedStatement ps =
conn.prepareStatement("insert into images values (?,?)");
ps.setString(1,file.getName());
ps.setBinaryStream(2,fis,(int)file.length());
ps.executeUpdate();
ps.close();
fis.close();

7.11 Connect to an Oracle database with JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0112.html

Oracle Corporation has released a free 100% JAVA driver. It is available at their Web site. All you
need is to include the required jar in the classpath.

import java.sql.*;

public class TestDBOracle {

public static void main(String[] args)


throws ClassNotFoundException, SQLException
{
Class.forName("oracle.jdbc.driver.OracleDriver");
//
// or

7.9 Retrieve an Image


// DriverManager.registerDriver
// (new oracle.jdbc.driver.OracleDriver());

String url = "jdbc:oracle:thin:@//server.local:1521/prod";


// jdbc:oracle:thin:@//host:port/service
// or
// String url = "jdbc:oracle:thin:@server.local:1521:prodsid";
// jdbc:oracle:thin:@host:port:SID

Connection conn =
DriverManager.getConnection(url,"scott", "tiger");

conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
ResultSet rset =
stmt.executeQuery("select BANNER from SYS.V_$VERSION");
while (rset.next()) {
System.out.println (rset.getString(1));
}
stmt.close();
System.out.println ("Ok.");
}
}

See also this HowTo to connect using the Oracle Connection Pool.

7.12 Connect to Oracle using a connection pool


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0545.html

The Oracle thin jdbc driver (v9.2) makes it very easy to use a connection pool, it's all built in the
OracleDataSource with the implicit connection cache mechanism.

An application turns the implicit connection cache on by invoking


OracleDataSource.setConnectionCachingEnabled(true). After implicit caching is turned on, the first
connection request to the OracleDataSource transparently creates a connection cache.

After you have turned connection caching on, whenever you retrieve a connection through an
OracleDataSource.getConnection(), the JDBC drivers check to see if a connection is available in
the cache.The getConnection() method checks if there are any free physical connections in the
cache that match the specified criteria. If a match is found, a logical connection is returned wrapping
the physical connection. If no physical connection match is found, a new physical connection is
created, wrapped in a logical connection, and returned.

A Connection Pool is a cache of database connections maintained in memory so that the


connections can be reused when the database receives future requests for data. Connection pools
are used to enhance the performance of executing commands on a database. Various parameters
such as number of minimum connections, maximum connections and idle connections can be set to
make sure the connection pool works well according to the environment it is deployed to work in.

In this example, we have a program with several threads. Each thread makes a connection but the
login process is done only once.

First a static class to manage the connection pool.

7.12 Connect to Oracle using a connection pool


import oracle.jdbc.pool.OracleDataSource;
import oracle.jdbc.pool.OracleConnectionCacheManager;

import java.util.Properties;
import java.sql.*;

public class JDBCUtils {


private final static String CACHE_NAME = "MYCACHE";
private static OracleDataSource ods = null;

static {
logger.info("Initialisation du OracleDataSource");
try {
ods = new OracleDataSource();
ods.setURL("jdbc:oracle:thin:@//server.local:1521/prod");
ods.setUser("scott");
ods.setPassword("tiger");
// caching parms
ods.setConnectionCachingEnabled(true);
ods.setConnectionCacheName(CACHE_NAME);
Properties cacheProps = new Properties();
cacheProps.setProperty("MinLimit", "1");
cacheProps.setProperty("MaxLimit", "4");
cacheProps.setProperty("InitialLimit", "1");
cacheProps.setProperty("ConnectionWaitTimeout", "5");
cacheProps.setProperty("ValidateConnection", "true");

ods.setConnectionCacheProperties(cacheProps);

}
catch (SQLException e) {
e.printStackTrace();
}
}

/**
* private constructor for static class
*/
private JDBCUtils() { }

public static Connection getConnection() throws SQLException {


return getConnection("env. unspecified");
}

public static Connection getConnection(String env)


throws SQLException
{
System.out.println("Request connection for " + env);
if (ods == null) {
throw new SQLException("OracleDataSource is null.");
}
return ods.getConnection();
}

public static void closePooledConnections() throws SQLException{


if (ods != null ) {
ods.close();
}
}

public static void listCacheInfos() throws SQLException{


OracleConnectionCacheManager occm =

7.12 Connect to Oracle using a connection pool


OracleConnectionCacheManager.getConnectionCacheManagerInstance();
System.out.println
(occm.getNumberOfAvailableConnections(CACHE_NAME)
+ " connections are available in cache " + CACHE_NAME);
System.out.println
(occm.getNumberOfActiveConnections(CACHE_NAME)
+ " connections are active");

}
}

then the working thread

import java.sql.*;

public class TestDBOraclePool3Thread implements Runnable {

private int noThread = 0;

TestDBOraclePool3Thread(int n) {
noThread = n;
}

public void run() {


System.out.println("Starting Thread " + noThread);
while (true) {
try {
Connection conn =
JDBCUtils.getConnection("env " + noThread);

conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
ResultSet rset =
stmt.executeQuery("select BANNER from SYS.V_$VERSION");
while (rset.next())
System.out.println (rset.getString(1));
stmt.close();
System.out.println ("Ok.");
JDBCUtils.listCacheInfos();
conn.close();

}
catch (SQLException e) {
e.printStatckTrace()
}
finally {
System.out.println ("Sleep... " + noThread);
try {
Thread.sleep(1000);
}
catch(Exception e) { }
}
}
}

and finally, the main class

import java.net.URL;
import java.sql.*;

7.12 Connect to Oracle using a connection pool


public class TestDBOraclePool3 {

public static void main(String[] args) throws SQLException {


new Thread( new TestDBOraclePool3Thread(1)).start();
new Thread( new TestDBOraclePool3Thread(2)).start();
new Thread( new TestDBOraclePool3Thread(3)).start();
new Thread( new TestDBOraclePool3Thread(4)).start();
new Thread( new TestDBOraclePool3Thread(5)).start();
new Thread( new TestDBOraclePool3Thread(6)).start();
new Thread( new TestDBOraclePool3Thread(7)).start();
}
}

7.13 Get JDBC driver for major database vendors


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0113.html

JDBC vendors list


Intersolv plugin to access ODBC database through a browser

7.14 Handle dates


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0114.html

To get the current date in SQL format.

java.util.Date today =
new java.util.Date();
java.sql.Date sqlToday =
new java.sql.Date(today.getTime());

For Timestamp, it's the same idea

java.util.Date today =
new java.util.Date();
java.sql.Timestamp now =
new java.sql.Timestamp(today.getTime());

To use a Date, Time or Timestamp in a query, you can use JDBC escape codes.

Date {d 'yyyy−mm−dd'}
Time {t {'hh:mm:ss'}
Timestamp {ts `yyyy−mm−dd hh:mm:ss.f . . .'}
note: the .f .... is optional

For example, a Statement with a Date will look like this

java.util.Date today =
new java.util.Date();
java.sql.Date sqlToday =
new java.sql.Date(today.getTime());

7.13 Get JDBC driver for major database vendors


String query =
"select * from cust where purchase_date <{ d '"
+ sqlDate.toString() + "' }");

With a PreparedStatement, you don't need JDBC escape codes, the JDBC driver will do the job for
you.

java.util.Date today =
new java.util.Date();
java.sql.Date sqlToday =
new java.sql.Date(today.getTime());

PreparedStatement p = theConn.prepareStatement
("select * from cust where purchase_date <?");
p.setDate(1, sqlToday);
ResultSet rs = p.executeQuery();

To INSERT

PreparedStatement p = theConn.prepareStatement
("insert into TableWithADateColumn values(?)");
p.setDate(1, sqlToday);
p.executeUpdate();

or

p.executeUpdate
("insert into TableWithADateColumn values( { d '1999−12−31' } )");

One thing to remember when using java.sql.date is (according to the javadoc) :

To conform with the definition of SQL DATE, the millisecond values


wrapped by a java.sql.Date instance must be 'normalized' by setting
the hours, minutes, seconds, and milliseconds to zero in the particular
time zone with which the instance is associated.

7.15 Call a stored procedure


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0115.html

We assume that the Connection is known as :

Connection conn;

then

String query = "begin thePackage.theProcedure(?,?,?); end;";


CallableStatement cs = conn.prepareCall(query);
cs.setString(1, "string parameter"); // #1 is INPUT
cs.setInt(2, 1); // #2 is INPUT
cs.registerOutParameter(2, Types.INTEGER); // and OUTPUT
cs.registerOutParameter(3, Types.INTEGER); // #3 is OUTPUT
cs.execute();

int output_parm2 = cs.getInt(2); // get the result from OUTPUT #2

7.15 Call a stored procedure


int output_parm3 = cs.getInt(3); // get the result from OUTPUT #3

7.16 Stored procedure with Input/Output parms and a ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0120.html

Thanks to T. Guirado for the tips.

public static int storedProcWithResultSet (String parms) throws Exception


// Stored procedure to be called.
CallableStatement cs = conn.prepareCall
("{? = call mypackage.p_astoreproc (?,?,?,?,?,?,?)}");

// register input parameters


cs.setString(2, "");
cs.setString(3, "");
cs.setString(4, parms);
// regsiter ouput parameters
cs.registerOutParameter(5, java.sql.Types.CHAR);
cs.registerOutParameter(6, java.sql.Types.CHAR);
cs.registerOutParameter(7, java.sql.Types.CHAR);

// Procedure execution
ResultSet rs = cs.executeQuery();

// Note that you need to retrieve the ResultSet _before_ retrieving


// OUTPUT parameters.
if ( rs == null)
System.out.println( "No resultSet!");
else {
// To retrieve columns info.
ResultSetMetaData rsmd = rs.getMetaData();
int nbCol = rsmd.getColumnCount();

int i = 0;
int j = 1;

Vector vResSet = new Vector();


while (rs.next ()) {
System.out.println( "Record " + (i+1));
// putting the ResultSet columns in a vector
for ( j = 1; j <= nbCol ; j++){
vResSet.insertElementAt(rs.getString(j), 0);
vResSet.addElement(rs.getString(j));
}

// Reading vector to print ResultSet data


for ( int k = 0 ; k < nbColonnes ; k++ ) {
if ( vResSet.elementAt(k) != null)
System.out.println( vResSet.elementAt(k).toString());
else
System.out.println( "Column " + (k+1) + " Null");
}
i++;
}
}

// Retrieving Strored Procedure OUTPUT parameters


System.out.println( "return code of Stored procedure = : "

7.16 Stored procedure with Input/Output parms and a ResultSet


+ cs.getInt(1));

// Retrieving OUTPUT parameters


for ( int i = 5 ; i <= 7; i ++)
System.out.println( "parameter " + i + " : "
+ cs.getString(i));

return cs.getInt(1);
}

7.17 Fix incomplete field returned by the ResultSet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0121.html

Some JDBC driver have limit about how big returned records can be.

First use the getMaxRowSize() and doesMaxRowSizeIncludeBlobs() from the DatabaseMetaData


class to see what the maximum supported by the driver. Then getMaxFieldSize() and
setMaxFieldSize() from the Statement class to adjust if necessary the current maximum value.

7.18 Get a record count with the SQL Statement


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0292.html

Statement s = con.createStatement();
ResultSet r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM MyTable");
r.next();
int ResultCount = r.getInt("rowcount") ;
r.close() ;

JDBC 2.0 provides a way to retrieve a rowcount from a ResultSet without having to scan through all
the rows or issue a separate SELECT COUNT(*).

Statement s =
conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet r =
s.executeQuery("SELECT * FROM employee WHERE id_emp LIKE '1%'");
r.last();
count = r.getRow();
r.beforeFirst();

7.19 Transfer a ResultSet to a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0309.html

// TableModel definition
String[] tableColumnsName = {"col 1","col 2","col 3"};
DefaultTableModel aModel = (DefaultTableModel) aTable.getModel();

7.17 Fix incomplete field returned by the ResultSet


aModel.setColumnIdentifiers(tableColumnsName);

// the query
ResultSet rs =
statement.executeQuery("select col1,col2,col3 from mytable");

// Loop through the ResultSet and transfer in the Model


java.sql.ResultSetMetaData rsmd = rs.getMetaData();
int colNo = rsmd.getColumnCount();
while(rs.next()){
Object[] objects = new Object[colNo];
// tanks to umit ozkan for the bug fix!
for(int i=0;i<colNo;i++){
objects[i]=rs.getObject(i+1);
}
aModel.addRow(objects);
}
aTable.setModel(aModel);

7.20 List tables in a database


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0317.html

import java.net.URL;
import java.sql.*;

class JDBCapp {
static MyConnection theConn;

public static void main (String args[]) {


new JDBCapp().doit();
}

public void doit() {


theConn = new MyConnection();
theConn.connect("myDSN", "user", "password");
try {
ResultSet rs1;
ResultSet rs2;
String ss, tblnames = "";
DatabaseMetaData dmd = theConn.dbConn.getMetaData();
rs1 = dmd.getSchemas();
while(rs1.next()) {
ss = rs1.getString(1);
rs2 = dmd.getTables(null,ss, "%",null);
while(rs2.next())
tblnames += rs2.getString(3) + " " + rs2.getString(4) + "\n\r";
}
System.out.println("Tables :");
System.out.println(tblnames);
}
catch (Exception e) { e.printStackTrace(); }
}
}

class MyConnection {
Connection dbConn = null;
void connect(String db, String user, String passw) {
try {

7.20 List tables in a database


Driver d =
(Driver)Class.forName
("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
// URL corresponding to the ODBC DSN
String URL = "jdbc:odbc:" + db;
// DB logon
dbConn =
DriverManager.getConnection(URL, user, passw);
}
catch (Exception e) {
e.printStackTrace();
}
}

void disconnect() {
try {
dbConn.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

7.21 Display ResultSet data in an HTML Table in Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0378.html

private int dumpData(java.sql.ResultSet rs, java.io.PrintWriter out)


throws Exception {
int rowCount = 0;

out.println("<P ALIGN='center'><TABLE BORDER=1>");


ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// table header
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TH>" + rsmd.getColumnLabel(i + 1) + "</TH>");
}
out.println("</TR>");
// the data
while (rs.next()) {
rowCount++;
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TD>" + rs.getString(i + 1) + "</TD>");
}
out.println("</TR>");
}
out.println("</TABLE></P>");
return rowCount;
}

7.21 Display ResultSet data in an HTML Table in Servlet


7.22 Detect SQL errors or warnings
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0331.html

Warning

When the database server executes an SQL statement successfully, but encounters a warning
condition, it sets the SQLSTATE class field to "01". The subclass code then indicates the cause of
the warning. This warning can be an ANSI or X/Open warning message (if supported by the driver)
the subclass code in the range "000" to "006". Also the driver can provide is own warning codes in
the "01" class.

Class Subclass
01 000 Success with warning

01 002 Disconnect error−transaction rolled back

01 003 Null value eliminated in set function

01 004 String data, right truncation

01 005 Insufficient item descriptor areas

01 006 Privilege not revoked

01 007 PRIVILEGE NOT GRANTED

The JDK API doc reveals that "The SQLWarning class provides information on a database access
warnings. Warnings are silently chained to the object whose method caused it to be reported". So
after DB operation, you ask the Connection object if there are any warnings. Depending on the
vendor driver, informations (not only Warnings) can be found in the SQLWarning object.

dbConn = DriverManager.getConnection
("jdbc:odbc:YourDatabaseName","username","password");
SQLWarning w = dbConn.getWarnings();
// If a SQLWarning object was returned by the
// Connection object, the warning messages are displayed.
// You may have multiple warnings chained together
if (w != null) {
System.out.println ("\n *** SQL Warning ***\n");
while (w != null) {
System.out.println ("Message: " + w.getMessage ());
System.out.println ("SQLState: " + w.getSQLState ());
System.out.println ("VendorCode: " + w.getErrorCode ());
System.out.println ("");
w = w.getNextWarning ();
}
}
}

Error

When an error occurs, a SQLException is thrown. You can interrogate the SQLException object to
know more details about the actual error. Note that SQLException can be chained. The

7.22 Detect SQL errors or warnings


SQLException object contains :

1. A string describing the error. This is used as the Java Exception message, available via the
getMessage method.
2. A "SQLState" string, which follows the XOPEN SQLState conventions.
3. An integer error code that is specific to each vendor.

try {
// ... some SQL operations
}
catch (SQLException ex) {
// SQLException occured.
// There could be multiple error objects chained together
System.out.out.println ("*** SQLException caught ***");

while (ex != null) {


System.out.println ("SQLState: " + ex.getSQLState () + "");
System.out.println ("Message: " + ex.getMessage() + "");
System.out.println ("Vendor ErrorCode: " + ex.getErrorCode() + "");
ex = ex.getNextException();
System.out.println("");
}
}
catch (java.lang.Exception ex) {
// Some other type of exception occurred
System.out.println("*** Exception caught ***");
System.out.println(ex.getMessage()+ "");
}
finally {
// Close the database connection.
try {
if (con != null) con.close();
}
catch (SQLException ignored) {
//do nothing
}
}

Check your DBMS manual for a full list of supported SQLState.

7.23 Using DSN−less connection


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0345.html

This HowTo seems broken, if anyone know what is problem, let me know!, Thanks
(works on some Windows installation while on other it does not!)

It is possible to connect to a database without a User or System DSN. This is useful if you don't
have easy access to a client registry to define the required DSN. Not all JDBC driver support this
feature.

// For Access
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String myDB =
"jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/data/month.MDB";
DBConn = DriverManager.getConnection(myDB,"","");

7.23 Using DSN−less connection


// For Excel
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
String myDB =
"jdbc:odbc:Driver={Microsoft Excel Driver (*.xls)};DBQ=c:/data/month.xls;"
+ "DriverID=22;READONLY=false";
DriverManager.getConnection(myDB,"","");

Thanks to R. Hibberd for the tip.

7.24 Read data from Excel worksheet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0362.html

Let's assume we have a worksheet like this

LASTNAME FIRSTNAME ID
Reiser Beth 102
Ricci Dylan 111
Gugliuzza Brian 116

To access this data, we can use the JDBC−ODBC bridge. Microsoft provides an ODBC driver to
Excel worksheet.

Define an ODBC datasource (system DSN) named "employee_xls" that points to that worksheet.

example 1

import java.io.*;
import java.net.*;
import java.sql.*;
import java.util.*;

public class EmployeeReader{


public static final String DRIVER_NAME =
"sun.jdbc.odbc.JdbcOdbcDriver";
public static final String DATABASE_URL = "jdbc:odbc:employee_xls";

public static void main(String[] args)


throws ClassNotFoundException, SQLException{
Class.forName(DRIVER_NAME);
Connection con = null;
try {
con = DriverManager.getConnection(DATABASE_URL);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery
("select lastname, firstname, id from [Sheet1$]");
while (rs.next()) {
String lname = rs.getString(1);
String fname = rs.getString(2);
int id = rs.getInt(3);

System.out.println(fname + " " + lname + " id : " + id);


}
rs.close();
stmt.close();
}

7.24 Read data from Excel worksheet


finally {
if (con != null)
con.close();
}
}
}

example 2

import java.io.*;
import java.sql.*;

public class EmployeeReader{


public static void main(String[] args){
Connection connection = null;
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection( "jdbc:odbc:employee_xls" );
Statement st = con.createStatement();
ResultSet rs = st.executeQuery( "Select * from [Sheet1$]" );

ResultSetMetaData rsmd = rs.getMetaData();


int numberOfColumns = rsmd.getColumnCount();

System.out.println ( "No of cols "+numberOfColumns );

while (rs.next()) {
for (int i = 1; i <= numberOfColumns; i++) {
if (i > 1) System.out.print(", ");
String columnValue = rs.getString(i);
System.out.print(columnValue);
}
System.out.println("");
}
rs.close();
st.close();
}
catch(Exception ex) {
System.err.print("Exception: ");
System.err.println(ex.getMessage());
}
finally {
con.close();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

7.25 Handle Excel files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0516.html

There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about

7.25 Handle Excel files


OpenSource (and free) solutions.

7.26 JDBC−ODBC Excel driver


This solution lets you access your Excel worksheet with SQL SELECT statement. The required
ODBC driver is included in a regular Windows installation and the JDBC−ODBC bridge is used to
access the Excel DSN.

See this HowTo for an example.

7.27 JExcel
Java Excel API is a java API enabling developers to read, write, and modify Excel spreadsheets
dynamically. Any operating system which can run a Java virtual machine can both process and
deliver Excel spreadsheets. One nice thing about JExcelApi is that it has no dependencies on any
third party libraries.

Example : output an Excel file from a Servlet

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Sample extends HttpServlet {


public void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream out = null;
try {
response.setContentType("application/vnd.ms−excel");
response.setHeader
("Content−Disposition", "attachment; filename=sampleName.xls");
WritableWorkbook w =
Workbook.createWorkbook(response.getOutputStream());
WritableSheet s = w.createSheet("Demo", 0);
s.addCell(new Label(0, 0, "Hello World"));
w.write();
w.close();
}
catch (Exception e){
throw new ServletException("Exception in Excel Sample Servlet", e);
}
finally{
if (out != null)
out.close();
}
}
}

7.26 JDBC−ODBC Excel driver


See http://jexcelapi.sourceforge.net/

7.28 POI
The POI project consists of APIs for manipulating various file formats based upon Microsoft's OLE 2
Compound Document format using pure Java. POI is your Java Excel solution as well as your Java
Word solution.

HSSF is the POI Project's pure Java implementation of the Excel '97(−2002) file format and it
provides a way to read spreadsheets create, modify, read and write XLS spreadsheets.

Since it's Jakarta project, POI has a dependencies with other JARs (commons,log4j,etc...).

Example : create an Excel file

HSSFWorkbook wb = new HSSFWorkbook();


HSSFSheet sheet = wb.createSheet("new sheet");

HSSFRow row = sheet.createRow((short)0);


row.createCell((short)0).setCellValue("HelloWorld");

FileOutputStream fileOut = new FileOutputStream("workbook.xls");


wb.write(fileOut);
fileOut.close();

The name was originally an acronym for "Poor Obfuscation Implementation" (ref: Wikipedia).

See http://jakarta.apache.org/poi/

7.29 JXLS
jXLS is a project that allows creation of extremely complex Excel reports just in several lines of
code. It is based on Jakarta POI.

With jXLS, all you need is to create XLS template file with all required formatting, formulas etc using
specific notation to indicate placement of data and then write a couple lines of code to invoke jXLS
engine passing XLS template and the exported data as parameters.

Example :
The XLS Template

Employees
Name Age Payment Bonus
${employee.name} ${employee.age} ${employee.payment} ${employee.bonus}
$[SUM(@employee.payment@)]

with the code

Collection staff = new HashSet();


staff.add(new Employee("Derek", 35, 3000, 0.30));
staff.add(new Employee("Elsa", 28, 1500, 0.15));
Map beans = new HashMap();
beans.put("employee", staff);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS(templateFileName, beans, destFileName);

7.28 POI
gives the result

Employees
Name Age Payment Bonus
Derek 35 3000 30,00%
Else 28 1500 15,00%
4500

See http://jxls.sourceforge.net/

7.30 xlSQL
xlSQL is a JDBC Driver for Excel and CSV data sources. Documents can be read and written with
SQL as if they were tables in a database.

You can export XLS to XML or SQL INSERT statements. xlSQL includes its own "zero−admin"
mySQL database. The documentation is minimal at this time.

See http://xlsql.sourceforge.net/

7.31 JCOM
JCOM is a Java to COM bridge library. With JCOM you can call a COM object from Java as if it
were a Java object without having to deal with the internals of JNI. The documentation is minimal (in
Japanese!).

Example :

import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
import java.io.File;
import java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
System.out.println("EXCEL startup...");
// if already started, open new window
ExcelApplication excel = new ExcelApplication(rm);
excel.Visible(true);
// display any information
System.out.println("Version="+excel.Version());
System.out.println("UserName="+excel.UserName());
System.out.println("Caption="+excel.Caption());
System.out.println("Value="+excel.Value());

ExcelWorkbooks xlBooks = excel.Workbooks();


ExcelWorkbook xlBook = xlBooks.Add(); // create new book

// enumurate all files


System.out.println
("set infomation of files in current directory to cell ...");
ExcelWorksheets xlSheets = xlBook.Worksheets();
ExcelWorksheet xlSheet = xlSheets.Item(1);
ExcelRange xlRange = xlSheet.Cells();

7.30 xlSQL
xlRange.Item(1,1).Value("filename" );
xlRange.Item(2,1).Value("size" );
xlRange.Item(3,1).Value("last modified time");
xlRange.Item(4,1).Value("is directory");
xlRange.Item(5,1).Value("is file");
xlRange.Item(6,1).Value("can read");
xlRange.Item(7,1).Value("can write");

File path = new File("./");


String[] filenames = path.list();
for(int i=0; i<filenames.length; i++) {
File file = new File(filenames[i]);
System.out.println(file);
xlRange.Item(1,i+2).Value( file.getName() );
xlRange.Item(2,i+2).Value( (int)file.length() );
xlRange.Item(3,i+2).Value( new Date(file.lastModified()) );
xlRange.Item(4,i+2).Value( file.isDirectory()?"Yes":"No" );
xlRange.Item(5,i+2).Value( file.isFile()?"Yes":"No" );
xlRange.Item(6,i+2).Value( file.canRead()?"Yes":"No" );
xlRange.Item(7,i+2).Value( file.canWrite()?"Yes":"No" );
}
String expression = "=Sum(B2:B"+(filenames.length+1)+")";
System.out.println
("embed equation, calculate sum of filesize: "+expression);
xlRange.Item(1,filenames.length+2).Value("sum");
xlRange.Item(2,filenames.length+2).Formula(expression);
xlRange.Columns().AutoFit(); // fit columns

// comment out, if print out.


// output default printer.
// System.out.println("print out...");
// xlSheet.PrintOut();

// comment out, if book save to file.


// if no path, save to(My Documents)
// System.out.println
// ("save to file... (My Documents)\\testExcel.xls");
// xlBook.SaveAs("testExcel.xls");

xlBook.Close(false,null,false);
excel.Quit();

System.out.println("thank you .");


}
catch(Exception e) { e.printStackTrace(); }
finally { rm.release(); }
}
}

See http://sourceforge.net/projects/jcom

See also this HowTo for an alternative package to access a COM package from Java.

7.32 OpenXLS Java Spreadsheet SDK


OpenXLS claims that it has the best compatibility with complex Excel files and able to handle any
kind of Excel file out there without corrupting it. This open source effort is the result of over 6 years
of development into it.

See http://www.extentech.com/estore/product_detail.jsp?product_group_id=228

7.32 OpenXLS Java Spreadsheet SDK


Example (extract 3 images from a workbook, create a new workbook with them) :

doit("testImages.xls","Sheet1");

...

void doit(String finpath, String sheetname){


System.out.println("Begin parsing: " + workingdir + finpath);
WorkBookHandle tbo = new WorkBookHandle(workingdir + finpath);

try{
sheet = tbo.getWorkSheet(sheetname);
// read images from sheet 1 −− .gif, .png, .jpg
ImageHandle[] extracted = sheet.getImages();
// extract and output images
for(int t=0;t<extracted.length;t++) {
System.out.println("Successfully extracted: "
+ workingdir + "testImageOut_"
+ extracted[t].getName()+"."
+extracted[t].getType());
FileOutputStream outimg = new FileOutputStream
(workingdir + extracted[t].getName()+"."
+extracted[t].getType());
extracted[t].write(outimg);
outimg.flush();
outimg.close();
}

tbo = new WorkBookHandle();


sheet = tbo.getWorkSheet("Sheet1");
CellHandle a1 = sheet.add
("New workbook with 3 images: a gif, a jpg, and a png", "A1");

// get gif image input stream


FileInputStream fin = new FileInputStream
(workingdir + "testImages.gif");

// add to sheet
ImageHandle giffy = new ImageHandle(fin, sheet);

// set picture size and location in sheet


giffy.setBounds(100, 100, 400, 200);
giffy.setName("giffy");
sheet.insertImage(giffy);

// add to sheet
for(int x=0;x<100;x++) {
fin = new FileInputStream(workingdir + "testImages.png");
ImageHandle jpgy = new ImageHandle(fin, sheet);
jpgy.setName("heart" + x);
// set the random x/y coords of picture
int ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setX(100 + ix);
ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setY(100 + ix);
sheet.insertImage(jpgy);
}
// get png image input stream
fin = new FileInputStream(workingdir + "testImages.jpg");
// add to sheet
ImageHandle pngy = new ImageHandle(fin, sheet);
// set just the x/y coords of picture
pngy.setX(10);

7.32 OpenXLS Java Spreadsheet SDK


pngy.setY(200);
sheet.insertImage(pngy);
}
catch(Exception e){
System.err.println("testImages failed: " + e.toString());
}
testWrite(tbo, workingdir + "testImagesOut.xls");
WorkBookHandle newbook = new WorkBookHandle
(workingdir + "testImagesOut.xls",0);
System.out.println("Successfully read: " + newbook);
}

public void testWrite(WorkBookHandle b, String fout){


try{
java.io.File f = new java.io.File(fout);
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bbout = new BufferedOutputStream(fos);
bbout.write(b.getBytes());
bbout.flush();
fos.close();
}
catch (java.io.IOException e){
System.err.println("IOException in Tester. "+e);
}
}

See also this HowTo for a way to create a simple XLS without any additional library.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

7.33 Specify a CharSet when connecting to a DBMS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0371.html

Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) ;

// setup the properties


java.util.Properties prop = new java.util.Properties();
prop.put("charSet", "iso−8859−7"); // for example...
prop.put("user", username);
prop.put("password", password);

// Connect to the database


con = DriverManager.getConnection(url, prop);

7.34 Get current date using JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0383.html

With most DBMS, JDBC function escape sequence can be used :

7.33 Specify a CharSet when connecting to a DBMS


SELECT {fn curdate() } for current date
SELECT {fn curtime() } for current hour
SELECT {fn now() } for current date and hour

for Oracle, you add the from dual

SELECT {fn curdate() } FROM dual for current date


SELECT {fn curtime() } FROM dual for current hour
SELECT {fn now() } FROM dual for current date and hour

Example :

// for Oracle
String sql =
"select {fn dayname ({fn now()})}," +
" {d '1997−05−24'}, " +
" {t '10:30:29' }, " +
" {ts '1997−05−24 10:30:29.123'}" +
" from dual" ;

ResultSet rs = stmt.executeQuery(sql);

while (rs.next())
System.out.println("results: " + rs.getString(1) +
"\n " + rs.getString(2) +
"\n " + rs.getString(3) +
"\n " + rs.getString(4) );

7.35 Enable JDBC logging


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0411.html

[JDK1.2]

Take the following program.

import java.net.URL;
import java.sql.*;

class JDBCapp {
static MyConnection theConn;

public static void main (String args[]) {


new JDBCapp().doit();
}

public void doit() {


theConn = new MyConnection();
theConn.connect("EAS Demo DB V3", "dba", "sql");

PreparedStatement prepstmt;
try {
prepstmt = theConn.dbConn.prepareStatement
("SELECT emp_id FROM employee" );
prepstmt.execute();
prepstmt.close();
}

7.35 Enable JDBC logging


catch (Exception e) { e.printStackTrace(); }
theConn.disconnect();
}
}

class MyConnection {
Connection dbConn = null;
void connect(String db, String user, String passw) {
try {
Driver d =
(Driver)Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
String URL = "jdbc:odbc:" + db;
dbConn = DriverManager.getConnection(URL, user, passw);
java.io.PrintWriter w =
new java.io.PrintWriter
(new java.io.OutputStreamWriter(System.out));
DriverManager.setLogWriter(w);
}
catch (Exception e) {
e.printStackTrace();
}
}

void disconnect() {
try {
dbConn.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

And the output at the console will look like this :

*Connection.prepareStatement (SELECT emp_id FROM employee)


Allocating Statement Handle (SQLAllocStmt), hDbc=185334988
hStmt=184290392
Setting statement option (SQLSetStmtOption), hStmt=184290392,
Setting statement option (SQLSetStmtOption), hStmt=184290392,
Preparing (SQLPrepare), szSqlStr=SELECT emp_id FROM employee
Number of parameter markers (SQLNumParams), hStmt=184290392
value=0
Registering Statement sun.jdbc.odbc.JdbcOdbcPreparedStatement@19ee1ac
*PreparedStatement.execute
Free statement (SQLFreeStmt), hStmt=184290392, fOption=0
Executing (SQLExecute), hStmt=184290392
Number of result columns (SQLNumResultCols), hStmt=184290392
value=1
*PreparedStatement.close
Free statement (SQLFreeStmt), hStmt=184290392, fOption=1
deregistering Statement sun.jdbc.odbc.JdbcOdbcPreparedStatement@19ee1ac
*Connection.close
0 Statement(s) to close
Disconnecting (SQLDisconnect), hDbc=185334988
Closing connection (SQLFreeConnect), hDbc=185334988
Closing environment (SQLFreeEnv), hEnv=185334828

7.35 Enable JDBC logging


7.36 Detect if a table exists
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0485.html

Connection c = ...
DatabaseMetaData dbm = c.getMetaData();
// check if "employee" table is there
ResultSet tables = dbm.getTables(null, null, "employee", null);
if (rs.next()) {
// Table exists
}
else {
// Table does not exist
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

7.37 Convert a ResultSet to XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0511.html

import java.sql.Connection;
import java.sql.Statement;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

class JDBCapp {

static Connection con;

public static void main (String args[]) {


ResultSet rs = null;
Statement stmt = null;
String sql;

try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element results = doc.createElement("Results");
doc.appendChild(results);

7.36 Detect if a table exists


// connection to an ACCESS MDB
con = AccessCon.getConnection();

sql = "select objet from Email";


stmt = con.createStatement();
rs = stmt.executeQuery(sql);

ResultSetMetaData rsmd = rs.getMetaData();


int colCount = rsmd.getColumnCount();

while (rs.next()) {
Element row = doc.createElement("Row");
results.appendChild(row);
for (int ii = 1; ii <= colCount; ii++) {
String columnName = rsmd.getColumnName(ii);
Object value = rs.getObject(ii);
Element node = doc.createElement(columnName);
node.appendChild(doc.createTextNode(value.toString()));
row.appendChild(node);
}
}

System.out.println(getDocumentAsXml(doc));

}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (con != null) con.close();
if (stmt != null) stmt.close();
if (rs != null) rs.close();
}
catch (Exception e) {
}
}
}

public static String getDocumentAsXml(Document doc)


throws TransformerConfigurationException, TransformerException {
DOMSource domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
return sw.toString();
}
}

class AccessCon {
public static Connection getConnection() throws Exception {
Driver d = (Driver)Class.forName

7.36 Detect if a table exists


("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
Connection c = DriverManager.getConnection
("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=c:/tech97.mdb");
return c;
/*
To use an already defined ODBC Datasource :

String URL = "jdbc:odbc:myDSN";


Connection c = DriverManager.getConnection(URL, "user", "pwd");

*/
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

7.38 Escape special character in a LIKE clause


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0554.html

Your JDBC driver may support the {escape 'escape character'} syntax for using LIKE clause
wildcards as literals. The escape sequence must be at the end of the SQL statement.

Searching for "one_word"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE value LIKE 'one/_word' {escape '/'}");

Searching for strings ending with "one%word"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE value LIKE '%one/%word' {escape '/'} ");

Find all rows in which a begins with the character "%"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE value LIKE '$%%' {escape '$'}");

Find all rows in which a ends with the character "_"

st = con.createStatement();
rs = st.executeQuery
("SELECT value FROM vendors WHERE a LIKE '%=_' {escape '='}");

7.38 Escape special character in a LIKE clause


7.39 Insert the current date
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0567.html

It's good idea to use the JDBC escape function instead of using a specific DBMS function. This way,
your code will be portable.

sql = "INSERT INTO CUSTOMERS VALUES("


+ "'" + custName + "'" + ","
+ "'" + custPhone + "'" + ","
+ " {fn now() } )";

7.40 Log the SQL Statements


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0602.html

7.41 Plain JDBC Logging


See this HowTo.

7.42 P6Spy
P6Spy is an open source framework for applications that intercept and optionally modify database
statements.

The log file format is

current time|execution time|category|statement SQL String|effective SQL string

P6Spy is especially useful with an application server.

Download at http://p6spy.com/

7.43 Proxool
Proxool is a Java connection pool.

It provides really nice logging facilities with the SQL statement and the running time.

Download at http://proxool.sourceforge.net/

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

7.39 Insert the current date


8 JNI
8.1 java−jni

8.2 Use native code through JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0283.html

• With MSVC6, create a new Win32 DLL project (simple) and call it javahowto.
• In the same directory create a java source called JavaHowTo.java
class JavaHowTo {
public native String sayHello();
static {
System.loadLibrary("javahowto");
}
}
• Compile the Java program and use javah utility to generate the JavaHowTo.h header file.
javah −jni JavaHowTo
• In MSVC6, add the JavaHowTo.h in your project header files
• In the Tools − Options menu, set the include directories to include the Java JNI headers
files. They are located in [jdk dir]\include and [jdk dir]\include\win32 directories
• In the javahowto.cpp source, add
#include "JavaHowTo.h"

JNIEXPORT jstring JNICALL Java_JavaHowTo_sayHello


(JNIEnv *env, jobject obj) {
return env−>NewStringUTF("Hello world");
}
• Select the Release configuration and build the project.
• Copy the javahowto.dll in the same directory as the java program.
• Create this new java program
public class JNIJavaHowTo {
public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
System.out.println(jht.sayHello());
}
}
• Compile and execute.

8.3 Pass a string to/from Java to/from C


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0284.html

To Java from C (as seen from the previous How−to) :

#include "JavaHowTo.h"

JNIEXPORT jstring JNICALL Java_JavaHowTo_sayHello


(JNIEnv *env, jobject obj) {

8 JNI
return env−>NewStringUTF("Hello world");
}

From Java to C : Suppose we have a Java Class

public class MyClass {


public String sayHello(){
return "Hello world From Java";
}
}

then from C, we want to call the Java sayHello() method which returns a String :

JNIEXPORT void JNICALL Java_JavaHowTo_sayHello


(JNIEnv *env, jobject obj) {
const char *str;

jclass myclass_class =(jclass) env−>NewGlobalRef


(env−>FindClass ("MyClass"));

// we need the MyClass constructor


jmethodID constructorID = env−>GetMethodID
(myclass_class, "", "()V");

// and the sayHello() method


jmethodID methodID = env−>GetMethodID
(myclass_class, "sayHello", "()Ljava/lang/String;");

// instanciate a MyClass object


jobject myclass_object = env−>NewObject
(myclass_class, constructorID);

// call the sayHello() method


jstring s = (jstring) env−>CallObjectMethod
(myclass_object, methodID);

// convert the Java String to use it in C


str = env−>GetStringUTFChars(s, 0);
printf("%s" , str);
env−>ReleaseStringUTFChars(s, str);
}

The Java JNI wrapper would be

class JavaHowTo {
public native void sayHello();
static {
System.loadLibrary("javahowto");
}
}

And finally, to use it

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
jht.sayHello();
}
}

8 JNI
8.4 Set the computer clock
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0285.html

Define the following prototype in the header file

JNIEXPORT void JNICALL Java_JavaHowTo_setSystemTime


(JNIEnv *, jobject, jshort, jshort);

the JNI function

JNIEXPORT void JNICALL Java_JavaHowTo_setSystemTime


(JNIEnv *env, jobject obj, jshort hour, jshort minutes) {

SYSTEMTIME st;

GetLocalTime(
st.wHour = hour;
st.wMinute = minutes;
SetLocalTime(
}

The Java JNI wrapper would be

class JavaHowTo {
public native void setSystemTime( short hour, short minutes);
static {
System.loadLibrary("javahowto");
}
}

And finally, to use it

public class JNIJavaHowTo {


public static void main(String[] args) {
short hour = 10;
short minutes = 21;

// this example will set the system at 10h21 using the Windows API
// SetLocalTime.

JavaHowTo jht = new JavaHowTo();


// set the time at 10h21
jht.setSystemTime(hour, minutes);
}
}

8.5 Determine the signature of a method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0286.html

Before calling a Java object's method from JNI, we need its signature. For example, the method

long myMethod (int n, String s, int[] arr);

8.4 Set the computer clock


is seen from JNI with the signature

(ILJAVA/LANG/STRING;[I)J

There are two parts to the signature. The first part is enclosed within the parentheses and
represents the method's arguments. The second portion follows the closing parenthesis and
represents the return type. The mapping between the Java type and C type is

Type Chararacter
boolean Z
byte B
char C
double D
float F
int I
long J
object L
short S
void V
array [

Note that to specify an object, the "L" is followed by the object's class name and ends with a
semi−colon, ';' .

The javap utility (included with the JDK) is very useful to show the signature to be used in JNI.

X:\>javap −s java.awt.Label
Compiled from Label.java
public class java.awt.Label extends java.awt.Component {
public static final int LEFT;
/* I */
public static final int CENTER;
/* I */
public static final int RIGHT;
/* I */
java.lang.String text;
/* Ljava/lang/String; */
int alignment;
/* I */
static {};
/* ()V */
public java.awt.Label();
/* ()V */
public java.awt.Label(java.lang.String);
/* (Ljava/lang/String;)V */
public java.awt.Label(java.lang.String,int);
/* (Ljava/lang/String;I)V */
public void addNotify();
/* ()V */
java.lang.String constructComponentName();
/* ()Ljava/lang/String; */
public int getAlignment();
/* ()I */
public java.lang.String getText();
/* ()Ljava/lang/String; */
protected java.lang.String paramString();
/* ()Ljava/lang/String; */
public synchronized void setAlignment(int);
/* (I)V */
public void setText(java.lang.String);
/* (Ljava/lang/String;)V */

8.4 Set the computer clock


The javap utility can be used on the java.* or your own classes.

8.6 Use arrays


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0287.html

JNI provides special functions (relative to the type) to access Java arrays.

This example returns the maximum of an int array.

JNIEXPORT jint JNICALL Java_JavaHowTo_max


(JNIEnv * env, jclass obj, jintArray arr) {
int i;
jsize len = env−>GetArrayLength(arr, max = −1;
jint *body = env−>GetIntArrayElements(arr, 0);
for (max = body[0], i=1; i <len; i++)
if (max <body[i]) max = body[i];
env−>ReleaseIntArrayElements(arr, body, 0);
return max;
}

The Java wrapper

class JavaHowTo {
public static native int max(int [] t);
static {
System.loadLibrary("javahowto");
}
}

The test program

class JNIJavaHowTo {
public static void main(String[] args) {
int [] myArray = {4, 7, 5, 9, 2, 0, 1};
System.out.println(JavaHowTo.max(myArray));
}
}

This following how−to is currently broken...


Without passing the array directly to the JNI function, it's possible to fetch directly from the class the
array.

JNIEXPORT jint JNICALL Java_JavaHowTo_printArray


(JNIEnv * env, jclass obj) {
jfieldID fid;
jobject jtab;
jsize len;
int i;

jclass cls = env−>GetObjectClass(obj);


fid = env−>GetFieldID(cls, "myArray", "[I");
if (fid == 0) return;
jtab = env−>GetObjectField(obj, fid);
tab = env−>GetIntArrayElements(jtab, 0);
len = env−>GetArrayLength(jtab);

8.6 Use arrays


printf("int [] : [");
for (i = 0; i <len ; i++) printf("%d ", tab[i]);
printf("]\n");
}

8.7 Load a DLL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0318.html

[pre JDK1.2]

System.loadLibrary("d:\\directoryX\\subDirY\\MyDll.dll")

In JDK1.2 (or better), if the DLL is in the CLASSPATH then you don't need to specify a PATH. If the
DLL is not in the CLASSPATH then you need to specify the PATH.

Do something like this instead.

Runtime.getRuntime().load("d:/directoryX/subDirY/MyDll.dll");

or specify through the JVM command line the location where to find the JNI DLL to be loaded

java −Djava.library.path=c:/temp JNIJavaHowTo

8.8 Use the MouseWheel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0314.html

Current JDK don't support scrolling via the MouseWheel.

Next version (JDK1.4) may provide this functionality but for now, you need some JNI functions.

See this link http://www.codeproject.com/java/mousewheel.asp .

8.9 Throw an Exception (from JNI code)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0323.html

Define the following prototype in the header file

JNIEXPORT jdouble JNICALL Java_JavaHowTo_divide


(JNIEnv *, jobject, jdouble, jdouble);

the JNI function

JNIEXPORT jdouble JNICALL Java_JavaHowTo_divide

8.7 Load a DLL


(JNIEnv *env, jobject obj, jdouble d1, jdouble d2) {
if (d2 == 0.0) {
jclass Exception = env−>FindClass("java/lang/Exception");
env−>ThrowNew(Exception,"Can't divide by zero.");
}
return d1/d2;
}

The Java JNI wrapper would be

class JavaHowTo {
public native double divide(double d1, double d2);
static {
System.loadLibrary("javahowto");
}
}

And finally, to use it

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
System.out.println("division 1 : " + jht.divide(9.0, 3.0));
System.out.println("division 2 : " + jht.divide(9.0, 0.0));
}
}

8.10 Throw my own Exception (from JNI code)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0322.html

The MyOwnException class

public class MyOwnException extends Exception {


public MyOwnException(){}
public MyOwnException(String txt) {
super(txt);
}
}

the prototype in the header file

JNIEXPORT void JNICALL Java_JavaHowTo_triggerException


(JNIEnv *, jobject);

the JNI function

JNIEXPORT void JNICALL Java_JavaHowTo_triggerException


(JNIEnv *env, jobject obj) {
jclass MyOwnException = env−>FindClass("MyOwnException");
env−>ThrowNew(MyOwnException,"Exception triggered from JNI routine.");
}

The Java JNI wrapper would be

class JavaHowTo {

8.10 Throw my own Exception (from JNI code)


public native void triggerException();
static {
System.loadLibrary("javahowto");
}
}

And finally, to use it

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
jht.triggerException();
}
}

8.11 JNI from a package


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0348.html

JNI requires that the function names follow a specific format. If you have a Java native method in a
class called MyClass like this:

public native void myMethod();

the native function must look like this:

JNIEXPORT void JNICALL Java_MyClass_myMethod(JNIEnv *, jobject);

When you put the class into a package (say com.rgagnon), you need to include the package
information in the native function name like this:

JNIEXPORT void JNICALL Java_com_rgagnon_MyClass_myMethod(JNIEnv *, jobject);

To generated the proper header, compile the JNI class in the package then, using the javah utility
(from the root of the package) :

javah com.rgagnon.MyClass

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

8.12 Make a Window "stay on top"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0353.html

First you need the handle of the Window. Call this JNI function with Window Title.

JNIEXPORT jint JNICALL Java_JavaHowTo_getHwnd


(JNIEnv *env, jclass obj, jstring title){

8.11 JNI from a package


HWND hwnd = NULL;
const char *str = NULL;

str = (*env)−>GetStringUTFChars(env, title, 0);


hwnd = FindWindow(NULL,str);
(*env)−>ReleaseStringUTFChars(env, title, str);
return (jint) hwnd;
}

Then you pass the handle to this function

JNIEXPORT void JNICALL Java_JavaHowTo_setWindowAlwaysOnTop


(JNIEnv *env, jclass obj, jint hwnd, jboolean flag){
if (flag)
SetWindowPos((HWND) hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
else
SetWindowPos((HWND) hwnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
return;
}

8.13 Start a JVM from C


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0354.html

#include <jni.h>
#include <stdio.h>

int main() {
JavaVM *vm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "−Djava.class.path=c:/myclasses";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = 1;
jstring jstr;
jobjectArray args;
jint res = JNI_CreateJavaVM((void **)
if (res < 0) {
printf("Can't create Java VM\n");
exit(1);
}
jclass cls = env−>FindClass("HelloWorld"); // in c:/myclasses
if (cls == 0) {
printf("HelloWorld class not found\n");
exit(1);
}
jmethodID mid =
env−>GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
if (mid == 0) {
printf("main() method not found\n");
exit(1);
}
jstring argString = env−>NewStringUTF(""); //empty arg list
jobjectArray args =
env−>NewObjectArray(1, env−>FindClass("java/lang/String"), jstr);

8.13 Start a JVM from C


if (args == 0) {
printf("Out of memory\n");
exit(1);
}
env−>CallStaticVoidMethod(cls, mid, args);
return 0;
}

8.14 Retrieve environment variable (JNI)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0460.html

For some odd reasons, the getenv() method was removed from the JDK. Rumors is that a
mechanism to retrieve an environment will be back in JDK1.5 (see this HowTo). But for now, you
can use −D switch to retrieve named environment variable and pass them to the JVM (see this
HowTo) or use this JNI routine :

JNIEXPORT jstring JNICALL JavaHowTo_getenv


(JNIEnv *env, jclass c, jstring jname){
if ( jname == NULL ) {
return NULL ;
}
const char *name =
(*env)−>GetStringUTFChars(env, jname, (jboolean *)NULL) ;
const char *value = getenv(name) ;
(*env)−>ReleaseStringUTFChars(env, jname, name) ;
return value ? (*env)−>NewStringUTF(env, value) : NULL ;
}

NOTE : This is fine if the environment variable contains only regular 7−bit ASCII characters.

See also this HowTo.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

8.15 Get the PID


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0467.html

class JavaHowTo {
public native long getCurrentProcessId();
static {
System.loadLibrary("jni2");
}
}

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();

8.14 Retrieve environment variable (JNI)


System.out.println("Press Any key...");
java.io.BufferedReader input =
new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
try { input.readLine();}
catch (Exception e) { e.printStackTrace();}
System.out.println(jht.getCurrentProcessId());
}
}

// jni2.cpp : Defines the entry point for the DLL application.


//

#include "stdafx.h"
#include <process.h>
#include "JavaHowTo.h"

BOOL APIENTRY DllMain( HANDLE hModule,


DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

JNIEXPORT jlong JNICALL Java_JavaHowTo_getCurrentProcessId


(JNIEnv *, jobject) {

// return GetCurrentProcessId();
return getpid();
}

You can download the whole thing here.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

8.16 Clear the console, set color and cursor position (JNI)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0469.html

[Windows only]
First you need this Java stub (JavaHowTo.java) to provide an interface to the JNI DLL (jni3.dll).

class JavaHowTo {

public static final short FOREGROUND_BLACK = 0x0;


public static final short FOREGROUND_BLUE = 0x1;
public static final short FOREGROUND_GREEN = 0x2;
public static final short FOREGROUND_RED = 0x4;
public static final short FOREGROUND_WHITE = 0x7;
public static final short FOREGROUND_INTENSITY = 0x8;

public static final short BACKGROUND_BLUE = 0x10;


public static final short BACKGROUND_GREEN = 0x20;

8.16 Clear the console, set color and cursor position (JNI)
public static final short BACKGROUND_RED = 0x40;
public static final short BACKGROUND_INTENSITY = 0x80;
// and so on...the definition for the other colors is
// left as an exercise :−)

public native void cls();


public native void setCursorPosition( short x, short y);
public native void keepColors();
public native void restoreColors();
public native void setColor( short foreground, short background);
static {
System.loadLibrary("jni3");
}
}

Compile and generate an header with javah JavaHowto, the result is a file called JavaHowTo.h.

Next we built a DLL, I'm using VisualStudio v6. Don't forget to include the folders
%JAVAHOME%\include and %JAVAHOME%\include\win32 to have access to the JNI header files.

// jni3.cpp : Defines the entry point for the DLL application.


//

#include "stdafx.h"
#include <stdlib.h>
#include "JavaHowTo.h"

int originalColors;

BOOL APIENTRY DllMain( HANDLE hModule,


DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}

JNIEXPORT void JNICALL Java_JavaHowTo_cls


(JNIEnv *env, jobject obj) {

HANDLE hConsole;
unsigned long * hWrittenChars = 0;
CONSOLE_SCREEN_BUFFER_INFO strConsoleInfo;
COORD Home;
static unsigned char EMPTY = 32;

Home.X = 0;
Home.Y = 0;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole,
FillConsoleOutputCharacter(hConsole, EMPTY,
strConsoleInfo.dwSize.X * strConsoleInfo.dwSize.X, Home,
hWrittenChars);
SetConsoleCursorPosition(hConsole, Home);
// system("cls"); will do the same as the above!
}

JNIEXPORT void JNICALL Java_JavaHowTo_setCursorPosition


(JNIEnv *env, jobject obj, jshort x, jshort y) {

8.16 Clear the console, set color and cursor position (JNI)
HANDLE hConsole;
COORD coordScreen;

hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
coordScreen.X = x;
coordScreen.Y = y;
SetConsoleCursorPosition( hConsole, coordScreen );

JNIEXPORT void JNICALL Java_JavaHowTo_setColor


(JNIEnv *env, jobject obj, jshort foreground, jshort background) {
HANDLE hConsole;

hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, foreground + background);
}

JNIEXPORT void JNICALL Java_JavaHowTo_keepColors


(JNIEnv *env, jobject obj) {
HANDLE hConsole;
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;

hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole,
originalColors = ConsoleInfo.wAttributes;
}

JNIEXPORT void JNICALL Java_JavaHowTo_restoreColors


(JNIEnv *env, jobject obj) {
HANDLE hConsole;

hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, originalColors);
}

Build the DLL (target Release), the result is jni3.dll.

Here an example how to use the DLL.

public class JNIJavaHowTo {


public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();

// clear the screen


jht.cls();

// set the cursor at line 10 column 20


jht.setCursorPosition((short)20,(short)10);
System.out.print("Real's HowTo");

// set the cursor at line 15 column 20


jht.setCursorPosition((short)20,(short)15);

// keep the current colors


jht.keepColors();

// set the color as WHITE on BLUE


jht.setColor(jht.FOREGROUND_WHITE,jht.BACKGROUND_BLUE);

System.out.print("http://www.rgagnon.com");

8.16 Clear the console, set color and cursor position (JNI)
// restore the orginal colors
jht.restoreColors();

// set the cursor at line 20 column 0


jht.setCursorPosition((short)0,(short)20);
}
}

You can download a zip with everything here.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

8.17 Call Windows API (Open source solution)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0497.html

NativeCall
NativeCall is a Java toolkit that lets you call operating system methods from whithin Java without
JNI code.

// copying a file to a new one using the Windows API


import com.eaio.nativecall.*;

NativeCall.init();
IntCall ic = new IntCall("CopyFileA");
ic.executeCall(new Object[] { "test.txt", "test_copy.txt", Boolean.FALSE });
ic.destroy();

See http://johannburkard.de/software/nativecall/

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

8.17 Call Windows API (Open source solution)


9 Javascript interaction
9.1 java−js

9.2 * Read me *
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0168.html

The examples in these How−to's are tested with Netscape 7 (or better) on Windows.

The LiveConnect package is included with IE4/5 (Win version).

The LiveConnect package is included with the Java plugin too. The official documentation for the
various versions can be found at http://java.sun.com/products/plugin/reference/docs/index.html.

Unix/Linux
But it seems that there is a LiveConnect−SDK for Unix. It's based on N3 but works on N4 (at least
on Solaris and Linux, thanks to A. Zisowsky for the tip).

The JSObject package is included with Netscape 6 preview but it is broken but should be fixed for
the release version!

Mac
To use the LiveConnect packages on the Mac you will need to install the latest MRJ available from
the Apple website and then goto the Mozilla website and download the MRJ Plugin. The only other
thing then is to change the <applet> tags to <embed> tag (more info on this is on the Mozilla site).
Thanks to Neil English for the tip

9.3 Wake−up a Java applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0169.html

When moving the mouse over an image, we want to start an applet (here a simple chronometer),
and when the mouse leave the image, the Applet should stop.

[JAVA APPLET]

import java.applet.*;
import java.awt.*;

public class JavaChrono extends Applet {


String previousTime = "0" ;
String currentTime = "0";
long j,k, l;
boolean okToChrono = false;

9 Javascript interaction
Color b, f;

public void init() {


b = getBackground();
f = getForeground();
MyThread tm = new MyThread(this);
tm.start();
}

public void startChrono() {


j = System.currentTimeMillis();
okToChrono = true;
}

public void stopChrono() {


okToChrono = false;
}

public void paint(Graphics g) {


if (okToChrono) {
g.setColor(b);
g.drawString(previousTime,10,30);
g.setColor(f);
k = System.currentTimeMillis();
l = k−j;
currentTime = Long.toString(l/1000);
g.drawString(currentTime,10,30);
previousTime = currentTime;
}
}
}

class MyThread extends Thread {


JavaChrono theApplet;

public MyThread(JavaChrono a) {
theApplet = a;
}

public void run() {


while (true) {
try {
theApplet.repaint();
this.sleep(1000);
}
catch(InterruptedException e) { }
}
}
}

[HTML]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE=JavaChrono.class
WIDTH=150
HEIGHT=150>
</APPLET>
<A HREF=""
onMouseOver="document.applets[0].startChrono()"
onMouseOut="document.applets[0].stopChrono()" >
<IMG SRC="whatever.gif" WIDTH=100 HEIGHT=100>
</A>
/BODY/HTML

9 Javascript interaction
Try it here.

In the next example, when we click on a FORM's button, we tell the applet to open or close a frame.

[HTML]

<HTML>
<HEAD></HEAD>
<BODY>
<APPLET NAME="myApplet" CODE="MyApplet.class" HEIGHT=1 WIDTH=1></APPLET>
<FORM>
<INPUT TYPE="button"
VALUE="Start the Applet"
onClick=
"if (document.applets[0].isActive()) document.myApplet.showFrame()">
<INPUT TYPE="button"
VALUE="Stop the Applet"
onClick=
"if (document.applets[0].isActive()) document.myApplet.disposeFrame()">
/FORM/BODY/HTML

[JAVA APPLET]

import java.applet.*;
import java.awt.*;

public class MyApplet extends Applet {


Frame f = null;

public void init() { }

public void showFrame() {


if (f == null) {
f = new Frame();
f.setSize(100,100);
f.add(new Label("Hello World"));
f.setVisible(true);
}
}

public void disposeFrame() {


if (f != null) {
f.dispose();
f = null;
}
}
}

Try it here.

9.4 Call a Java method from Javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0170.html

You call a Java method by giving its fully qualified name. In the following snippet, the first example
calls the method in the Toolkit to retrieve the screen resolution. The second example, calls a
method in our Applet.

9.4 Call a Java method from Javascript


NOTE: On IE4 or better, you can't call java.* methods directly from Javascript or Jscript. IE
javascript can only access the public methods of an applet (a class derived from java.applet.Applet)
but don't have a general access to other java classes . So the solution is simple, wrap the java.* call
in a public method of a "dummy" Applet.

[Java applet]

import java.awt.*;
import java.applet.*;
public class InJava extends Applet{
public void sayHello() {
Graphics g = getGraphics();
g.drawString("Hello from JAVA!", 10, 10);
}
}

[Javascript and HTML (Netscape)]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
function getScreenDimension() {

alert("Screen Dimension\n" +
" width:" +
java.awt.Toolkit.getDefaultToolkit().getScreenSize().width +
" height:" +
java.awt.Toolkit.getDefaultToolkit().getScreenSize().height);
}
</SCRIPT>
<FORM>
<INPUT type="button" value="call Java Applet method"
onClick = "document.myApplet.sayHello()">
</FORM>

<INPUT type="button" value="call Java method direct"


onClick = "getScreenDimension()">

<APPLET CODE="InJava.class"
NAME="myApplet"
HEIGHT=100 WIDTH=100>
</APPLET>
/BODY/HTML

Try it here

import java.awt.*;
import java.applet.*;
// (IE and Netscape ok)
public class InJava2 extends Applet{
public int getScreenWidth() {
return Toolkit.getDefaultToolkit().getScreenSize().width;
}
public int getScreenHeight() {
return Toolkit.getDefaultToolkit().getScreenSize().height;
}
}

[Javascript and HTML (IE and Netscape)]

<HTML><HEAD></HEAD><BODY>

9.4 Call a Java method from Javascript


<SCRIPT>
function getScreenDimension() {
alert("Screen Dimension\r\n width:" +
document.myApplet.getScreenWidth() +
" height:" +
document.myApplet.getScreenHeight() );
}
</SCRIPT>
<FORM>
<INPUT type="button" value="call JAVA"
onClick = "getScreenDimension()">
</FORM>
<APPLET CODE="InJava2.class"
NAME="myApplet"
HEIGHT=100 WIDTH=100>
</APPLET>
/BODY/HTML

Try it here

NOTE: This for demonstration only. On N4 or IE4, it's better to use screen.height and screen.width properties directly. There is no need for a
Java Applet!

NOTE: The first time, there is a delay because the Applet need to load and initialize.

9.5 Calling Java applets methods using DOM and JavaScript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0346.html

[IE4 or better]
<OBJECT ID="myApplet" ...>
...
<PARAM NAME="scriptable" value="true">
<PARAM NAME="mayscript" value="true">
...
</OBJECT>

[in your script]


document.all.myApplet.myMethod()

You use the scriptable parameter if you call Java method from Javascript.
You use the mayscript parameter if you call Javascript function from Java.

This Sun's document describes how Java to Javascript communication works when using the Java
Plug−in.

9.6 Access Java variables from Javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0171.html

Java variables can be used by giving the fully qualified name. In Java, the variable must be
declared as "public". To be compatible Netscape AND MSIEv4, the preferred way is to use special
"access method" to read Java variables (only String or integer).

9.5 Calling Java applets methods using DOM and JavaScript


[Java applet]

import java.awt.*;
import java.applet.*;
public class InJava3 extends Applet{
public int iJava = 123;
public String sJava = "String from JAVA";

public int getIntJava() {


return iJava;
}
public String getStringJava() {
return sJava;
}
}

[Javascript and HTML]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
function JavaSays() {
alert("Java says\n the value of iJava is :" +
document.myApplet.getIntJava() + "\n" +
"and sJava is :" +
document.myApplet.getStringJava());
}
</SCRIPT>
<FORM>
<INPUT type="button" value="Java says"
onClick = "JavaSays();">
</FORM>
<APPLET CODE="InJava3.class"
NAME="myApplet"
HEIGHT=0 WIDTH=0>
/APPLET/BODY/HTML

Try it here

Remember that IE4 can access only attributes and methods from a class derived from java.applet.Applet. If you want to call a method or use an
attribute in another class, you have to create a method in your applet class that calls the other class's method.

9.7 Call Javascript from a Java applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0172.html

Netscape only, using the javascript: protocol


A Javascript function is called from Java by using the showDocument method. A URL is needed
with "javascript:" as the protocol.

[Java applet]

import java.applet.*;
import java.net.*;

public class InJava4 extends Applet{


public void init(){
String msg = "Hello from Java (using javascript alert)";

9.7 Call Javascript from a Java applet


try {
getAppletContext().showDocument
(new URL("javascript:doAlert(\"" + msg +"\")"));
}
catch (MalformedURLException me) { }
}
}

[Javascript and HTML]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
function doAlert(s) {
alert(s);
}

</SCRIPT>
<APPLET CODE="InJava4.class"
NAME="myApplet" MAYSCRIPT
HEIGHT=10 WIDTH=10>
</APPLET>
</BODY>
/HTML

Try it here

Netscape and IE ok, using the netscape.javascript.JSObject package

How to compile when using the netscape.javascript.JSObject package ?

For Java 1.4.2 and later: add plugin.jar to your classpath. It can be found in the lib directory of your
JRE installation, e.g. C:\Program Files\Java\jre1.5.0\lib\plugin.jar

For Java 1.4.0/1.4.1: use jaws.jar (same directory).

In the following example, you type in the TextField a Javascript function and press the button to
execute the function. For example, try alert('Hello from JAVA'). Or you can execute function defined
on the same page as the Applet. The Applet must contains the MAYSCRIPT parameter to be able
to use JSObject.

Netscape and IE Ok.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import netscape.javascript.*;

public class InJava5 extends Applet implements ActionListener {


Button b;
TextField t;

public void init() {


t = new TextField(20);
add(t);
b = new Button("execute Javascript");
add(b);
b.addActionListener(this);
}

9.7 Call Javascript from a Java applet


public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == b) {
JSObject win = (JSObject) JSObject.getWindow(this);
win.eval(t.getText());
}
}
}

Try it here

Another way is to use the Reflection API. That way you don't need to modify your CLASSPATH for
compilation or even import the netscape.jsobject package.

// posted by C Werner on the realhowto list


import java.lang.reflect.*;
...
// Somewhere in the applet class ...
...
String jscmd = "window.close()"; /* JavaScript command */
String jsresult = null;
boolean success = false;
try {
Method getw = null, eval = null;
Object jswin = null;
Class c =
Class.forName("netscape.javascript.JSObject"); /* does it in IE too */
Method ms[] = c.getMethods();
for (int i = 0; i < ms.length; i++) {
if (ms[i].getName().compareTo("getWindow") == 0)
getw = ms[i];
else if (ms[i].getName().compareTo("eval") == 0)
eval = ms[i];
}
}
Object a[] = new Object[1];
a[0] = this; /* this is the applet */
jswin = getw.invoke(c, a); /* this yields the JSObject */
a[0] = jscmd;
Object result = eval.invoke(jswin, a);
if (result instanceof String)
jsresult = (String) result;
else
jsresult = result.toString();
success = true;
}

catch (InvocationTargetException ite) {


jsresult = "" + ite.getTargetException();
}
catch (Exception e) {
jsresult = "" + e;
}

if (success)
System.out.println("eval succeeded, result is " + jsresult);
else
System.out.println("eval failed with error " + jsresult);

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

9.7 Call Javascript from a Java applet


9.8 Create dynamic HTML from a Java applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0173.html

We can use the netscape.javascript.* included with Netscape browser and IE4 (Win version). See
also this HowTo to learn how to compile with this package.

[Java applet JDK1.1 Netscape/IE4 (win) OK]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import netscape.javascript.*;

public class HtmlFromJava extends Applet


implements ActionListener {
Button aButton;

public void init(){


setLayout(new FlowLayout());
aButton = new Button("create HTML");
add(aButton);
aButton.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == aButton){
String HTML = "<HTML><HEAD></HEAD><BODY>";
HTML += "<TABLE BORDER=1><TR><TD>Hello world</TD></TR></TABLE>";
HTML += "</BODY></HTML>";
JSObject win = (JSObject)JSObject.getWindow(this);
win.eval("createHTML(\"" + HTML +"\");");
}
}
}

[Javascript and HTML]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
function createHTML(s) {
win = window.open("about:");
win.document.write(s);
win.document.close();
}
</SCRIPT>

<APPLET CODE=HtmlFromJava.class
MAYSCRIPT
WIDTH=150
HEIGHT=150>
/APPLET/BODY/HTML

Try it here

9.8 Create dynamic HTML from a Java applet


9.9 Have Applets on different frames communicates with each
other
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0174.html

You can use a Javascript function as a bridge between the 2 frames.

[main HTML (interframe0.html)]

<HTML><HEAD></HEAD>
<FRAMESET COLS="50%,*">
<FRAME SRC="interframe1.html" NAME="f1" >
<FRAME SRC="interframe2.html" NAME="f2">
</FRAMESET>
</HEAD>

[frame 1 HTML (interframe1.html)]

<HTML><HEAD></HEAD>
<SCRIPT>
function toOtherFrame(a, target) {
if (target == "f1")
parent.f1.document.app1.fromOtherFrame(a);
else
parent.f2.document.app2.fromOtherFrame(a);
}
</SCRIPT>
</HEAD>

<BODY>
<APPLET CODE="InterFrameDemo.class"
NAME="app1" MAYSCRIPT
HEIGHT=200
WIDTH=200>
<PARAM NAME="target"
VALUE="f2">
</APPLET></BODY></HTML>

[frame 2 HTML (interframe2.html)]

<HTML><HEAD></HEAD>

<BODY>
<APPLET CODE="InterFrameDemo.class"
NAME="app2" MAYSCRIPT
HEIGHT=200
WIDTH=200>
WIDTH=200>
<PARAM NAME="target"
VALUE="f1">
</APPLET></BODY></HTML>

[Java applet (InterFrameDemo.java)]

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

9.9 Have Applets on different frames communicates with each other


import java.net.URL;
import netscape.javascript.*;

public class InterFrameDemo extends Applet implements ActionListener {


TextField tf;
Button b;
String target;

public void init() {


target = getParameter("target");
setLayout(new BorderLayout());
tf = new TextField(20);
add("South", tf);
b = new Button("To other frame");
add("North",b);
b.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b) {
String js =
"parent.f1.toOtherFrame(\"" +
tf.getText() +
"\",\"" + target + "\")";
System.out.println("to Javascript:" + js);
JSObject win = (JSObject) JSObject.getWindow(this);
win.eval(js);
}
}

public void fromOtherFrame(String s) {


tf.setText(s);
}
}

Try it here

For a JAVA−only solution check this Java How−to

9.10 Send a message from an Applet to another Applet on a


different page
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0181.html

FirstApplet encodes the message for SecondApplet in the search (or query) section of
SecondApplet.html URL. A simple script in SecondApplet.html decodes the search section and
dynamically creates a new page containing the APPLET tag for SecondApplet and a PARAM with
the message coming from FirstApplet.

FirstApplet.html

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="FirstApplet.class"
HEIGHT=100
WIDTH=300>
/APPLET/BODY/HTML

9.10 Send a message from an Applet to another Applet on a different page


FirstApplet.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class FirstApplet extends Applet implements


ActionListener {
Button b;
TextField t;
public void init() {
add(new Label("Message to 2nd applet :"));
add(t= new TextField(20));
add(b = new Button("Load 2nd applet"));
b.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b) {
try {
getAppletContext().showDocument
(new URL(getCodeBase(),
"SecondApplet.html?" + "message="
+ URLEncoder.encode(t.getText())));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

SecondApplet.html

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
// from Javascript How−to general part 3,
// replace all occurrence of token by another
// in a string.
function replace(s, t, u) {
i = s.indexOf(t);
r = "";
if (i == −1) return s;
r += s.substring(0,i) + u;
if ( i + t.length <s.length)
r += replace(s.substring(i + t.length, s.length), t, u);
return r;
}

strlen = document.location.search.length
if (strlen > 0) {
theMessage = document.location.search
// strip the "message header"
theMessage = theMessage.substring(1 + 'message='.length,strlen)
// replace all '+" by space
theMessage = replace(theMessage, '+', ' ')
// replace encoded chars by decoded chars if any
theMessage = unescape(theMessage)
html = '<APPLET CODE="SecondApplet.class"'
html += ' HEIGHT=100'
html += ' WIDTH=400> '

9.10 Send a message from an Applet to another Applet on a different page


html += '<PARAM NAME="Message" VALUE="' + theMessage + '"> '
html += '</APPLET>'
document.close()
document.open()
document.write(html)
document.close()
}
</SCRIPT>
/BODY/HTML

SecondApplet.java

import java.applet.*;
import java.awt.*;

public class SecondApplet extends Applet {


public void init() {
Label l = new Label("Message from 1st Applet");
add (l);
TextField tf = new TextField( 50 );
add(tf);
String s = getParameter("Message");
tf.setText(s);
}
}

You can try it here!

This method is useful when you need to pass the message to the SecondApplet via PARAM tag.
But if you don't need the PARAM tag, take a look at this Java How−to.

9.11 Retrieve values from a Java applet for HTML form (CGI)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0175.html

Retrieve the value with a Javascript function called via the onSubmit event of the form.

[InitHTMLForm.java]

public class InitHTMLForm extends java.applet.Applet {


public String getFirstName() {
// in real life, you have TextField in your Applet and
// you want to transert its content to the HTML FORM
// return myTextField.getText();
return "Real's HowTo";
}
}

[HTML and Javascript]

<HTML><HEAD>
<SCRIPT>
function getValueFromApplet(){
document.myForm.q.value = document.myApplet.getFirstName();
return true;
}

9.11 Retrieve values from a Java applet for HTML form (CGI)
</SCRIPT>
<BODY>
<APPLET CODE="InitHTMLForm.class"
NAME="myApplet"
HEIGHT=0 WIDTH=0>
</APPLET>
<FORM ACTION="http://www.google.ca/search"
NAME="myForm"
onSubmit="return getValueFromApplet()">
<INPUT TYPE="hidden" VALUE="" NAME="q">
<INPUT TYPE="submit" VALUE="Submit" >
</FORM>
/BODY/HTML

Try it here

9.12 Detect if an Applet is ready


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0176.html

<SCRIPT>
function isAppletReady(a) {
return a.isActive();
}
</SCRIPT>

<FORM>
<INPUT TYPE=button
VALUE="Check applet"
onClick="if (!isAppletReady(document.applets[0])) alert("not ready");">
/FORM

An Applet is ready when it's loaded and its init() method is done.

To execute a Javascript only when an Applet is ready :

<SCRIPT>
function waituntilok() {
if (document.myApplet.isActive()) {
doit();
}
else {
settimeout(waituntilok(),5000)
}
}

function doit() {
....
}
</SCRIPT>
...
<BODY onLoad="waituntilok();">

....

/BODY

9.12 Detect if an Applet is ready


By calling the javascript function from the BODY onLoad handler, we can assume that the Applet is
loaded, initiated and started.

Here a "browser friendly" solution from N. Witteman to check if an Applet can be loaded (or found).

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">

onError = errHandler;
// Without he parentheses, because we don't want IE
// to do this. Like this, only NS does.

function appLoaded() {
if (!document.applets[0].isActive)
// in IE: isActive returns an error if the applet IS loaded,
// false if not loaded
// in NS: isActive returns true if loaded, an error if not loaded,
// so never reaches the next statement
alert("IE: Applet could not be loaded");
}

function errHandler() {
alert("NS: Applet could not be loaded");
consume();
// stops further processing of the error
}

</SCRIPT>
</HEAD>

<BODY onLoad = appLoaded();>


<APPLET code=someClass.class
codeBase=someURL height=50 width=300><PARAM NAME="bgcolor" VALUE="FFFFFF">
</APPLET>
</BODY>
/HTML

9.13 Read/Write HTML field values from JAVA


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0177.html

[Netscape AND IE4 compatible]


The netscape.javascript.* (LiveConnect) package provides facilities to directly manipulate HTML
FORM components.

JSObject win = (JSObject)JSObject.getWindow(this);


JSObject inputText = (JSObject) win.eval("document.forms[0].elements[0]");
String value = (String)inputText.getMember("value"); // read form value
inputText.setMember("value" , value + " new stuff"); // write form value

But this action requires a signed applet. in Netscape, you must

PrivilegeManager.enablePrivilege("UniversalBrowserRead");
PrivilegeManager.enablePrivilege("UniversalBrowserWrite");

9.13 Read/Write HTML field values from JAVA


before using an JSObject related to an HTML document.

But there is a workaround, simply pass the informations through Javascript functions!

[JSjava.java]

import java.applet.*;
import java.awt.event.*;
import java.awt.*;
import netscape.javascript.*;

public class JSjava extends Applet


implements ActionListener {
Button b1,b2;
TextField tf;

JSObject win;

public void init(){


setLayout(new FlowLayout());
tf = new TextField(10);
b1 = new Button("to FORM");
b2 = new Button("from FORM");

b1.addActionListener(this);
b2.addActionListener(this);
add(tf);add(b1);add(b2);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) {
// send TO FORM
JSObject win = (JSObject)JSObject.getWindow(this);
win.eval("setHTMLInputText('"+tf.getText()+"');");
}
if (ae.getSource() == b2) {
// receive FROM FORM
JSObject win = (JSObject)JSObject.getWindow(this);
tf.setText((String)win.eval("getHTMLInputText();"));
}
}
}

[JSjava.html]

<HTML><HEAD>
<SCRIPT>
function getHTMLInputText(){
return document.forms[0].elements[0].value;
}
function setHTMLInputText(s){
document.forms[0].elements[0].value = s;
}
</SCRIPT></HEAD><BODY>
<FORM>
<INPUT TYPE=text SZIE=20>
</FORM>

<APPLET NAME="JS" CODE=JSjava.class MAYSCRIPT WIDTH=200 HEIGTH=200>


/APPLET/BODY/HTML

9.13 Read/Write HTML field values from JAVA


For best result, never use LiveConnect JSObject in Applet's init() method.

9.14 Detect if Java is enabled


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0178.html

from Javascript :

function isJavaAvailable(){
return ( navigator.javaEnabled &navigator.javaEnabled() );
}

For an HTML solution, check this How−to

9.15 Detect if Java 1.1 (with event delegation) is available


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0179.html

On some version of Netscape (eg.4.03), even if the JDK1.1 is reported as the Java version, you
need to apply a special patch to upgrade to the event delegation model. Here how you can detect if
the patch has been applied.

function isJava11Available() {
if (java.awt.event.MouseEvent)
return true;
else
return false;
}

Someone at Netscape suggests a better way to check :

function isJava11Available(){
if (java.awt.event.MouseEvent == "[JavaClass java/awt/event/MouseEvent]")
return true;
return false;
}

because Unknown Java classes are reflected as JavaPackages, for reasons related to the fact that
there's no way to tell if something is a valid package.

9.16 Access Cookies from a Java Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0180.html

This Applet uses the package netscape.javascript.JSObject. To compile such program, you have to
include in the CLASSPATH the file java40.jar if you have the Netscape Communicator v4 installed
or classes.zip for the Microsoft Internet Explorer. Compile with something like

9.14 Detect if Java is enabled


javac −classpath
.;
"\program files\netscape\communicator\program\java\classes\java40.jar";
%classpath%
testcookie.java

NOTE: The netscape.javascript.* package is now included in %JRE_HOME%\lib\jaws.jar file.

[HTML file (testCookie.html)]

<HTML><HEAD></HEAD><BODY>
<APPLET CODE=TestCookie.class
MAYSCRIPT
HEIGHT=150
WIDTH=200>
/APPLET/BODY/HTML

[Java applet (TestCookie.java)]

import netscape.javascript.*;
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class TestCookie extends Applet


implements ActionListener {
TextField tf1, tf2;
Button b1, b2, b3;

public void init() {


tf1 = new TextField(20);
tf2 = new TextField(20);

b1 = new Button("Write Cookie");


b2 = new Button("Read Cookie");
b3 = new Button("Delete Coookie");

setLayout(new FlowLayout());
add(tf1);
add(tf2);
add(b1);
add(b2);
add(b3);

b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) {
/*
** write a cookie
** computes the expiration date, good for 1 month
*/
java.util.Calendar c = java.util.Calendar.getInstance();
c.add(java.util.Calendar.MONTH, 1);
String expires = "; expires=" + c.getTime().toString();

String s1 = tf1.getText() + expires;


System.out.println(s1);

9.14 Detect if Java is enabled


JSObject myBrowser = JSObject.getWindow(this);
JSObject myDocument = (JSObject) myBrowser.getMember("document");

myDocument.setMember("cookie", s1);
}

if (ae.getSource() == b2) {
/*
** read a cookie
*/
tf2.setText(getCookie());
}

if (ae.getSource() == b3) {
/*
** delete a cookie, set the expiration in the past
*/
java.util.Calendar c = java.util.Calendar.getInstance();
c.add(java.util.Calendar.MONTH, −1);
String expires = "; expires=" + c.getTime().toString();

String s1 = tf1.getText() + expires;


JSObject myBrowser = JSObject.getWindow(this);
JSObject myDocument = (JSObject) myBrowser.getMember("document");
myDocument.setMember("cookie", s1);
}
}

public String getCookie() {


/*
** get all cookies for a document
*/
try {
JSObject myBrowser = (JSObject) JSObject.getWindow(this);
JSObject myDocument = (JSObject) myBrowser.getMember("document");
String myCookie = (String)myDocument.getMember("cookie");
if (myCookie.length() > 0)
return myCookie;
}
catch (Exception e){
e.printStackTrace();
}
return "?";
}

public String getCookie(String name) {


/*
** get a specific cookie by its name, parse the cookie.
** not used in this Applet but can be useful
*/
String myCookie = getCookie();
String search = name + "=";
if (myCookie.length() > 0) {
int offset = myCookie.indexOf(search);
if (offset != −1) {
offset += search.length();
int end = myCookie.indexOf(";", offset);
if (end == −1) end = myCookie.length();
return myCookie.substring(offset,end);
}
else
System.out.println("Did not find cookie: "+name);

9.14 Detect if Java is enabled


}
return "";
}
}

You can try it here.

See this text file with some useful Javascript functions for cookies handling.

Check this How−to to detect if Cookies are enabled or not.

9.17 Set Applet PARAM VALUE from javascript


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0182.html

PARAM VALUE can't be changed ar run−time but during layout time, javascript "entities" can be
used to set calculated VALUES.

In this How−to, VALUES are coming from a javascript variable, a javascript function and a javascript
expression.

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
var jsVar = "Hello World from jsVar";

function jsFnct() {
return "Hello World from jsFnct";
}

</SCRIPT></HEAD><BODY>
<<APPLET CODE ="MyApplet.class" HEIGHT=100 WIDTH=400>
<PARAM NAME="first" VALUE="&{jsVar};">
<param name="second" value="&{jsFnct()};">
<param name="third"
value="&{'hello world'.toUpperCase() + ' from js Expression'};">
</APPLET>
/BODY/HTML

For demonstration purpose, the MyApplet class

import java.applet.*;
import java.awt.*;

public class MyApplet extends Applet {

public void init() {


add(new Label(getParameter("first")));
add(new Label(getParameter("second")));
add(new Label(getParameter("third")));
}
}

NOTE: Javascript entities are not supported in IE. The workaround is to use the document.write() method to customize the APPLET PARAM
during layout time. See this How−to for an example.

9.17 Set Applet PARAM VALUE from javascript


9.18 Pass an Array between Java and Javascript
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0183.html

Javascript can read directly a Java Array but the other way don't seem be true. NOTE : Reading a
Java array from Javascript may crash your browser for some unknown reason. So it's safer
to use the next technique!

A safe and simple way is to transform the Array as a big String with a known character used a
separator. From there, it's trivial to do some manipulations to retrieve the array.

In the following example, the first button is used to read directly the Java array. The second button
call a Java method which to transform the array as a string, then the Javascript function split() is
used to retrieve the array. The third button will modify the Java array. A Javascript array is
transformed with the function join() and on the Java−side, a StringTokenizer will do the rest.

[Java applet]

import java.awt.*;
import java.applet.*;
import java.util.*;

public class TestJavaArray extends Applet{


public String javaArray [] =
{ "array 1", "array 2" , "array 3" };

public String [] getJavaArray() {


return javaArray;
}

public String getJavaArrayAsAString() {


// you need more error checking here, of course...
int k;
String s = "";

k = javaArray.length;
s = javaArray[0];
for (int i= 1 ; i < k; i++) {
s += "|" + javaArray[i] ;
}
return s;
}

public void putJavaArray(String arrayAsAString) {


int i = 0;
String s;
StringTokenizer st =
new StringTokenizer(arrayAsAString, "|");

while(st.hasMoreTokens()){
javaArray[i++] = st.nextToken();
}
}
}

[HTML and Javascript]

9.18 Pass an Array between Java and Javascript


<HTML><HEAD></HEAD><BODY>
<SCRIPT>
function getJavaArray() {
arrayFromJava = document.myApplet.getJavaArray();

alert("Java Array length = " + arrayFromJava.length + "\r\n" +


"element 2 is " + arrayFromJava[1]);
}

function getJavaArrayAsAString() {
var arrayAsAString =
document.myApplet.getJavaArrayAsAString();
realJsString = arrayAsAString + "";
arrayFromJava = realJsString.split("|");
alert("Java Array length = " + arrayFromJava.length + "\r\n" +
"element 2 is " + arrayFromJava[1]);
}

function putJavaArray() {
arrayFromJs = new Array("ARRAY 1", "ARRAY 2", "ARRAY 3");
arrayAsAString = arrayFromJs.join("|");
document.myApplet.putJavaArray(arrayAsAString);
}

</SCRIPT>
<FORM>
<INPUT type="button" value="get JAVA array"
onClick = "getJavaArray();">
<INPUT type="button" value="get JAVA array (as a string)"
onClick = "getJavaArrayAsAString();">
<INPUT type="button" value="put JAVA array"
onClick = "putJavaArray();">
</FORM>
<APPLET CODE="TestJavaArray.class"
NAME="myApplet"
HEIGHT=0 WIDTH=0>
/APPLET/BODY/HTML

Try it here.

Here an interesting piece of code submitted by M. Caetano which does basically the same thing.
Note the use of regular expressions to keep the code short and compact. Since java classes are
called directly by javascript, these functions won't work with IE (only with Netscape).

/*
COPYJAVA (by Mike Caetano)

Array prototype method to transfer array elements between javascript and


java

java array arg fills this empty js array with elements from java array
empty js array assigns its elements to string cast java array

Use:
// fill empty jsArray with the elements from the java array as strings
var jsArray = [];
jsArray.copyJava(javaArray)

// fill a javaArray with the elements from jsArray cast as


java.lang.String
var javaArray2 = jsArray.copyJava()

9.18 Pass an Array between Java and Javascript


Note: doesn't include cast for netscape.javascript.JSObject
− that requires a more stringent type checking
ie. typeof( [object Layer] ) => netscape.javascript.JSObject
− for now just don't call copyJava on an array of objects
−−−−−−−−−−−−−−−−−−−−−−−−−−−− */

function copyJava(arg_) {
if ( /^\bnull\b$|^\bundefined\b$|^\s?$/i.test(arg_) ) {
if ( this.length > 0 ) {
var temp = makeJavaArray('String',this.length);
var i=0; while ( i < this.length ) { temp[i] = ''+this[i++]; }
return temp;
}
else {
return null;
}
}
else {
if ( /^\bobject\b$/i.test(typeof(arg_)) ) {
if ( this.length == 0 ) {
var len = java.lang.reflect.Array.getLength(arg_);
var i=0; while ( i < len ) { this[i] = ''+arg_[i++]; }
}
}
}
}

function makeJavaArray(type_,size_) {
if ( !/^\bnull\b$|^\bundefined\b$|^\s?$/i.test(type_) ) {
if (
/boolean|byte|int|long|short|double
|float|char|void|String|Object|Class|Thread/.test(type_)
) {
var type = type_.charCodeAt(0)<91 ? 'java.lang.' + type_: type_;
var size = !isNaN(Number(size_)) ? Number(size_) : 1;
return ( new
java.lang.reflect.Array.newInstance
(java.lang.Class.forName(type),size)
);
} // else invalid cast
} // else invalid args
}

9.19 Interaction without LiveConnect


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0184.html

Java−Javascript interaction is not possible on many browsers or platforms. On Mac, for example,
the LiveConnect package is not available, even with the latest Netscape version. On IE3, the
interaction is very limited too.

Java to Javascript
One way to pass information from Java to Javascript, without LiveConnect or scripting support, is to
have an hidden frame acting as a bridge. From Java you do a showDocument() with a particuliar
page passing the message as parameter to the hidden frame, something like
showDocument("mypage.html?HelloJavascriptFromJava", "hiddenframe"). The mypage.html page
contains a javascript script to extract the parameter received in the URL (using the

9.19 Interaction without LiveConnect


document.search property). And then the parameter extracted is send to another javascript function
in the visible frame.

First, define the frameset with an invisible frame.

[SimpleJ2JS.HTML]
<FRAMESET ROWS="100%,*">
<FRAME NAME="mainFrame" SRC="visiblepage.html" border=0>
<FRAME NAME="scriptFrame" SRC="invisiblepage.html" border=0>
</FRAMESET>

visiblepage.html contains the Applet and a javascript function. The idea is to type something in a
TextField, press a Button to send a string to a javascript to do an alert() with the TextField content.

[visiblepage.html]
<HTML><HEAD>
<SCRIPT>
function showMessage(s) {
alert(s)
}
</SCRIPT>
</HEAD><BODY><H1>Simple Java to Javascript interaction</H1><P>
<APPLET CODE=SimpleApplet.class
WIDTH=150
HEIGHT=150>
</APPLET></BODY></HTML>

invisiblepage.html contains the function to extract the parameter and call the showMessage()
function in the visible frame.

<HTML><HEAD>
<SCRIPT>
function replace(s, t, u) {
i = s.indexOf(t);
r = "";
if (i == −1) return s;
r += s.substring(0,i) + u;
if ( i + t.length < s.length)
r += replace(s.substring(i + t.length, s.length), t, u);
return r;
}

function getAndSendMessage() {
theMessage = document.location.search.substring(1,255)
if (theMessage.length > 0) {
// replace all '+" by space
theMessage = replace(theMessage, '+', ' ')

window.parent.mainFrame.showMessage(unescape(theMessage))
}
}
</SCRIPT>
</HEAD><BODY onLoad="getAndSendMessage();">
</BODY></HTML>

and finally the Applet (a JDK102 style, since we want to be friendly to older browsers).

[SimpleApplet.java]
import java.applet.Applet;
import java.awt.*;

9.19 Interaction without LiveConnect


public class SimpleApplet extends Applet {
TextField aMessage;
Button sendButton;

public void init() {


aMessage = new TextField(20);
add(aMessage);
sendButton = new Button("Send to Javascript");
add(sendButton);
}

public boolean action(Event e, Object o) {


if (e.target.equals(sendButton)) {
try {
getAppletContext().showDocument
(new java.net.URL
(getCodeBase(),
"invisiblepage.html?"+
java.net.URLEncoder.encode(aMessage.getText())),
"scriptFrame");
}
catch (Exception ex) {
ex.printStackTrace();
}
}
return true;
}
}

Try it here.

Javascript to Java
The idea here is to have an invisible Applet in an invisible frame that will receive a message (from
Javascript in the visible frame) through the search part of its URL. Then via a static pointer to the
visible Applet, the invisible Applet pass the message to the visible Applet by calling the appropriate
function.

Frames definition

[SimpleJS2J.html]
<FRAMESET ROWS="100%,*">
<FRAME NAME="visibleFrame" SRC="visiblepage2.html" border=0>
<FRAME NAME="invisibleFrame" SRC="invisiblepage2.html" border=0>
</FRAMESET>

The visible page

[visiblepage2.html]

<HTML><HEAD>
<SCRIPT>
function send2Java() {
// you may need to encode the value with the escape() function
parent.invisibleFrame.location =
"invisiblepage2.html?" + document.forms[0].FromJs.value
}
</SCRIPT>
</HEAD><BODY><H1>Simple Javascript to Java interaction</H1>
<FORM>
<INPUT TYPE=input NAME=FromJs WIDTH=50 VALUE="HelloWorld">

9.19 Interaction without LiveConnect


<INPUT TYPE=button VALUE="Send to JAVA" onClick="send2Java();">
</FORM>

<APPLET CODE=SimpleApplet2.class
WIDTH=300
HEIGHT=150>
</APPLET></BODY></HTML>

The class to hold a static pointer to SimpleApplet2. This pointer will be used by the InvisibleApplet.

[SimpleAppletRegistered.java]

public class SimpleAppletRegistered {


static SimpleApplet2 sa;
}

The SimpleApplet2 is TextField which will be used to display the message type in the HTML FORM.

[SimpleApplet2.java]

import java.applet.Applet;
import java.awt.*;

public class SimpleApplet2 extends Applet {


TextField aMessage;

public void init() {


add(new Label("Message from Javascript "));
aMessage = new TextField(20);
add(aMessage);
// put a pointer to this Applet in a static
// variable which can be shared with the InvisibleApplet
SimpleAppletRegistered.sa = this;
}

public void setMessage(String msg) {


aMessage.setText(msg);
}
}

And finally the invisible page and InvisibleApplet

[invisiblepage2.html]
<HTML><HEAD>
</HEAD>
<BODY>
<APPLET CODE=InvisibleApplet.class
WIDTH=1
HEIGHT=1>
</APPLET>
</BODY></HTML>

[InvisibleApplet.java]

import java.applet.Applet;

public class InvisibleApplet extends Applet {


public void init() {
String completeURL = getDocumentBase().toString();
System.out.println("URL received : " + completeURL);
int i = completeURL.indexOf("?");

9.19 Interaction without LiveConnect


if (i > −1) {
String msg = completeURL.substring(completeURL.indexOf("?") + 1);
// call SimpleApplet via the static pointer
// you may to decode the string here with
// java.net.URLDecoder.decode() method.
SimpleAppletRegistered.sa.setMessage(msg);
}
}
}

Try it here.

NOTE: To send a message containing spaces and other special characters like &or ?, you will need to encode the message from Javascript
(with the escape function) and decode the message in Java.

With IE, you need to run this sample through a Web server.

9.20 Directory listing on the Web server in a Java Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0185.html

There is no way for an Applet to retrieve a directory contents without the help of server side
process(servlet/CGI). But here a way to do it with some help from Javascript.

In a browser, loading a URL with no file specified will return a directory listing under the following
conditions :

1. The directory doesn't contain a default page like index.html, default.htm or default.html.
2. The web server allows directory exploration.

For example, the URL http://www.tactika.com/realhome/images shows a directory listing of the files
in the images directory.

The listing is actually a real HTML page build on the fly. Our applet will extract the links in this page
and present them in a List. Links in a page are listed in the document property called links. This
property can be easily transform into a String array by a Javascript function. Then the array is
passed to a Java method. The Applet is very simple and can be customized to display more useful
descriptions or filter some entries.

We have 3 frames, 2 visibles and 1 invisible. The invisible one will contains the directory listing.
Frame visible #1 is for the Applet, by doubleclicking on a line in the List, the corresponding images
will be displayed in frame visble #2.

Frames definitions
Note that the 2 visibles frames are initially loaded with a "blank.html" to allow the third frame (the
invisible one) to be loaded with the directory content (here "../images").

browse.html

<HTML><HEAD>
<SCRIPT>
function reload_master() {
window.master.location.href = "./selector.html";

9.20 Directory listing on the Web server in a Java Applet


}
</SCRIPT></HEAD>
<FRAMESET ROWS="35%,65%,*" onLoad="reload_master()">
<FRAME SRC="blank.html" NAME="master">
<FRAME SRC="blank.html" NAME="detail">
<FRAME SRC="../images" NAME="contents" NORESIZE>
</FRAMESET>
/HTML

blank.html

<HTML<<HEAD><TITLE
</TITLE></HEAD><BODY>
</BODY></HTML>

When all pages are loaded, the selector.html page is loaded into the first visible frame. That page
contains the Applet. During layout time, Javascript extracts links to the an Array. Via the BODY
onLoad event handler, we trigger a Javascript function to transfer the Array to the Applet.

selector.html

<HTML><HEAD>
<SCRIPT>
var LinksLength =
parent.contents.window.document.links.length
var AllTheLinksAsArray = new Array()
// start at the second link because
// we dont want the root directory
for (var i = 1; i < LinksLength ; i++) {
s = parent.contents.window.document.links[i];
AllTheLinksAsArray[i] = s;
}

function putLinksIntoApplet() {
AllTheLinksAsString = AllTheLinksAsArray.join("|");
document.Selector.insertData(AllTheLinksAsString);
}
</SCRIPT></HEAD>
<BODY onLoad ="putLinksIntoApplet()">
<P ALIGN="center">Doubleclick to view
<APPLET
CODE=Selector.class
HEIGHT=100
WIDTH=400
NAME=Selector>
<PARAM NAME="targetFrame" VALUE="detail">
</APPLET>
</BODY>
/HTML

Selector.java

import java.awt.*;
import java.awt.event.*;
import java.applet.*;
import java.util.*;
import java.net.*;

public class Selector extends Applet


implements ActionListener {
java.awt.List l;

9.20 Directory listing on the Web server in a Java Applet


boolean okToDisplay = false;
String targetFrame = "";

public void init() {


setLayout(new BorderLayout());
add(l = new java.awt.List(5), "Center");
l.addActionListener(this);
targetFrame = getParameter("targetFrame");
}

public void actionPerformed(ActionEvent ae) {


if (okToDisplay) {
try {
URL urlToDisplay = new URL(ae.getActionCommand());
getAppletContext().showDocument(urlToDisplay, targetFrame);
}
catch (Exception e) { e.printStackTrace(); }
}
}

public void insertData(String arrayAsAString) {


int i = 0;
String s;
StringTokenizer st =
new StringTokenizer(arrayAsAString, "|");

while(st.hasMoreTokens()){
s = st.nextToken();
l.add(s); // or l.addItem(s);
System.out.println(s);
}
okToDisplay = true;
}
}

You can try it here.

NOTE: This How−to is inspired by an article by Martin Webb on http://www.irt.org

9.21 Have a Java button close the browser window


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0282.html

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import netscape.javascript.*;

public class WinClose extends Applet


implements ActionListener{

Button wc = new Button("Close me");

public void init() {


wc.setActionCommand("CLOSE");
wc.addActionListener(this);
add(wc);
}

9.21 Have a Java button close the browser window


public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("CLOSE")) {
JSObject win = (JSObject) JSObject.getWindow(this);
win.eval("self.close();");
}
}
}

Try it here

9.22 Detect if cookies are enabled


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0303.html

The detection is made by trying to write a cookie and reading it back. The value is passed to a Java
Applet by create dynamically the APPLET tag.

[testcookie.html]

<HTML><HEAD></HEAD><BODY>
<SCRIPT>
document.write("<APPLET CODE='MyApplet.class' HEIGHT=100 WIDTH=400>");

// check if cookie are enabled


cookieBackup = document.cookie
document.cookie = "cookie=yep"
cookieOk = document.cookie.indexOf("cookie=yep") > −1
document.cookie = cookieBackup

document.write(" <PARAM NAME='okToCookie' VALUE=" + cookieOk + ">");


document.write("</APPLET>");
</SCRIPT>
</BODY></HTML>

[MyApplet.java]

import java.applet.*;
import java.awt.*;

public class MyApplet extends Applet {

public void init() {


add(new Label("Cookie enabled :"));
add(new Label(getParameter("okToCookie")));
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

9.22 Detect if cookies are enabled


9.23 Display a page after all applets are loaded
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../jsdetails/js−0071.html

Place your page completely in a DIV tag.

Initially the visible attribute is false. When the page is completely loaded, the DIV visibility attribute is
set to true.

<HTML>
<HEAD>
<SCRIPT>
function doIt() {
if (document.all)
mypage.style.visibility="visible"
else
document.mypage.visibility="visible"
}

</SCRIPT></HEAD>
<BODY onLoad="doIt();">
<DIV name=mypage style="visibility:hidden" >
...
</DIV>
</BODY>
</HTML>

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

9.23 Display a page after all applets are loaded


10 Servlet/JSP
10.1 java−jsp

10.2 Read me
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0379.html

You may to take a look to these related How−to's in the EAServer/Jaguar section.

10.3 Get parameters passed to a servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0357.html

<HTML>
<HEAD></HEAD>
<BODY>
<FORM METHOD=POST ACTION="/servlet/MyServlet">
value : <INPUT TYPE="TEXT" NAME="someValue">
</FORM>
</BODY>
</HTML>

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost(HttpServletRequest req, HttpServletResponse res) {
// note : if "someValue" is missing a null is returned
String valuePassed = req.getParameter("someValue");
res.setContentType("text/html");

java.io.PrintWriter out = res.getWriter();


out.println("<html><head></head><body>");
out.println("the value is : " + valuePassed);
out.println("</body></html>");
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10 Servlet/JSP
10.4 Detect no argument condition in a Servlet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0341.html

Servlet 2.3

int i = req.getParameterMap().size();
if (i = 0) {
// no arguments
}
else {
Enumeration paramNames = req.getParameterNames();
while(paramNames.hasMoreElements()) {
String parm = (String)paramNames.nextElement();
// do something with this parm
}
}

Previous version of the Servlet API

protected void doGet


(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
response.setContentType( "text/html" );
out.println("<HTML>");
if (!request.getParameterNames().hasMoreElements()) {
// no arguments
out.println("<HEAD><TITLE>MyServlet (no args)</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1>MyServlet</H1>");
out.println("<FORM METHOD='GET' ACTION='Servlet1'>");
out.println(" Subject<INPUT TYPE=INPUT NAME=subject>");
out.println(" Recipients<INPUT TYPE=INPUT NAME=to>");
out.println(" Message<INPUT TYPE=INPUT NAME=message>");
out.println(" <INPUT TYPE=SUBMIT VALUE='Ok'>");
out.println(" </FORM>");
}
else {
out.println("<HEAD><TITLE>MyServlet (with args)</TITLE></HEAD>");
out.println("<BODY>");
out.println("<H1>Servlet</H1>");
java.util.Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements()) {
String parm = (String)paramNames.nextElement();
out.println(parm + " = " + request.getParameter(parm) + "<BR>");
}
out.println("</BODY></HTML>");
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.4 Detect no argument condition in a Servlet


10.5 Set a Cookie from a servlet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0358.html

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost(HttpServletRequest req, HttpServletResponse res) {
res.addCookie(new Cookie("mycookie_name", "mycookie_value"));
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.6 Read a Cookie from a servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0359.html

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost
(HttpServletRequest req, HttpServletResponse res) {
Cookie[] theCookies = request.getCookies();
if (theCookies != null) {
java.io.PrintWriter out = res.getWriter();
for (int i =0; i<cookies.length; i++) {
Cookie aCookie = theCookies[i];
out.println
("Name : " + aCookie.getName()
+ " Value: " + aCookie.getValue());
}
}
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

10.5 Set a Cookie from a servlet


Written and compiled by Réal Gagnon ©1998−2005
[ home ]

10.7 Delete (or expire) a Cookie from a servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0360.html

import javax.servlet.*;
import javax.servlet.http.*;

public class MyServlet extends HttpServlet {


public void doPost(HttpServletRequest req, HttpServletResponse res) {

Cookie cookie = new Cookie ("myCookie", "theCookieValue");

// Expire in five minutes (5 * 60)


cookie.setMaxTime( 300 );

// Expire after the browser is closed


// cookie.setMaxTime( −1 );

// Expire right now


// cookie.setMaxTime( 0 );

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.8 Ask for a password from a Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0342.html

public void askPassword(HttpServletResponse response) {


response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW−Authenticate",
"BASIC realm=\"protected−area\"");
}

then the browser will popup a dialog for username/password

10.7 Delete (or expire) a Cookie from a servlet


10.9 Talk to a CGI/Servlet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0082.html

From the client point of view, there is no difference talking to CGI or Servlet. There is two ways to
send a request to a CGI. The GET method contains encoded parameters in the URL. A typical URL
talking to CGI using the GET method would be:

new URL("http://www.server.com/cgi−bin/acgi.pl?name=real);

Here we calling a script called aCGI.pl (a PERL script) passing the parameters name and site.
Parameters are encoded, spaces are changed to "+" and special character to hexadecimal using a
3−letter escape sequence. Each parameter is delimited by the character "Habitually the encoding is
done through the static method encode of the java.net.URLencoder class.

String theCGI = "http://www.server.com/cgi−bin/aCGI.pl?";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL cgiurl = new URL(thecgi + encoded);

Once the URL is constructed, you call the CGI using the showDocument method (Applet).

getAppletContext().showDocument(cgiurl);

The CGI will process the result and produce a page to be displayed.

The POST method allows the programmer to manipulate the data received from the CGI. First a
connection is made to the CGI, an OutputStream is open to send the parameters (if any). Then
InputStream is created to receive the result.

String theCGI = "http://www.server.com/cgi−bin/aCGI.pl";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL CGIurl = new URL(theCGI);

URLConnection c = CGIurl.openConnection();
c.setDoOutput(true);
c.setUseCaches(false);
c.setRequestProperty("content−type","application/x−www−form−urlencoded");
DataOutputStream out = new DataOutputStream(c.getOutputStream());
out.writeBytes(encoded);
out.flush(); out.close();

BufferedReader in =
new BufferedReader(new InputStreamReader(c.getInputStream());

String aLine;
while ((aLine = in.readLine()) != null) {
// data from the CGI
System.out.println(aLine);
}

You can't do some output then some input and do again some output. You must do all the output
and then the input. There is no "dialog" between the client and the server. The client make a
request and the server send back the result and close the connection.

10.9 Talk to a CGI/Servlet


10.10 Test for Cookies
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0374.html

import javax.servlet.*;
import javax.servlet.http.*;

public class Test4Cookies extends HttpServlet {

private static final Cookie cookie = new Cookie( "hello" , "world" );


private static final String paramName = "foo";
private static final String successURI = "/success.htm";
private static final String failureURI = "/failure.htm";

public void doPost(HttpServletRequest req, HttpServletResponse res) {


if ( req.getParameter( paramName ) == null ) {
res.addCookie( cookie );
res.sendRedirect(req.getRequestURI() +"?"+ paramName +"=bar" );
}
else {
res.sendRedirect
(( req.getCookies().length == 0 ) ? failureURI : successURI
)
}

public void doGet(HttpServletRequest req, HttpServletResponse res) {


doPost(req, res);
}
}

10.11 Display ResultSet data in an HTML Table in Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0378.html

private int dumpData(java.sql.ResultSet rs, java.io.PrintWriter out)


throws Exception {
int rowCount = 0;

out.println("<P ALIGN='center'><TABLE BORDER=1>");


ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// table header
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TH>" + rsmd.getColumnLabel(i + 1) + "</TH>");
}
out.println("</TR>");
// the data
while (rs.next()) {
rowCount++;
out.println("<TR>");
for (int i = 0; i < columnCount; i++) {
out.println("<TD>" + rs.getString(i + 1) + "</TD>");
}
out.println("</TR>");
}

10.10 Test for Cookies


out.println("</TABLE></P>");
return rowCount;
}

10.12 Specify the filename to be used for a file sent by a Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0387.html

Say that your servlet called ""/servlet/GetFile" send back a file to a client request. That file needs to
be saved by the client. If you do nothing, the browser will suggest "GetFile" as the filename.

To specify the correct filename

String filename = "abc.dat" ;


File textFile = new File(filename);
response.setHeader("Content−length",Integer.toString(textFile.length()));
response.setHeader("Content−type","application/octetstream");
response.setHeader("Content−disposition","inline; filename=" + filename );

// open the file and write it in the OutputStream

NOTE: For PDF output, see this HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.13 Pass information to another servlet/jsp


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0401.html

You set attributes on your request object and then forward the request object to the other
servlet/jsp.

For a simple string

request.setAttribute("foo", "Real's HowTo");

A parameter received by the first servlet to the second one

String requestVar = request.getParameter("sitename");


request.setAttribute("foo", requestVar);

A Bean

MyBean myBean = new MyBean();


myBean.setFooProperty("Real's HowTo");
request.setAttribute("foo", myBean);

Then you forward the request

10.12 Specify the filename to be used for a file sent by a Servlet


RequestDispatcher dispatch = request.getRequestDispatcher("next.jsp");
dispatch.forward(request, response);

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.14 Handle PDF output


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0404.html

• Set the content−type of the response to "application/pdf", ex.


response.setContentType("application/pdf");
• Add a dummy parameter on the end of the url, like:
http://x.y.z/DoGenCompStmt?filename=dummy.pdf
because IE ignores content−types, so you need to give it a hint, and the ".pdf" extension is
an easy way.
• Set the "content−length" on the response, otherwise the Acrobat Reader plugin may not
work properly, ex. response.setContentLength(bos.size());
• An additional thing that seems to help some IE browsers is to also have :
response.setHeader("Content−Disposition", "inline;filename=somepdf.pdf");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.15 Detect if the connection is via a secure channel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0415.html

Use the servlet request's isSecure() or getAuthType() methods. Or you look at these HTTP headers
: CERT_KEYSIZE , CERT_KEYSIZE, HTTPS_KEYSIZE

Note: for a javascript solution see this HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.16 In a Servlet, check if Form Field is present


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0443.html

public isDefined(HttpServletRequest req, String fieldNameToSearchFor) {

10.14 Handle PDF output


return req.getParameterMap().containsKey(fieldNameToSearchFor);
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.17 Get the root dir of a web app


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0519.html

In a JSP

String path = application.getRealPath("/");

In a Servlet

String path = getServletContext.getRealPath("/");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.18 Get client IP address from JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0363.html

<%
out.print( request.getRemoteAddr() );
out.print( request.getRemoteHost() );
%>

10.19 Output a binary stream from a JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0366.html

You can't.

From JSP, only character stream should be used.

JSP pages were designed for *text* output. The "out" object is a Writer, which means it will play
games with text encoding.

For binary output, like PDF or dynamically generated GIF, it's a better idea to use a servlet.

10.17 Get the root dir of a web app


Having said that, since a JSP will be converted to a servlet, it's possible to modifed the output
stream.

[image.jsp]

<%@ page import="java.io.*" %>


<%@ page import="java.net.*" %>
<%@page contentType="image/gif" %><%
OutputStream o = response.getOutputStream();
InputStream is =
new URL("http://myserver/myimage.gif").getInputStream();
byte[] buf = new byte[32 * 1024]; // 32k buffer
int nRead = 0;
while( (nRead=is.read(buf)) != −1 ) {
o.write(buf, 0, nRead);
}
o.flush();
o.close();// *important* to ensure no more jsp output
return;
%

Thanks to Benjamin Grant for the bug fix.

10.20 Use a connection cache from JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0380.html

Jaguar provides a very useful cache mechanism to speed up database requests. You can have
ODBC, JDBC or Oracle cached connections.

NOTE: Java component can't use cached ODBC connection, you need to use a cached JDBC connection. If there is no JDBC driver available,
it's still possible to use the ODBC−JDBC provided by Sun. But performance of such a bridge is poor and the reliability is not good in a
multi−threaded environment.

To define a cache using ODBC−JDBC (bridge) connection, follow these steps:

1. Define a regular System DSN (through the ODBC Administration panel)


2. In jaguar, you define the cache :
1. General Tab : Server name = jdbc:odbc:YourSystemDSNName with user/pwd
2. Driver Tab : DLL or class name = sun.jdbc.odbc.JdbcOdbcDriver with JDBC radio
button selected
3. Cache Tab : checkbox cache−by−name checked

<%@page contentType="text/html"%>
<html>
<head><title>JSP Page</title></head>
<body>
<%@ page import="java.sql.*" %>
<%
com.sybase.jaguar.jcm.JCMCache jcmCache= null;
java.sql.Connection dbConn = null;
String jcmCacheString = "mycachename";
String msg = "";

try {
jcmCache =

10.20 Use a connection cache from JSP


com.sybase.jaguar.jcm.JCM.getCacheByName(jcmCacheString);
dbConn =
jcmCache.getConnection(com.sybase.jaguar.jcm.JCMCache.JCM_WAIT);

Statement stmt = dbConn.createStatement();


ResultSet rs =
stmt.executeQuery
("select msg from messages where msgid='00001'");

if(rs != null) {
while(rs.next()) {
msg = rs.getString("msg");
}
}
rs.close();
dbConn.close();
}
catch (Exception e) {
out.println("OUPS " + e.getMessage() + "<BR>");
}
%>
msgtext =
<i><%= msg %></i>
</body>
</html>

Instead of hard−coding the cache name into your java component, make the name available
through a Property (of the Environment) of the Web application. This way your components are
more flexible and you are using the "J2EE way" to make a connection. In this example,
myconnection contains the cache name to be used.

javax.naming.InitialContext ctx = new javax.naming.InitialContext();


javax.sql.DataSource ds = (javax.sql.DataSource)
ctx.lookup("java:comp/env/jdbc/myconnection");
java.sql.Connection con = ds.getConnection();
java.sql.PreparedStatement stmt = con.prepareStatement(sql);
java.sql.ResultSet rs = stmt.executeQuery();

while (rs.next()) {
//do something
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.21 Read a Web Application property


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0381.html

Web Application properties are defined in the WEB−INF/web.xml deployment descriptor (in between
the <webapp> </webapp> tag)

<env−entry>
<env−entry−name>docPath</env−entry−name>
<env−entry−value>c:/doc/doc1</env−entry−value>

10.21 Read a Web Application property


<env−entry−type>java.lang.String</env−entry−type>
</env−entry>

<env−entry>
<env−entry−name>docUser</env−entry−name>
<env−entry−value>net1</env−entry−value>
<env−entry−type>java.lang.String</env−entry−type>
</env−entry>

Then from your JSP or Servlet,

Context env = (Context) new InitialContext().lookup("java:comp/env");


String docBase = (String) env.lookup("docPath");
String docBaseUser = (String) env.lookup("docUser");

10.22 Use EJB from JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0396.html

EJB with constructor with no parameter

<jsp:useBean id="myBean" scope="session" class="com.company.MyBean"/>

EJB with constructor with parameters

<%
com.company.MyBean bean=new com.company.MyBean(1, 2, 3, 4);
session.putAttribute("myBean", bean);
%>

10.23 Define a method in a JSP page


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0410.html

<%!
public String sayHello(){
return "Hello";
}
%>

<%= sayHello() %>

10.24 Precompile JSP pages


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0414.html

Some JSP containers (as per section 8.4.2 of the JSP 1.2 specification) support the capability of
precompiling a JSP page.

10.22 Use EJB from JSP


To precompile a JSP page, access the page with a query string of ?jsp_precompile

http://hostname.com/mywebapp/mypage.jsp?jsp_precompile

The JSP page will not be executed. If the container supports precompilation, the JSP page will be
compiled if necessary.

Here a JSP page that will scan the current directory (and subdirectories) to precompile all JSP
found.

<%@ page contentType="text/html;charset=UTF−8" language="java" %>


<%@ page import="javax.servlet.*"%>
<%@ page import="javax.servlet.http.*,javax.servlet.jsp.*"%>
<%@ page import="java.util.Set,java.util.Iterator,java.io.IOException"%>

<%! private void compileAllJsps


(PageContext pageContext, JspWriter out,
HttpServletRequest request,HttpServletResponse response,
String uripath)
throws IOException, ServletException {

Set set = pageContext.getServletContext().getResourcePaths(uripath);


for (Iterator iter = set.iterator(); iter.hasNext();) {
String uri = (String) iter.next();
if (uri.endsWith(".jsp")) {
out.write("<li>"+ uri +"</li>");
out.flush();
RequestDispatcher rd =
getServletContext().getRequestDispatcher(uri);
if (rd == null) {
throw new Error(uri +" − not found");
}
rd.include(request, response);
}
else if (uri.endsWith("/")) {
compileAllJsps(pageContext, out, request, response, uri);
}
}
}
%>

<html><head><title>Precompiling *.JSPs</title></head>
<body><h4>Precompiling *.JSPs:</h4>
<ul>
<%
HttpServletRequest req = new HttpServletRequestWrapper(request) {
public String getQueryString() {
// can be "jsp_precompile=true"
return "jsp_precompile";
};
};
compileAllJsps(pageContext, out, req, response, "/");
%>
</ul>
<h4>Done.</h4>
</body> </html>

NOTE: Many Application servers provide an utility to precompile JSP pages (ex. EAServer, BEAWLS). Check for a JSPC command file.

10.22 Use EJB from JSP


10.25 Get a list of directories for JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0417.html

<h1>Directories</h1>
<ul>
<%
String root="c:/Repository/WebApplication/mydocs/javadoc/";
java.io.File file;
java.io.File dir = new java.io.File(root);

String[] list = dir.list();

if (list.length > 0) {

for (int i = 0; i < list.length; i++) {


file = new java.io.File(root + list[i]);
if (file.isDirectory()) {
%>
<li><a href="javadoc/<%=list[i]%>" target="_top"><%=list[i]%></a><br>
<%
}
}
}
%>
</ul>

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.26 Use and share a class in JSP pages


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0508.html

I have a class

public class Hello {


public String say() {
return "Hello";
}
}

and I need to use it in many JSP pages using

<%= say() %>

They are many to achieve that goal :

• Create a Java class with the method in it, compile it, and deploy the resulting .class file(s) in your
webapp's WEB−INF/class directory.
<%
Hello h = new Hello();

10.25 Get a list of directories for JSP


out.print(h.say());
%>
• Create a JAR file containing the .class file(s) and deploy the resulting JAR file via your webapp's
WEB−INF/lib directory.
<%
Hello h = new Hello();
out.print(h.say());
%>
• Create a tag library for it, deploy it via the webapp's WEB−INF/tld directory.

TAG source code

TAG source code :

package test;

import java.io.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class HelloTag extends TagSupport {


public int doStartTag() throws JspException
{
try {
pageContext.getOut().println("Hello");
} catch (IOException e) {
}

return SKIP_BODY;
}
}

the resulting class should go in the WEB−INF/class directory.

TLD configuration (in the WEB−INF/tlds as hello.tld)

<taglib>
<tag>
<name>hello</name>
<tagclass>test.HelloTag</tagclass>
</tag>
</taglib>

and to use the tag

<%@ taglib prefix="ht" uri="WEB−INF/tlds/hello.tld" %>


...
<ht:hello/>
• Create the desired method at the top of the page and copy it from page to page
<%!
public static String say() {
return "Hello";
}
%>
• Create an "include file" (say hello.inc), place the method noted above in it, and include it at the
top of each JSP page
<%@ include file="hello.inc" %>

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

10.25 Get a list of directories for JSP


Written and compiled by Réal Gagnon ©1998−2005
[ home ]

10.27 Get the root dir of a web app


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0519.html

In a JSP

String path = application.getRealPath("/");

In a Servlet

String path = getServletContext.getRealPath("/");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.28 Launch an applet from a JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0534.html

The jsp:plugin tag will generate the right html code to load your Applet.

<jsp:plugin type="applet"
code="TestApplet.class"
width="500"
height="300">

<jsp:params>
<jsp:param name="message" value="Hello, world"/>
<jsp:param name="action" value="<%=AppletAction%>"/>
</jsp:params>

<jsp:fallback>
<p> unable to start plugin </p>
</jsp:fallback>
</jsp:plugin>

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

10.29 Prevent caching of a JSP output


Current version of this HowTo :

10.27 Get the root dir of a web app


http://www.rgagnon.com/javadetails/../javadetails/java−0590.html

You will need to set the appropriate HTTP header attributes.

<%
response.setHeader("Cache−Control","no−cache");
response.setHeader("Pragma","no−cache");
response.setDateHeader ("Expires", −1);
%>

However, cache handling is tricky with IE brower.

See http://support.microsoft.com/kb/q222064/.

By adding a second HEAD is supposed to solve the problem!

<%
response.setHeader("Cache−Control","no−cache");
response.setHeader("Pragma","no−cache");
response.setDateHeader ("Expires", −1);
%>
<HTML>
<HEAD>
</HEAD>
<BODY>
my page body

</BODY>
<HEAD>
<META HTTP−EQUIV="PRAGMA" CONTENT="NO−CACHE">
<META HTTP−EQUIV="Expires" CONTENT="−1">
</HEAD>
</HTML>

NOTE: Pragma: no−cache prevents caching only when used over a secure connection, Expires: −1
should do the job over unsecure conection.

See also this HowTo and this one.

10.30 Call another EJB


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0384.html

InitialContext ctx = new InitialContext();


Object objref = ctx.lookup("MyPackage/MyEJB");
MyEJBHome home = (MyEJBHome)
PortableRemoteObject.narrow(objref, MyEJBHome.class);
return (MyEJB) home.create();

10.31 Keep java files generated from JSP (BEA WLS)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0446.html

10.30 Call another EJB


Set the 'keepgenerated' parameter in weblogic.xml to 'true'

<jsp−descriptor>
<jsp−param>
<param−name>
keepgenerated
</param−name>
<param−value>
true
</param−value>
</jsp−param>
</jsp−descriptor>

or, with weblogic.jar in the classpath,

java weblogic.jspc −keepgenerated Your.jsp

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.32 Get the server version (BEA WLS)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0447.html

<%@page import = "weblogic.common.internal.VersionInfo"%>


...
<%VersionInfo serverVersion = VersionInfo.theOne();%>
...
%=serverVersion.getImplementationVersion()%

or from the command line

java −cp weblogic.jar weblogic.version

Thanks to Frederic Close for the tip!

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.33 Quickly create a Web application with BEA WLS


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0449.html

To create a web application without an EAR or WAR, follow these steps :

1. Open a Shell window in %BEA%\user_projects\domains\[mydomain]\applications


2. Run this script : ..\setenv.cmd

10.32 Get the server version (BEA WLS)


3. Type this command : md testapp
4. Type this command : md testapp\WEB−INF
5. Run this program : java weblogic.marathon.ddinit.WebInit testapp

and that's all.

To configure your new application, run this program java weblogic.marathon.Main testapp

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.34 Nicely display WEB.XML informations


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0451.html

A web.xml file contains informations about a web application hosted by a application server. While
it's possible to consult the data using a regular text editor, it maybe easier to use a special
stylesheet to nicely format the data for easy browsing.

I found a nice generic stylesheet on the Web and adapted it a little bit for that purpose. Here the
modified xsl file, the css file, a sample web.xml.

See the sample output if your browser supports XML/XSL transformation.

Attach the xsl to the xml by adding this line to the xml file :

<?xml version="1.0" encoding="UTF−8"?>


<?xml−stylesheet type="text/xsl" href="tree−view.xsl"?>
...

or do the transformation in Java, for a hint see this How−to.

Here an ASP page (yeah I know...) which accepts as a parameter an XML filename and transforms
the passed filename using the XSL. As an added bonus, the original XML filename is displayed (you
will need this XSL).
<META http−equiv="Content−Type" content="text/html; charset=ISO8859−1">
<%@ LANGUAGE="JScript" %>
<%
Response.buffer = true;
var xmlfile;
var oXML;
var oXSL;
var oXSLTemplate;
var oXSLProcessor;
var SrcXSL;
var SrcXML;

// get the PARAM=??? (assumes you have used GET request method!)...
// assume something like http://.../docxml.asp?xmlfile=myxml.xml
xmlfile = '' + Request.QueryString('xmlfile');

// get the source file (XML and XSL) paths

10.34 Nicely display WEB.XML informations


SrcXML = Server.MapPath(xmlfile);
SrcXSL = Server.MapPath('xmldoc/tree−view2.xsl');

// create documents for the XML and XSL...


oXML = Server.CreateObject('Msxml2.DOMDocument');
oXSL = Server.CreateObject('Msxml2.FreeThreadedDOMDocument');

// load the XML and XSL into your documents...


// we don't want to waste time validating the file
oXSL.load(SrcXSL);
oXML.validateOnParse = false ;
oXML.async = false ;
oXML.resolveExternals = false ;

oXML.load(SrcXML);

// create the XSL template and processor...


oXSLTemplate = Server.CreateObject('Msxml2.XSLTemplate');
oXSLTemplate.stylesheet = oXSL;
oXSLProcessor = oXSLTemplate.createProcessor;

// place the ?xmlfile=xxx value into the XSL processor...


oXSLProcessor.addParameter('xmlfile',xmlfile,'');

// tell the XSL processor of the XML you want to have transformed...
oXSLProcessor.input = oXML;

try {
oXSLProcessor.transform ;
Response.write(oXSLProcessor.output);
}
catch (e) {
Response.write
('The file ' +e.url + ' is not valid. Reason: ' + e.reason );
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

10.35 Reverse the CLASSLOADER order (BEA)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0551.html

By default, Weblogic loads a class by asking the parent classloader to load the required class. This
can be a problem, if you have a JAR version in the server LIB directory and your web app requires
an another version.

ref : WebLogic Server Application Classloader Overview

To make sure that your web app will use the JAR located in its WEB−INF\LIB, create a file called
weblogic.xml in the WEB−INF directory with the content :

<!DOCTYPE weblogic−web−app PUBLIC

10.35 Reverse the CLASSLOADER order (BEA)


"−//BEA Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810−web−jar.dtd">

<weblogic−web−app>
<container−descriptor>
<prefer−web−inf−classes>true</prefer−web−inf−classes>
</container−descriptor>
</weblogic−web−app>

10.36 Detect change in JSP and recompile (BEA)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0562.html

By default, if you deployed an application in exploded mode, BEA WLS doesn't recompile a
modified JSP. You change this behaviour by adding this directive in a weblogic.xml configuration
file.

<jsp−descriptor>
<jsp−param>
<param−name>page−check−seconds</param−name>
<param−value>60</param−value>
</jsp−param>
</jsp−descriptor>

page−check−seconds sets the interval, in seconds, at which WLS checks to see if JSP files have
changed and need recompiling. Dependencies are also checked and recursively reloaded if
changed.

If set to 0, pages are checked on every request. If set to −1, page checking and recompiling is
disabled.

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

10.36 Detect change in JSP and recompile (BEA)


11 Language
11.1 java−language

11.2 * Read me *
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0290.html

If you can't find what you are looking here, you may want to look at these other sites :

Java Glossary
The Java Developers Almanac 1.4 (exampledepot.com)
Sun Developers Online Community

Also check out my Java links page.

Usenet's newgroups are very useful too. Check out the comp.lang.java.* groups on your favorite
Usenet newserver.

Specialized server from vendors can be accessed to obtain support :

• forums.sybase.com

Easerver and Powerbuilder


• news.gmane.org

Netbeans, look for the hierarchy gmane.comp.java.netbeans.*


• news.eclipse.org

Eclipse, need to ask for username first at http://www.eclipse.org/newsgroups/register.php.


• news.mozilla.org

Mozilla
• msnews.microsoft.com

Microsoft
• news.software.ibm.com

IBM (WebSphere)
• newsgroups.bea.com

BEA WebLogic

11 Language
11.3 Use a Hashtable
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0027.html

Hashtables are very useful for maintaining a 1−to−1 relationship between Objects. With an arbitary
key, you can retrieve easily an Object. In the following example, we retrieve a String array with a
String.

String[] array1 = {"A","B","C"};


String[] array2 = {"X","Y","Z"};
String[] array3 = {"1","2","3"};

Hashtable arrays = new Hashtable();


arrays.put("Array1", array1);
arrays.put("Array2", array2);
arrays.put("Array3", array3);

String[] resultArray = (String[])(arrays.get("Array2"));


System.out.println
(resultArray[0] + ", " + resultArray[1] + ", " + resultArray[2]);

11.4 Scan the content of a hashtable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0032.html

Enumeration keys = hash.keys();


while( keys.hasMoreElements() ) {
Object key = keys.nextElement();
Object value = hash.get(key);
}

11.5 Call a method dynamically (Reflection)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0031.html

import java.lang.reflect.*;
import java.io.*;

public class TestReflect {

public static void main(String s[]) throws Exception{


String aClass;
String aMethod;
// we assume that called methods have no argument
Class params[] = {};
Object paramsObj[] = {};

while (true) {
aClass = lineInput("\nClass : ");
aMethod = lineInput("Method: ");
// get the Class
Class thisClass = Class.forName(aClass);

11.3 Use a Hashtable


// get an instance
Object iClass = thisClass.newInstance();
// get the method
Method thisMethod = thisClass.getDeclaredMethod(aMethod, params);
// call the method
System.out.println
(thisMethod.invoke(iClass, paramsObj).toString());
}
/* Output examples:
Class : Class1
Method: class1Method2
### Class 1, Method2 ###

Class : java.util.Date
Method: toString
Sat Aug 11 13:18:39 EDT 2007

Class : java.util.Date
Method: getTime
1186852732140
*/
}

public static String lineInput (String prompt) throws IOException {


BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print(prompt);
return input.readLine();
}

class Class1 {
public String class1Method1() {
return "*** Class 1, Method1 ***";
}

public String class1Method2() {


return "### Class 1, Method2 ###";
}
}

The next example calls a class method with 2 arguments :

import java.lang.reflect.*;

public class TestReflect {

public static void main(String[] args) throws Exception {


TestReflect.invoke("Class1", "say", new Class[] {String.class, String.class},
new Object[]
{new String("Hello"), new String("World")});
/*
output :
Hello World
*/
}

public static void invoke


(String aClass, String aMethod, Class[] params, Object[] args)
throws Exception {
Class c = Class.forName(aClass);

11.3 Use a Hashtable


Method m = c.getDeclaredMethod(aMethod, params);
Object i = c.newInstance();
Object r = m.invoke(i, args);
}
}

class Class1 {
public void say( String s1, String s2) {
System.out.println(s1 + " " + s2);
}
}

11.6 Create an object from a string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0351.html

import java.lang.reflect.*;

Class [] classParm = null;


Object [] objectParm = null;

try {
String name = "com.rgagnon.MyClass";
Class cl = Class.forName(name);
java.lang.reflect.Constructor co = cl.getConstructor(classParm);
return co.newInstance(objectParm);
}
catch (Exception e) {
e.printStackTrace();
return null;
}

Another example, but this time we are passing a parameter to the constructor and calling a method
dynamically.

public class Test {


public static void main(String args[]) {

try {
String name = "java.lang.String";
String methodName = "toLowerCase";

// get String Class


Class cl = Class.forName(name);

// get the constructor with one parameter


java.lang.reflect.Constructor constructor =
cl.getConstructor
(new Class[] {String.class});

// create an instance
Object invoker =
constructor.newInstance
(new Object[]{"REAL'S HOWTO"});

// the method has no argument


Class arguments[] = new Class[] { };

11.6 Create an object from a string


// get the method
java.lang.reflect.Method objMethod =
cl.getMethod(methodName, arguments);

// convert "REAL'S HOWTO" to "real's howto"


Object result =
objMethod.invoke
(invoker, (Object[])arguments);

System.out.println(result);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

11.7 Get a variable value from the variable name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0038.html

import java.lang.reflect.*;

public class ReflectUtils {

public static void main(String[] args) throws Exception{


TestClass test = new TestClass();

System.out.println (ReflectUtils.getValueOf(test,"firstValue"));
System.out.println (ReflectUtils.getValueOf(test,"secondValue"));
System.out.println (ReflectUtils.getValueOf(test,"thirdValue"));

/*
output :
3.1416
42
Hello world
*/
}

public static Object getValueOf(Object clazz, String lookingForValue)


throws Exception {
Field field = clazz.getClass().getField(lookingForValue);
Class clazzType = field.getType();
if (clazzType.toString().equals("double"))
return field.getDouble(clazz);
else if (clazzType.toString().equals("int"))
return field.getInt(clazz);
// else other type ...
// and finally
return field.get(clazz);
}
}

class TestClass {
public double firstValue = 3.1416;
public int secondValue = 42;
public String thirdValue = "Hello world";

11.7 Get a variable value from the variable name


}

11.8 Launch an application from another application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0394.html

While you can exec("java myaotherapp"), it is more appropriate to instanciate and called the main
method of the other application.

For example, take this simple application :

public class Program2 {


public static void main(String arg[]) {
System.out.println("Hello from Program2");
}
}

To call the above application from another

public class Program1a {


public static void main(String arg[]) {
System.out.println("Hello from Program1a");
new Thread(){
public void run() {
Program2.main(new String[]{});}
}.start();
}

The above example is used when the class is hard−coded.

The dynamic version is little more tricky.

public class Program1b {


public static void main(String arg[]) {
System.out.println("Hello from Program1b");
new Program1b().execute("Program2");
}

public void execute(String name) {


Class params[] = {String[].class};
// if you need parameters
// String[] args = new String[] { "Hello", "world" };
// Class params[] = new Class[] { args.getClass() });
try {
Class.forName(name).
getDeclaredMethod("main", params).
invoke(null, new Object[] {new String[] {}});
}
catch(Exception e){ e.printStackTrace();}
}
}

11.8 Launch an application from another application


Launch many programs using Thread and use join() to wait for the completion.

[Program2.java]
public class Program2 {
public static void main(String arg[]) {
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
System.out.println("Hello from Program2");
}
}

[Program1a.java]
public class Program1a {
public static void main(String arg[]) throws Exception{
System.out.println("Hello from Program1a");
Thread t1 = new Thread(){
public void run() {
Program2.main(new String[]{});}
};
t1.start();
t1.join();
System.out.println("Hello from Program1a");
}
}

The output :

C:\>java Program1a
Hello from Program1a
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program1a

11.9 Create a java source dynamically, compile and call


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0039.html

import java.io.*;
import java.util.*;
import java.lang.reflect.*;

public class MakeTodayClass {


Date today = new Date();
String todayMillis = Long.toString(today.getTime());
String todayClass = "z_" + todayMillis;
String todaySource = todayClass + ".java";

public static void main (String args[]){


MakeTodayClass mtc = new MakeTodayClass();
mtc.createIt();
if (mtc.compileIt()) {
System.out.println("Running " + mtc.todayClass + ":\n\n");
mtc.runIt();
}
else

11.9 Create a java source dynamically, compile and call


System.out.println(mtc.todaySource + " is bad.");
}

public void createIt() {


try {
FileWriter aWriter = new FileWriter(todaySource, true);
aWriter.write("public class "+ todayClass + "{");
aWriter.write(" public void doit() {");
aWriter.write(" System.out.println(\""+todayMillis+"\");");
aWriter.write(" }}\n");
aWriter.flush();
aWriter.close();
}
catch(Exception e){
e.printStackTrace();
}
}

public boolean compileIt() {


String [] source = { new String(todaySource)};
ByteArrayOutputStream baos= new ByteArrayOutputStream();

new sun.tools.javac.Main(baos,source[0]).compile(source);
// if using JDK >= 1.3 then use
// public static int com.sun.tools.javac.Main.compile(source);
return (baos.toString().indexOf("error")==−1);
}

public void runIt() {


try {
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(todayClass);
Object iClass = thisClass.newInstance();
Method thisMethod = thisClass.getDeclaredMethod("doit", params);
thisMethod.invoke(iClass, paramsObj);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

11.10 Access the enclosing class from an inner class


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0037.html

public class TestIt {


public static void main(String a[]){
new TestIt().doit();
/*
output :
Hello world!
*/
}
public void doit() {
new InnerClass().sayHello();
}
public void enclosingClassMethod(){

11.10 Access the enclosing class from an inner class


System.out.println("Hello world!");
}

class InnerClass {
public void sayHello() {
TestIt.this.enclosingClassMethod();
}
}
}

or

public class TestIt {


TestIt testItClass = this;

public static void main(String a[]){


new TestIt().doit();
/*
output :
Hello world!
*/
}

public void doit() {


new InnerClass().sayHello();
}

public void enclosingClassMethod(){


System.out.println("Hello world!");
}

class InnerClass {
public void sayHello() {
testItClass.enclosingClassMethod();
}
}
}

11.11 Access inner class from outside


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0425.html

public class TestIt {


public static void main(String[] args) {
Outer outer = new Outer();
outer.new Inner().hello();
/*
output :
Hello from Inner()
*/
}
}

class Outer {
public class Inner {
public void hello(){
System.out.println("Hello from Inner()");

11.11 Access inner class from outside


}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.12 Use globally defined constants


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0040.html

Via a class
This technique is useful for constants defined on a corporate level. They are very generic by nature.
The CONSTANT class is included in the classpath.

public class CONSTANT {


public static final integer SUCCESS = 1;
public static final integer FAILURE = −1;
public static final integer NOTFOUND = 0;
}

Since the members of the class are defined as "static", there is no need to instantiate the class. To
use a constant, simply use CONSTANT.[constant name]

if (myMethod()==CONSTANT.SUCCESS) {
...;
}
else {
...;
}

Via an interface
This technique can be used if the constants are not really global but especially designed to be used
in a specific application for example. An application−level class needs to implement the interface to
be able to see the constant definitions.

public interface APPCONSTANT {


public static final String APPNAME = "The Super APP";
public static final String APPVERSION = "version 1.0";
public static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver";
}

then to use a constant, simply implement the interface

public class TheAppFrame extends Frame


implements APPCONSTANT {

TheAppFrame {
...
setTitle(APPNAME);
...
}
...

11.12 Use globally defined constants


}

NOTE : This is not considered as good practice (depending on who you are talking to!) to use an
interface this way.

NOTE: By convention, constant name are always in CAPITALS.

JDK1.5
JDK1.5 import statement can be used to import only static member from a class.

import static java.lang.Math.*;

public class DemoImport {


public static void main(String[] args) {
double x = 16.0;
System.out.println(abs(x));
System.out.println(PI);
// instead of System.out.println(Math.abs(x));
// System.out.println(Math.PI);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.13 Serialize an Object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0042.html

To serialize an object, it must implements the Serializable interface. The object needs 2 functions
with these signatures

private void writeObject(java.io.ObjectOutputStream out)


throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;

Many standard Java objects already implements the Serializable interface so there is almost
nothing to do.

In the following snippet, we use a Vector to simulate a Queue.

First the Queue state is saved to a file.

Then rename main to main_serialize and main_reload to main and compile. Now the snippet read
the file to reload the Queue from the data previously saved.

import java.util.Vector;
import java.io.*;

public class Queue extends Vector {


/*

11.13 Serialize an Object


** FIFO
*/
Queue() {
super();
}

void put(Object o) {
addElement(o);
}

Object get() {
if (isEmpty()) return null;
Object o = firstElement();
removeElement(o);
return o;
}

Object peek() {
if (isEmpty()) return null;
return firstElement();
}

public static void main(String args[]) {


Queue theQueue;

theQueue = new Queue();


theQueue.put("element 1");
theQueue.put("element 2");
theQueue.put("element 3");
theQueue.put("element 4");
System.out.println(theQueue.toString());

// serialize the Queue


System.out.println("serializing theQueue");
try {
FileOutputStream fout = new FileOutputStream("thequeue.dat");
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(theQueue);
oos.close();
}
catch (Exception e) { e.printStackTrace(); }
}

public static void main_load(String args[]) {


Queue theQueue;

theQueue = new Queue();

// unserialize the Queue


System.out.println("unserializing theQueue");
try {
FileInputStream fin = new FileInputStream("thequeue.dat");
ObjectInputStream ois = new ObjectInputStream(fin);
theQueue = (Queue) ois.readObject();
ois.close();
}
catch (Exception e) { e.printStackTrace(); }
System.out.println(theQueue.toString());
}
}

Note : See this How−to to serialize using XML format.

11.13 Serialize an Object


11.14 Serialize an Object over a socket
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0043.html

From the client side, you open a Socket and then

oos = new ObjectOutputStream(socket.getOutputStream());


oos.writeObject(someObject);

On the server side, you use the ObjectInputStream.readObject method.

NOTE:
If the OutputStream is kept open and you modify your object and resend it, you will not see a
change on the server side. That's because Java keeps objects sent in an internal cache and the old
version will be taken in account instead of the new one. The fix is to do an
ObjectOutputStream.reset() before re−sending the object or open a new connection each time.

11.15 Easily remove my debugging code


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0130.html

Unlike a C/C++ compiler, there is no JAVA compiler directive to exclude certain source code parts
from compilation. By making the release version of a class smaller, the loading process will faster.

Without editing the source to remove the debugging codes, you can rely on the simple optimization
that the JAVA compiler always do. If a if expression is always false, the code in the if statement will
not be included in the compilation. Not only the resulting class will be smaller, but the execution time
will be a little faster too by not making unnecessary test.

The technique is simple. In the development environment, you have a class called Debug.

public class Debug {


public static final boolean RELEASE = true;
}

In your source, when you need some debugging codes, you included them in a if statement like

if (Debug.RELEASE) {
System.out.println("The value of i is " + i);
}

During compilation, since Debug.RELEASE is always true, the code will be present. In the
production environment, the Debug class looks like this:

public class Debug {


public static final boolean RELEASE = false;
}

11.14 Serialize an Object over a socket


When compiling in that environment, the debugging code will be absent from the class file since
Debug.release is always false.

Another way is to simply close the out stream.


(System.out.println() will be present in your class but the output is disabled).

public class TestOut {


public TestOut() { }

public static void main(String s[]) {


System.out.close(); // may want System.err.close() too
for (int i=0; i <100000; i++){ System.out.print(".");}
}
}

11.16 Obtain from where a Class is loaded


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0300.html

public class LoadingFromWhere {


public static void main(String args[]){
LoadingFromWhere s = new LoadingFromWhere();
s.doit();
}

public void doit() {


System.out.println(this.getClass().getName() + " is loaded from " +
getClass().getProtectionDomain().getCodeSource().getLocation());

MyClass s = new MyClass();


}
}

class MyClass {
MyClass() {
System.out.println
(this.getClass().getName() + " is loaded from " +
this.getClass().getProtectionDomain().getCodeSource().getLocation());
}
}

The output

>java LoadingFromWhere
LoadingFromWhere is loaded from file:/C:/temp/
MyClass is loaded from file:/C:/temp/

Other technique (doesn't work with jar)

public class FromWhere {


public static void main(String args[]){
Class theClass = FromWhere.class;
java.net.URL u = theClass.getResource("");
System.out.println("This class (FromWhere) is located at : " + u);
}
}

11.16 Obtain from where a Class is loaded


The output

> java FromWhere


This class (FromWhere) is located at : file:/C:/temp/

See these related HowTo's : 1 2

11.17 Get the class name in a static method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0402.html

public class ClassFromStatic {

public static void main(java.lang.String[] args) {


someStaticMethod();
}

public static void someStaticMethod() {


System.out.println
("I'm in " + new CurrentClassGetter().getClassName() + " class");
}

public static class CurrentClassGetter extends SecurityManager {


public String getClassName() {
return getClassContext()[1].getName();
}
}
}

11.18 Get the current method name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0420.html

JDK1.4

public class MyTest {


public static void main(String args[]) {
new MyTest().doit();
}
public void doit() {
System.out.println
(new Exception().getStackTrace()[0].getMethodName());
}
}

The output

doit

JDK1.5
While the above snippet is not bad, it is expensive since we need to create an Exception.

11.17 Get the class name in a static method


With JDK1.5, a new technique is available.

public class Test {


public static void main(String args[]) {
trace(Thread.currentThread().getStackTrace());
new Test().doit();
trace(Thread.currentThread().getStackTrace());
}
public void doit() {
trace(Thread.currentThread().getStackTrace());
doitagain();
}
public void doitagain() {
trace(Thread.currentThread().getStackTrace());
}

public static void trace(StackTraceElement e[]) {


boolean doNext = false;
for (StackTraceElement s : e) {
if (doNext) {
System.out.println(s.getMethodName());
return;
}
doNext = s.getMethodName().equals("getStackTrace");
}
}
}

main
doit
doitagain
main

To get the calling method

public class Test {


public static void main(String args[]) {
new Test().doit();
}
public void doit() {
System.out.println(
Thread.currentThread().getStackTrace()[3].getMethodName());
}
}

See also this HowTo.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.19 Detect if a package is available


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0422.html

public class ClassUtils {

11.19 Detect if a package is available


public static void main(String args[]) {
System.out.println ("Swing " +
(ClassUtils.isAvailable("javax.swing.JComponent")?"present":"absent"));
System.out.println ("JAI " +
(ClassUtils.isAvailable("javax.media.jai.ImageJAI")?"present":"absent"));
System.out.println ("SAX " +
(ClassUtils.isAvailable("org.xml.sax.XMLReader")?"present":"absent"));
System.out.println ("ImaginaryClass " +
(ClassUtils.isAvailable("imaginary.ImaginaryClass")?"present":"absent"));
System.out.println ("Java3d " +
(ClassUtils.isJava3dAvailable()?"present":"absent"));
/*
output :
Swing present
JAI absent
SAX present
ImaginaryClass absent
Java3d absent
*/
}

public static boolean isAvailable(String className) {


boolean isFound = false;
try {
Class.forName(className, false, null);
isFound = true;
}
catch (ClassNotFoundException e) {
isFound = false;
}
return isFound;
}

public static boolean isJava3dAvailable() {


return isAvailable("javax.media.j3d.View");
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.20 Have a singleton


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0355.html

A singleton is a class that can be instantiated only one time in a JVM. Repeated calls always return
the same instance.

public class OnlyOne{


private static OnlyOne one = new OnlyOne();

private OnlyOne(){}

public static OnlyOne getInstance() { return one; }


}

11.20 Have a singleton


To use it

OnlyOne myOne = OnlyOne.getInstance();

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.21 Make methods that have unspecified number of


parameters
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0289.html

You pass an array of Objects.

public class Howto {


public static void main(String args[]) {
Howto howto = new Howto();
howto.myMethod
( new Object[] {"value 1", new Integer(2), "value n"} );
}

public void myMethod(Object parms[]) {


for (int i=0; i < parms.length; i++)
System.out.println(parms[i]);
}
}

NOTE : In JDK1.5, we have VARARGS parameters so this not needed anymore!

public class TestIt {


public static void main(String args[]) {
TestIt.doit
( "value 1", new Integer(2), "value n" );
/*
output :
value 1
2
value n
*/
}

public static void doit(Object ... parms) {


for(Object parm:parms) {
System.out.println(parm);
}
}
}

public class TestIt {


public static void main(String ... args) {
for(String arg:args) {
System.out.println(arg);
}
}

11.21 Make methods that have unspecified number of parameters


/*
output :
>java TestIt 1 2 3 how−to
1
2
3
how−to
*/
}

11.22 Multiple expressions in for loops


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0316.html

You do it "à la C".

public class MultipleFor{


public static void main (String [] args){
for (int i=0, j=0; i < 10; i++, j−−)
System.out.println ("i = " + i + " j= " + j);
}
}

11.23 Handle the List conflict


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0372.html

The List interface is declared in the java.util package and the List class is in the java.awt package.
So if both import are defined in your source you won't be able to compile properly because this will
cause a name conflict. The solution is to fully qualify the name used when you reference the List
class or interface.

import java.util.*;
import java.awt.*;

...
java.awt.List myAwtList = new java.awt.List();
...

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.24 Use a generic toString()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0432.html

A nice idea is to put this toString() into a base class so all the descendents inherit from it.

11.22 Multiple expressions in for loops


public class generictostring {

String hello = "world";


int i = 42;

public static void main(String args []) {


System.out.println(new generictostring().toString());
// generictostring{i=42, hello=world}
}

public String toString() {


java.util.Hashtable h = new java.util.Hashtable();
Class cls = getClass();
java.lang.reflect.Field[] f = cls.getDeclaredFields();
java.lang.reflect.AccessibleObject.setAccessible(f, true); //jdk1.2
for (int i = 0; i < f.length; i++) {
try {
h.put(f[i].getName(),f[i].get(this));
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (cls.getSuperclass().getSuperclass() != null) {
h.put("super", super.toString());
}
return cls.getName() + h;
}
}

Christian Ullenboom wrote:

Hi, your solution is fine, but has some drawbacks:


− it based on inheritance
− an attribute of a subclass cannot overlap an attribute of a superclass (because of hashtable)

So I changed your solution a bit:

// @author Christian Ullenboom


// @url http://java−tutor.com
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;

class ToStringHelper {
public static String toString( Object o ) {
ArrayList list = new ArrayList();
toString( o, o.getClass(), list );
return o.getClass().getName().concat( list.toString() );
}

private static void toString( Object o, Class clazz, ArrayList list ) {


Field f[] = clazz.getDeclaredFields();
AccessibleObject.setAccessible( f, true );
for ( int i = 0; i < f.length; i++ ) {
try {
list.add( f[i].getName() + "=" + f[i].get(o) );
}
catch ( IllegalAccessException e ) { e.printStackTrace(); }
}
if ( clazz.getSuperclass().getSuperclass() != null )

11.22 Multiple expressions in for loops


toString( o, clazz.getSuperclass(), list );
}
}

class Ober {
int i = 123;
private double d = 3.1415;
}

public class ToStringHelperTest extends Ober {


String hello = "world";
int i = 42;

public static void main(String args[]) {


Ober t = new ToStringHelperTest();
System.out.println( ToStringHelper.toString(t) );
// ToStringHelperTest[hello=world, i=42, i=123, d=3.1415]
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.25 Use Object.clone()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0433.html

Consider the following example.

import java.util.Date;

class MyData {

private Date aDate;

MyData() {
aDate = new Date();
}

public Date getDate() {


return aDate;
}
public void setdate(Date d) {
aDate = d;
}
}

public class DemoClone {

public static void main(String args[]) {

MyData mydata = new MyData();


Date d = mydata.getDate();
System.out.println(d);
d.setTime(1000);
System.out.println(d);

11.25 Use Object.clone()


System.out.println(mydata.getDate());
// Sat Apr 19 23:17:43 EDT 2003
// Wed Dec 31 19:00:01 EST 1969
// Wed Dec 31 19:00:01 EST 1969 which is no good
}
}

Even if aDate is declared as private, it is possible to modify because a Date object is mutable and
we have a reference to it. The solution is to return a copy of aDate, so even if you have reference to
it, any modification will be done on the copy, not the original.

import java.util.Date;

class MyData {

private Date aDate;

MyData() {
aDate = new Date();
}

public Date getDate() {


return (Date)aDate.clone();
}
public void setdate(Date d) {
aDate = d;
}
}

public class DemoClone {

public static void main(String args[]) {

MyData mydata = new MyData();


Date d = mydata.getDate();
System.out.println(d);
d.setTime(1000);
System.out.println(d);
System.out.println(mydata.getDate());
// Sat Apr 19 23:17:43 EDT 2003
// Wed Dec 31 19:00:01 EST 1969
// Sat Apr 19 23:17:43 EDT 2003 which is good
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.26 Static field, constructor and exception


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0444.html

Consider the following class

public class Foo {

11.26 Static field, constructor and exception


private static Bar b = new Bar();
...
}

class Bar {
public Bar ( ) throws Exception {
}
}

it will not compile because Bar() is declared to throw an exception.

To solve this situation, use a static block.

public class Foo {


static Bar bar ;

static {
try {
bar = new Bar() ;
}
catch ( Exception e ) {
e.printStackTrace() ;
}
}
}

class Bar {
public Bar ( ) throws Exception {
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.27 Use a Label break


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0500.html

Labelled breaks allow breaking out of several levels of nested loops inside a pair of curly braces.
This way, you can almost simulate a GOTO!

class JavaGoto {
public static void main(String args[]) {

int max = 10;


int limit = 5;
int j = 0;
out: { for( int row=0; row< max; row++ ) {
for( int col=0; col< max; col++ )
if( row == limit) break out;
j += 1;
}
}
System.out.println(j); // output 5

11.27 Use a Label break


}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.28 Put printStackTrace() into a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0537.html

public class TestException {


public static void main(String args[]) {
try {
throw new Exception("for no reason!");
}
catch (Exception e) {
e.printStackTrace();
}
}2
// output :
// java.lang.Exception: for no reason!
// at TestException.main(TestException.java:8)
}

You redirect the StackTrace to a String with a StringWriter/PrintWriter :

import java.io.PrintWriter;
import java.io.StringWriter;

public class TestException {


public static void main(String args[]) {
try {
throw new Exception("for no reason!");
}
catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
System.out.println(sw.toString().toUpperCase());
}
}
// output :
// JAVA.LANG.EXCEPTION: FOR NO REASON!
// AT TESTEXCEPTION.MAIN(TESTEXCEPTION.JAVA:7)
}

This can be useful if you want to format the StackTrace before showing it to the user.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

11.28 Put printStackTrace() into a String


11.29 Sort an array
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0008.html

[ArraySorter.java] JDK1.1

public class ArraySorter {


/*
** Sort in the same array
*/
public static void sort(Object[] a, Comparer comparer) {
sort(a, null, 0, a.length − 1, true, comparer);
}

/*
** Sort a and b, using a as the reference
*/
public static void sort(Object[] a, Object[] b,
int from, int to, boolean ascending, Comparer comparer) {
// No sort
if (a == null || a.length < 2) return;

// sort using Quicksort


int i = from, j = to;
Object center = a[ (from + to) / 2 ];
do {
if (ascending) {
while( (i < to) &(comparer.compare( center, a[i]) > 0) )
i++;
while( (j > from) &(comparer.compare(center, a[j]) < 0) )
j−−;
}
else {
// Decending sort
while( (i < to) &(comparer.compare( center, a[i]) < 0) )
i++;
while( (j > from) &(comparer.compare(center, a[j]) > 0) )
j−−;
}
if (i < j) {
// Swap elements
Object temp = a[i]; a[i] = a[j]; a[j] = temp;
// Swap in b array if needed
if (b != null) {
temp = b[i]; b[i] = b[j]; b[j] = temp;
}
}
if (i <= j) { i++; j−−; }
} while(i <= j);
// Sort the rest
if (from < j) sort(a, b, from, j, ascending, comparer);
if (i < to) sort(a, b, i, to, ascending, comparer);
}

public static interface Comparer {


/**
* The interface implementation should compare the two
* objects and return an int using these rules:
* if (a > b) return > 0;
* if (a == b) return 0;

11.29 Sort an array


* if (a < b) return < 0;
*/
public int compare(Object a, Object b);
}
}

[testArraySorter.java]

public class testArraySorter {


public static final ASCIIComparer asciiComparer = new ASCIIComparer();
public static void main(String args[]) {
if (args.length == 0)
System.out.println("give me some args to sort");
else {
ArraySorter.sort(args, asciiComparer);
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}

public static class ASCIIComparer implements ArraySorter.Comparer {


public int compare(Object a, Object b) {
return ((String)a).compareTo((String)b);
}
}
}

JDK1.4 case−sensitive

String[] myArray = new String[] {"foo","bar","baz"};


java.util.Arrays.sort(myArray);

case−insensitive

String[] myArray = new String[] {"foo","Bar","baz"};


java.util.Arrays.sort(myArray, java.text.Collator.getInstance());

11.30 Initialize multidimensional array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0036.html

Simply use braces...

static double[][] Rates = {


{0.50, 0.70, 0.40, 0.60},
{0.50, 1.10, 0.50, 0.80},
{0.80, 1.60, 0.70, 1.20},
{1.50, 2.90, 1.20, 2.10},
{2.50, 4.90, 2.00, 3.30},
{4.60, 8.50, 3.20, 5.00},
{6.40,11.00, 4.10, 6.00}
};

11.30 Initialize multidimensional array


11.31 Get array upperbound
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0280.html

class ArrayLength {
public static void main(String args[]) {
String[][] data = new String[3][4];
System.out.println("Dimension 1: " + data.length);
System.out.println("Dimension 2: " + data[0].length);
}
}

To get the number of dimensions :

class ArrayDim {
public static void main(String args[]) {
String[][] data = new String[3][4];
System.out.println("This array has " + getDim(data) + " dimensions");
// expected output :
// "This array has 2 dimensions"
}

public static int getDim(Object array ) {


int dim=0;
Class c = array.getClass();
while( c.isArray() ) {
c = c.getComponentType();
dim++;
}
return( dim );
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.32 Convert a String to an array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0368.html

NOTE: This HowTo was designed for JDK 1.0.2. Starting with version 1.4, the String class offers a
better way to split a String into an Array. It's the String.split(regexp) method. See this HowTo.

Thanks to T. GUIRADO

public String[] stringtoArray( String s, String sep ) {


// convert a String s to an Array, the elements
// are delimited by sep
StringBuffer buf = new StringBuffer(s);
int arraysize = 1;
for ( int i = 0; i < buf.length(); i++ ) {
if ( sep.indexOf(buf.charAt(i) ) != −1 )
arraysize++;

11.31 Get array upperbound


}
String [] elements = new String [arraysize];
int y,z = 0;
if ( buf.toString().indexOf(sep) != −1 ) {
while ( buf.length() > 0 ) {
if ( buf.toString().indexOf(sep) != −1 ) {
y = buf.toString().indexOf(sep);
if ( y != buf.toString().lastIndexOf(sep) ) {
elements[z] = buf.toString().substring(0, y );
z++;
buf.delete(0, y + 1);
}
else if ( buf.toString().lastIndexOf(sep) == y ) {
elements[z] = buf.toString().substring
(0, buf.toString().indexOf(sep));
z++;
buf.delete(0, buf.toString().indexOf(sep) + 1);
elements[z] = buf.toString();z++;
buf.delete(0, buf.length() );
}
}
}
}
else {
elements[0] = buf.toString();
}
buf = null;
return elements;
}

To transform back to String

public String arrayToString(String s[], String sep) {


int k;
String result = "";

k = s.length;
if (k > 0) {
result = s[0];
for (int i= 1 ; i < k; i++) {
result += sep + s[i] ;
}
}
return result;
}

11.33 Sort in reverse order


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0428.html

Arrays.sort (myArray, Collections.reverseOrder());

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.33 Sort in reverse order


11.34 Resize an array
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0431.html

Arrays cannot be resized dynamically. If you want a dynamic data structure with random access,
you use a Collection (Map, ArrayList,...).

If you need to expand, you can use System.arraycopy() method to copy the content of an array to
another one.

import java.lang.reflect.Array;

public class ArrayUtils {

public static void main (String arg[]) {


String s[] = new String[20];
System.out.println("The s array length is " + s.length); // 20
s = (String[])ArrayUtils.expand(s);
System.out.println("The s array length is " + s.length); // 30

int i[] = {1 ,2 ,3, 4};


System.out.println("The i array length is " + i.length); // 4
i = (int[])ArrayUtils.expand(i);
System.out.println("The i array length is " + i.length); // 6
}

public static Object expand(Object a) {


Class cl = a.getClass();
if (!cl.isArray()) return null;
int length = Array.getLength(a);
int newLength = length + (length / 2); // 50% more
Class componentType = a.getClass().getComponentType();
Object newArray = Array.newInstance(componentType, newLength);
System.arraycopy(a, 0, newArray, 0, length);
return newArray;
}
}

But a better way is to use a Vector or an ArrayList. ArrayList is roughly equivalent to Vector, except
that it is unsynchronized.

import java.util.ArrayList;

public class ArrayListDemo {


public static void main (String arg[]) {
ArrayListDemo x = new ArrayListDemo();
x.doit1();
x.doit2();
}

public void doit1() {


// single dimension
ArrayList list = new ArrayList();
list.add("a");
list.add("b");
int size = list.size(); // 2
System.out.println("Array 1 " +list.get(0); // a
}

11.34 Resize an array


public void doit2() {
// multi dimensions
ArrayList list = new ArrayList();
ArrayList l1 = new ArrayList();
l1.add("a");
ArrayList l2 = new ArrayList();
l2.add("b");
ArrayList l3 = new ArrayList();
l3.add("c");

list.add(l1);
list.add(l2);
list.add(l3);

int size1 = list.size(); // 3


int size2 = ((ArrayList)list.get(0)).size(); // 1
System.out.println("Array 2 "
+ ((ArrayList)list.get(1)).get(0)); // b
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.35 Dump array content


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0465.html

Convert the array to a List and then convert to String. This technique works only with classes and
not with primitives like int or double.

public class Test {


public static void main(String args[]) {
String s[] = {"a", "b", "c", "d"};

System.out.println(java.util.Arrays.asList(s).toString());
// output
// [a, b, c, d]
}
}

JDK1.5
java.utils.Arrays provides new ways to dump the content of an array. It's even possible to dump
muti−dimensional arrays.

public class Test {


public static void main(String args[]) {
String s[] = {"a", "b", "c", "d"};
double d [][]= {
{0.50, 0.70, 0.40, 0.60},
{0.50, 1.10, 0.50, 0.80}
};
System.out.println(java.util.Arrays.toString(s));
System.out.println(java.util.Arrays.deepToString(d));
// output

11.35 Dump array content


// [a, b, c, d]
// [[0.5, 0.7, 0.4, 0.6], [0.5, 1.1, 0.5, 0.8]]
}
}

You can also use the new shorthand notation to iterate through an array :

public class Test {


public static void main(String args[]) {
String s[] = {"a", "b", "c", "d"};
for (String element : s)
System.out.println(element);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.36 Initialize a static array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0475.html

import java.util.*;
import java.io.*;

class InitStaticArray {

static Integer[] integerArray;

static {
integerArray= new Integer[] {
new Integer(1),
new Integer(2),
new Integer(3),
new Integer(4),
};
}

public static void main(String args[]) {


for (int i=0; i <integerArray.length; i++){
System.out.println(integerArray[i]);
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.36 Initialize a static array


11.37 Sort an Hashtable
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0478.html

Data in hashtable are not sorted. We extract the keys and sort them.

import java.util.*;

public class HashtableTest {

static String[] array1 = {"C","B","A"};


static String[] array2 = {"1","2","3"};

public static void main(String args[]) {

Hashtable h = new Hashtable();


h.put(array1[0], array2[0]);
h.put(array1[1], array2[1]);
h.put(array1[2], array2[2]);

// unsorted keys output


Iterator it = h.keySet().iterator();
while (it.hasNext()) {
String element = (String)it.next();
System.out.println(element + " " + (String)h.get(element));
}

System.out.println("============");

// sorted keys output thanks to T. GUIRADO for the tip!


Vector v = new Vector(h.keySet());
Collections.sort(v);
it = v.iterator();
while (it.hasNext()) {
String element = (String)it.next();
System.out.println( element + " " + (String)h.get(element));
}
/*
output :
A 3
C 1
B 2
============
A 3
B 2
C 1
*/
}
}

NOTE : When possible always use an HashMap instead of an Hashtable. Since Hashtable methods
are synchronized they are slower than those in HashMap. See this Howto.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.37 Sort an Hashtable


11.38 Eliminate "[unchecked] unchecked call ..." compiler
warning
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0521.html

import java.util.*;

public class ArrayListGeneric {


public static void main(String[] args) {
ArrayList data = new ArrayList();
data.add("hello");
data.add("world");

Iterator<String> it = data.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}

When compiling the above class, the compiler (jdk1.5) emits the following warnings :

C:\ArrayListGeneric.java:21:
warning: [unchecked] unchecked call to add(E) as a member of the raw type
java.util.ArrayList
data.add("hello");
^
C:\ArrayListGeneric.java:22:
warning: [unchecked] unchecked call to add(E) as a member of the raw type
java.util.ArrayList
data.add("world");
^
C:\ArrayListGeneric.java:25: warning: [unchecked] unchecked conversion
found : java.util.Iterator
required: java.util.Iterator
Iterator it = data.iterator();
^
3 WARNINGS

Since there are only warnings, your class is ready to run but ... it's not bad idea to eliminate the
warnings in production code.

Simply add the expected type (between < and >) after the class.

import java.util.*;

public class ArrayListGeneric {


public static void main(String[] args) {
ArrayList<String> data = new ArrayList<String>();
data.add("hello");
data.add("world");

Iterator<String> it = data.iterator();
while (it.hasNext()) {
String s = it.next();

11.38 Eliminate "[unchecked] unchecked call ..." compiler warning


System.out.println(s);
}
}
}

In JDK 1.6, it will be possible to insert a special annotation to suppress this kind of warning,
something like :

import java.util.*;

public class ArrayListGeneric {

@SuppressWarnings("unchecked") public static void main(String[] args) {


ArrayList data = new ArrayList();
data.add("hello");
data.add("world");

Iterator it = data.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}

A complete list of possible @SuppressWarnings parameters can be found at


http://mindprod.com/jgloss/annotations.html.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.39 Sort on many fields


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0520.html

We want to sort a Collection of Person objects based on their LastName and Firstname.

First the Person class

class Person implements Comparable {


String firstName, lastName;

public Person(String f, String l) {


this.firstName = f;
this.lastName = l;
}

public String getFirstName() {


return firstName;
}

public String getLastName() {


return lastName;

11.39 Sort on many fields


}

public String toString() {


return "[ firstname=" + firstName + ",lastname=" + lastName + "]";
}

public int compareTo(Object obj) {


Person emp = (Person) obj;
int deptComp = firstName.compareTo(emp.getFirstName());

return ((deptComp == 0) ? lastName.compareTo(emp.getLastName())


: deptComp);
}

public boolean equals(Object obj) {


if (!(obj instanceof Person)) {
return false;
}
Person emp = (Person) obj;
return firstName.equals(emp.getFirstName())
&lastName.equals(emp.getLastName());
}
}

then we need a class to implement the Comparable interface. It's in there where we put the logic
behind the sorting.

import java.util.Comparator;

class PersonComparator implements Comparator{


public int compare(Object obj1, Object obj2) {
Person emp1 = (Person) obj1;
Person emp2 = (Person) obj2;

int nameComp = emp1.getLastName().compareTo(emp2.getLastName());

return ((nameComp == 0) ?
emp1.getFirstName().compareTo(emp2.getFirstName()) :
nameComp);
}
}

To test it :

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Iterator;

public class TestSort {


public static void main(String args[]) {
String Smith[] = { "Real", "Vincent", "Nathalie", "Christine" };
String Simpsons[] = { "Bart", "Lisa", "Marge", "Homer", "Maggie" };

ArrayList names = new ArrayList();

// do the smith
for(int i = 0 ; i < Smith.length ; i ++) {
Person one = new Person(Smith[i],"Smith");
names.add(one);
}

11.39 Sort on many fields


// do the simpsons
for(int i = 0 ; i < Simpsons.length ; i ++) {
Person one = new Person(Simpsons[i],"Simpsons");
names.add(one);
}

System.out.println("BEFORE:");
Iterator iter1 = names.iterator();
while (iter1.hasNext()) {
System.out.println(iter1.next());
}

// now sort everything


Collections.sort(names, new PersonComparator());

System.out.println("AFTER:");
Iterator iter2 = names.iterator();
while (iter2.hasNext()) {
System.out.println(iter2.next());
}

/*
output :
BEFORE:
[ firstname=Real,lastname=Smith]
[ firstname=Vincent,lastname=Smith]
[ firstname=Nathalie,lastname=Smith]
[ firstname=Christine,lastname=Smith]
[ firstname=Bart,lastname=Simpsons]
[ firstname=Lisa,lastname=Simpsons]
[ firstname=Marge,lastname=Simpsons]
[ firstname=Homer,lastname=Simpsons]
[ firstname=Maggie,lastname=Simpsons]
AFTER:
[ firstname=Bart,lastname=Simpsons]
[ firstname=Homer,lastname=Simpsons]
[ firstname=Lisa,lastname=Simpsons]
[ firstname=Maggie,lastname=Simpsons]
[ firstname=Marge,lastname=Simpsons]
[ firstname=Christine,lastname=Smith]
[ firstname=Nathalie,lastname=Smith]
[ firstname=Real,lastname=Smith]
[ firstname=Vincent,lastname=Smith]
*/
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.40 Optimize Collection usage


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0553.html

11.40 Optimize Collection usage


From Usenet, (a post by ""Ed") a post to demonstrate that depending on your need, choosing the
right Collection implementation can be really important.

In the demonstration, we read a huge text file war−and−peace.txt and then count the duplicated
words. as you can see depending on the Collection used, the execution time is very different!

import java.util.*;
import java.io.*;

class TestCollectionPerformance {
private static String TEXT_BOOK_NAME = "war−and−peace.txt";

public static void main(String[] args) {


try {
String text = readText(); // Read text into RAM
countDuplicateWords(text, new HashSet<String>());
countDuplicateWords(text, new TreeSet<String>());
countDuplicateWords(text, new ArrayList<String>());
countDuplicateWords(text, new LinkedList<String>());
}
catch (Throwable t) {
System.out.println(t.toString());
}
}

private static String readText() throws Throwable {


BufferedReader reader =
new BufferedReader(new FileReader(TEXT_BOOK_NAME));
String line = null;
StringBuffer text = new StringBuffer();
while ((line = reader.readLine()) != null) {
text.append(line + " ");
}
return text.toString();
}

private static void countDuplicateWords(String text,


Collection<String> listOfWords) {
int numDuplicatedWords = 0;
long startTime = System.currentTimeMillis();
for (StringTokenizer i = new StringTokenizer(text);
i.hasMoreElements();) {
String word = i.nextToken();
if (listOfWords.contains(word)) {
numDuplicatedWords++;
}
else {
listOfWords.add(word);
}
}
long endTime = System.currentTimeMillis();
System.out.println(numDuplicatedWords + " duplicated words. " +
"Using " + listOfWords.getClass().getName() +
", time = " + (endTime − startTime) + "ms.");
}
}

Result :

522396 duplicated words. Using java.util.HashSet, time = 453ms.


522396 duplicated words. Using java.util.TreeSet, time = 1031ms.

11.40 Optimize Collection usage


522396 duplicated words. Using java.util.ArrayList, time = 100937ms.
522396 duplicated words. Using java.util.LinkedList, time = 129375ms.

• A Set offers a collection of unique elements.


• An HashSet maintains its collection in an unordered manner.
• A TreeSet keeps the elements in the collection in sorted order.
• A List provides ordered access (by index), but it doesn't guarantee uniqueness.
• The ArrayList provides a collection backed by an array. It provides quick indexed access to its
elements, and works best when elements are only added and removed at the end. To make this
happen, ArrayList performs an internal move operation when an element is added or removed.
• The LinkedList is best when add and remove operations happen anywhere, not only at the end.
LinkList doesn't do an internal move operation for an element insert or remove, it just manipulates
reference pointers. But LinkedList's added flexibility comes at an added cost −− it results in much
slower indexed operations.

ref : Sun's Java tech Tips Feb2003

11.41 Sort an HashMap


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0561.html

Sort based on the keys

Map yourMap= new HashMap();


// put some tuples in yourMap ...
Map sortedMap = new TreeMap(yourMap);

Sort based on the values

HashMap yourMap = new HashMap();


// put some tuples in yourMap ...

// to hold the result


HashMap map = new LinkedHashMap();

List yourMapKeys = new ArrayList(yourMap.keySet());


List yourMapValues = new ArrayList(yourMap.values());
TreeSet sortedSet = new TreeSet(yourMapValues);
Object[] sortedArray = sortedSet.toArray();
int size = sortedArray.length;

for (int i=0; i<size; i++) {


map.put
(yourMapKeys.get(yourMapValues.indexOf(sortedArray[i])),
sortedArray[i]);
}

To iterate your new Sorted Map

Set ref = map.keySet();


Iterator it = ref.iterator();

while (it.hasNext()) {
String file = (String)it.next();

11.41 Sort an HashMap


}

11.42 Get a key from value with an HashMap


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0564.html

[Java 5]

public static Object getKeyFromValue(HashMap hm,Object value){


for(Object o:hm.keySet()){
if(hm.get(o).equals(value)) {
return o;
}
}
return null;
}

[Java 1.4]

public static Object getKeyFromValue(HashMap hm,Object value){


Set ref = hm.keySet();
Iterator it = ref.iterator();

while (it.hasNext()) {
Object o = it.next();
if(o.equals(value)) {
return o;
}
}
return null;
}

11.43 Use an INI file (properties)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0024.html

In Java, configuration file are stored in properties file. By convention, the filename extension is
props or properties. The structure is very similar to Windows INI file with except that there is
no [...] section.

[Props file : user.props]

# this a comment
! this a comment too
DBuser=anonymous
DBpassword=DBlocation=bigone

[JAVA code]

import java.util.*;
import java.io.*;

11.42 Get a key from value with an HashMap


class ReadProps {
public static void main(String args[]) {
ReadProps props = new ReadProps();
props.doit();
}

public void doit() {


try{
Properties p = new Properties();
p.load(new FileInputStream("user.props"));
System.out.println("user = " + p.getProperty("DBuser"));
System.out.println("password = " + p.getProperty("DBpassword"));
System.out.println("location = " + p.getProperty("DBlocation"));
p.list(System.out);
}
catch (Exception e) {
System.out.println(e);
}
}
}

Since the Properties class extends the Hashtable, we can manipulate the Properties through the
get and put methods. The modified data can be saved back to a file with the save method. This
can be useful to store user preferences for example. Note that the order is not preserved.

import java.util.*;
import java.io.*;

class WriteProps {
public static void main(String args[]) {
WriteProps props = new WriteProps();
props.doit();
}

public void doit() {


try{
Properties p = new Properties();
p.load(new FileInputStream("user.props"));
p.list(System.out);
// new Property
p.put("today", new Date().toString());
// modify a Property
p.put("DBpassword","foo");
FileOutputStream out = new FileOutputStream("user.props");
p.save(out, "/* properties updated */");
}
catch (Exception e) {
System.out.println(e);
}
}
}

This ok with an application but you can't do it from an Applet since you can't write directly on the
server without some kind of a server−side process.

To read a Properties file via an Applet, load the Properties files this way :

p.load((new URL(getCodeBase(), "user.props")).openStream());

A Properties file stored in a JAR can be loaded this way :

11.42 Get a key from value with an HashMap


URL url =
ClassLoader.getSystemResource("/com/rgagnon/config/system.props");
if (url != null) props.load(url.openStream());

See also this HowTo, this one and finally this one too!

11.44 Load a properties file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0434.html

public class LoadProps {

public static void main(String args[]) throws Exception{


h.doit();
h.doitagain();
}
public void doit() throws Exception{
// properties in the classpath
java.util.Properties props = new java.util.Properties();
java.net.URL url = ClassLoader.getSystemResource("myprops.props");
props.load(url.openStream());
System.out.println(props);
}
public void doitagain() throws Exception{
// properties in the startup directory
java.util.Properties props = new java.util.Properties();
String path = getClass().getProtectionDomain().getCodeSource().
getLocation().toString().substring(6);
java.io.FileInputStream fis = new java.io.FileInputStream
(new java.io.File( path + "\\myprops.props"));
props.load(fis);
System.out.println(props);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.45 Accentuated characters in Properties/ResourceBundle file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0492.html

The rules are

• Only use ISO Latin 1 characters in the Properties/ResourceBundle files


• For other characters use the \u.... notation
• To avoid having to type all the \u... notation manually, use the native2ascii tool (included with
the SDK).

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

11.44 Load a properties file


Written and compiled by Réal Gagnon ©1998−2005
[ home ]

11.46 Have a multi−line value in a properties file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0503.html

You add a slash ("\") to continue the value on the next line.

Take the following properties file :


[props.properties]

prop1=first line of prop1 \


second line of prop1\
third line of prop1
prop2=first line of prop2 \n \
second line of prop2 \n \
third line of prop2

A program to read the properties file :


[Hello.java]

public class Hello {


public static void main(String args[]) throws Exception{
Hello h = new Hello();
h.doit();
}
public void doit() throws Exception{
// properties in the classpath
java.util.Properties props = new java.util.Properties();
java.net.URL url = ClassLoader.getSystemResource("props.properties");
props.load(url.openStream());
System.out.println("prop1 :\n " + props.get("prop1"));
System.out.println("prop2 :\n " + props.get("prop2"));
}
}

The output

>java Hello
prop1 :
first line of prop1 second line of prop1third line of prop1
prop2 :
first line of prop2
second line of prop2
third line of prop2

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

11.46 Have a multi−line value in a properties file


11.47 Use XML with Properties
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0578.html

import java.util.*;
import java.io.*;

class XMLProps {
public static void main(String args[]) {
new XMLProps().doit();
}

public void doit() {


try{
Properties p = new Properties();

p.put("today", new Date().toString());


p.put("user", "Bob");

FileOutputStream out = new FileOutputStream("user.props");


p.storeToXML(out,"props updated");

FileInputStream in = new FileInputStream("user.props");

p.loadFromXML(in);
p.list(System.out);
/*
output :
−− listing properties −−
today=Thu Aug 09 22:45:11 EDT 2007
user=Bob
*/
}
catch (Exception e) {
e.printStackTrace();
}
}
}

The XML looks like

<?xml version="1.0" encoding="UTF−8"?>


<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>props updated</comment>
<entry key="user">Bob</entry>
<entry key="today">Thu Aug 09 22:45:11 EDT 2007</entry>
</properties>

11.48 Use the Registry to store informations (Preferences API)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0421.html

With JDK1.4, the Preferences class can use the Windows registry (on Unix, a file is used) :

11.47 Use XML with Properties


import java.util.prefs.Preferences;

public class UsingReg {

public static final String REALKEY= "com.rgagnon.foo";

public static void main(String[] args){


new UsingReg().doit();
}

public void doit() {


// write into HKCU\Software\Javasoft\Prefs\com.rgagnon.foo
Preferences p = Preferences.userRoot();
p.put(REALKEY, "bar");

// read back from HKEY_CURRENT_USER


System.out.println(p);
System.out.println(p.get(REALKEY, "HKCU houston we have a problem"));

// write into HKLM\Software\Javasoft\Prefs\com.rgagnon.foo


p = Preferences.systemRoot();
p.put(REALKEY, "barbar");

// read back from HKEY_LOCAL_MACHINE


System.out.println(p);
System.out.println(p.get(REALKEY, "HKLM houston we have a problem"));
}
}

See also this How−to to access the Windows registry.

With Unix (or Linux), a file is used and you may run into problems if you don't have write access in
the default location for the Preferences storage. See this interesting article and these 2 bugs : 1
2

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

11.47 Use XML with Properties


12 Networking
12.1 java−net

12.2 Extract network card address


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0369.html

JDK1.6
java.net.NetworkInterface

import java.io.*;
import java.net.*;
import java.util.*;

public class ListNetsEx


{
public static void main(String args[])
throws SocketException
{
Enumeration nets =
NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets))
displayInterfaceInformation(netint);
}

static void displayInterfaceInformation(NetworkInterface netint)


throws SocketException
{
System.out.println("Display name: "
+ netint.getDisplayName());
System.out.println("Hardware address: "
+ Arrays.toString(netint.getHardwareAddress()));
}
}

JDK1.5 or less
One way, without using JNI, is to launch an external utility and interpret the output.

In Windows, "arp −a" will return the MAC addresses of all adapters that have TCP/IP bound to them
and have recently (default < 5 mins) resolved an IP address. Otherwise, in NT/2K/XP, "ipconfig /all"
will return all relevant network info for IP−bound adapters, including the MAC address (displayed as
"physical address").

In Linux, "ifconfig" does something similar.

Example for Windows

import java.net.InetAddress;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.IOException;

12 Networking
import java.text.ParseException;
import java.util.StringTokenizer;

//
// inspired by
// http://forum.java.sun.com/thread.jspa?messageID=902023
//

public final class NetworkUtils {

private final static int MACADDR_LENGTH = 17;


private final static String WIN_OSNAME = "Windows";
private final static String WIN_MACADDR_REG_EXP =
"^[0−9A−F]{2}−[0−9A−F]{2}−[0−9A−F]{2}−[0−9A−F]{2}−[0−9A−F]{2}−[0−9A−F]{2}$";
private final static String WIN_MACADDR_EXEC = "ipconfig /all";

public final static String getMacAddress() throws IOException {


String os = System.getProperty("os.name");
try {
if (os.startsWith(WIN_OSNAME)) {
return winMacAddress(winIpConfigCommand());
}
// other OS left as an exercise !
// LINUX −−> else if (os.startsWith("Linux")) { ...
// ...
// Process p = Runtime.getRuntime().exec("ifconfig");
// MAC OSX −−> else if(os.startsWith("Mac OS X")) { ...
// ...
// Process p = Runtime.getRuntime().exec("ifconfig");
else {
throw new IOException("OS not supported : " + os);
}
}
catch(ParseException e) {
e.printStackTrace();
throw new IOException(e.getMessage());
}
}

private final static String winMacAddress(String ipConfigOutput)


throws ParseException {
String localHost = null;
try {
localHost = InetAddress.getLocalHost().getHostAddress();
}
catch(java.net.UnknownHostException ex) {
ex.printStackTrace();
throw new ParseException(ex.getMessage(), 0);
}

StringTokenizer tokenizer =
new StringTokenizer(ipConfigOutput, "\n");
String lastMacAddress = null;

while(tokenizer.hasMoreTokens()) {
String line = tokenizer.nextToken().trim();

// see if line contains IP address


if (line.endsWith(localHost) && lastMacAddress != null) {
return lastMacAddress;
}

12 Networking
// see if line contains MAC address
int macAddressPosition = line.indexOf(":");
if(macAddressPosition <= 0) continue;

String macAddressCandidate = line.substring(macAddressPosition + 1).trim();


if (winIsMacAddress(macAddressCandidate)) {
lastMacAddress = macAddressCandidate;
continue;
}
}

ParseException ex = new ParseException


("cannot read MAC address from [" + ipConfigOutput + "]", 0);
ex.printStackTrace();
throw ex;
}

private final static boolean winIsMacAddress(String macAddressCandidate) {


if (macAddressCandidate.length() != MACADDR_LENGTH) return false;
if (!macAddressCandidate.matches(WIN_MACADDR_REG_EXP)) return false;
return true;
}

private final static String winIpConfigCommand() throws IOException {


Process p = Runtime.getRuntime().exec(WIN_MACADDR_EXEC);
InputStream stdoutStream = new BufferedInputStream(p.getInputStream());

StringBuffer buffer= new StringBuffer();


for (;;) {
int c = stdoutStream.read();
if (c == −1) break;
buffer.append((char)c);
}
String outputText = buffer.toString();
stdoutStream.close();
return outputText;
}

public final static void main(String[] args) {


try {
System.out.println("MAC ADDRESS");
System.out.println(" OS : "
+ System.getProperty("os.name"));
System.out.println(" IP/Localhost: "
+ InetAddress.getLocalHost().getHostAddress());
System.out.println(" MAC Address : "
+ getMacAddress());
}
catch(Throwable t) {
t.printStackTrace();
}
}
}

12.3 Get the workstation name/ip

12.3 Get the workstation name/ip


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0390.html

public class NetInfo {


public static void main(String[] args) {
new NetInfo().say();
}

public void say() {


try {
java.net.InetAddress i = java.net.InetAddress.getLocalHost();
System.out.println(i); // name and IP address
System.out.println(i.getHostName()); // name
System.out.println(i.getHostAddress()); // IP address only
}
catch(Exception e){e.printStackTrace();}
}
}

The output

> java NetInfo


realone/209.142.72.112
realone
209.142.72.112

Note: This may not work on Linux workstation. Search Sun's Bug Parade for a workaround.

To list all the interfaces available on a workstation :


[JDK1.4]

import java.net.*;
import java.util.*;
import java.io.*;
import java.nio.*;

public class IPAdress {

public void getInterfaces (){


try {
Enumeration e = NetworkInterface.getNetworkInterfaces();

while(e.hasMoreElements()) {
NetworkInterface netface = (NetworkInterface)
e.nextElement();
System.out.println("Net interface: "+netface.getName());

Enumeration e2 = netface.getInetAddresses();

while (e2.hasMoreElements()){
InetAddress ip = (InetAddress) e2.nextElement();
System.out.println("IP address: "+ip.toString());
}
}
}
catch (Exception e) {
System.out.println ("e: " + e);
}
}

public static void main(String[] args) {

12.3 Get the workstation name/ip


IPAdress ip = new IPAdress();
ip.getInterfaces();
}
}

The output

> java IPAdress


Net interface: lo
IP address: /127.0.0.1
Net interface: eth0
IP address: /194.168.0.1
Net interface: eth1
IP address: /164.254.147.20
Net interface: ppp0
IP address: /64.68.115.69

Windows

A "low−tech" way to get the computer name (can be useful if there is no network card) is to use the
environment variable COMPUTERNAME (at least on modern Windows installation).

So pass it to your JVM as java −Dcomputername="%COMPUTERNAME%" ... and the get the value
with System.getProperty("computername") or use the jdk1.5 which can extract environment variable
directly with System.getenv("COMPUTERNAME")

12.4 Find port number not in use


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0412.html

On Windows, "netstat −an" list the ports currently in use.

Take a look at http://www.iana.org/assignments/port−numbers for a list of assigned numbers.

12.5 Disable DNS caching


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0445.html

Once an application has performed network access (i.e. urlconnection, parsing of xml document
with external references, etc), the DNS settings get cached so any subsequent operation will use
the old settings even if the real settings have changed. To reset everything, you have to restart the
server since the the default setting JVM setting is to cache forever.

There are 4 properties that can be used to override the default behaviour.

networkaddress.cache.ttl (default: −1)


Specified in java.security to indicate the caching policy for successful
name lookups from the name service. The value is specified as as integer
to indicate the number of seconds to cache the successful lookup.

12.4 Find port number not in use


A value of −1 indicates "cache forever".

networkaddress.cache.negative.ttl (default: 10)


Specified in java.security to indicate the caching policy for un−successful
name lookups from the name service. The value is specified as as integer to
indicate the number of seconds to cache the failure for un−successful lookups.

A value of 0 indicates "never cache". A value of −1 indicates "cache forever".

sun.net.inetaddr.ttl
This is a sun private system property which corresponds to networkaddress.cache.ttl.
It takes the same value and has the same meaning, but can be set as a command−line
option. However, the preferred way is to use the security property mentioned above.

sun.net.inetaddr.negative.ttl
This is a sun private system property which corresponds to networkaddress.cache.negative.tt
It takes the same value and has the same meaning, but can be set as a command−line option.
However, the preferred way is to use the security property mentioned above.

So you can disable caching by adding −Dsun.net.inetaddr.ttl=0 on the command line starting the
JVM. But you can't set the value of networkaddress.cache.ttl on the command line. You can set the
required value in the java.security file located in %JRE%\lib\security

networkaddress.cache.ttl=60
networkaddress.cache.negative.ttl=10

or set the value in your code with

java.security.Security.setProperty("networkaddress.cache.ttl" , "0");

ref : J2SE 1.4 Net properties

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

12.6 Encode/Decode to/from Base64


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0598.html

As seen in this HowTo, the sun.misc.BASE64Encoder/Decoder or creating your own Base64


handling are the best way to deal with Base64 encoding/decoding.

12.7 Using javax.mail.internet.MimeUtility


import javax.mail.internet.MimeUtility;
import java.io.*;

public class Base64Utils {


public static byte[] encode(byte[] b) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = MimeUtility.encode(baos, "base64");
b64os.write(b);

12.6 Encode/Decode to/from Base64


b64os.close();
return baos.toByteArray();
}

public static byte[] decode(byte[] b) throws Exception {


ByteArrayInputStream bais = new ByteArrayInputStream(b);
InputStream b64is = MimeUtility.decode(bais, "Base64");
byte[] tmp = new byte[b.length];
int n = b64is.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return res;
}

public static void main(String[] args) throws Exception {


String test = "realhowto";

byte res1[] = Base64Utils.encode(test.getBytes());


System.out.println(test + " base64 −> " + java.util.Arrays.toString(res1));
System.out.println(new String(res1));
byte res2[] = Base64Utils.decode(res1);
System.out.println("");
System.out.println( java.util.Arrays.toString(res1) + " string −−> "
+ new String(res2));

/*
* output
* realhowto base64 −>
* [99, 109, 86, 104, 98, 71, 104, 118, 100, 51, 82, 118]
* cmVhbGhvd3Rv
* [99, 109, 86, 104, 98, 71, 104, 118, 100, 51, 82, 118]
* string −−> realhowto
*/
}

12.8 Using Apache Commons Codec


Apache Commons Codec provides implementations of common encoders and decoders such as
Base64, Hex, Phonetic and URLs. Download at http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Base64;

public class Codec {


public static void main(String[] args) {
try {
String clearText = "Hello world";
String encodedText;

// Base64
encodedText = new String(Base64.encodeBase64(clearText.getBytes()));
System.out.println("Encoded: " + encodedText);
System.out.println("Decoded:"
+ new String(Base64.decodeBase64(encodedText.getBytes())));
//
// output :
// Encoded: SGVsbG8gd29ybGQ=
// Decoded:Hello world
//
}

12.8 Using Apache Commons Codec


catch (Exception e) {
e.printStackTrace();
}
}
}

12.9 MiGBase64
• MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

12.10 Lookup using MX record to validate mail server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0452.html

The best you can do to verify if an email address is real is to verify if there is a mail server
registered to the domain name.

import java.util.Hashtable;
import javax.naming.*;
import javax.naming.directory.*;

public class MXLookup {


public static void main( String args[] ) {
if( args.length == 0 ) {
System.err.println( "Usage: MXLookup host [...]" );
System.exit( 99 );
}
for( int i = 0; i < args.length; i++ ) {
try {
System.out.println( args[i] + " has " +
doLookup( args[i] ) + " mail servers" );
}
catch( Exception e ) {
System.out.println(args[i] + " : " + e.getMessage());
}
}
}

static int doLookup( String hostName ) throws NamingException {


Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext( env );
Attributes attrs =
ictx.getAttributes( hostName, new String[] { "MX" });
Attribute attr = attrs.get( "MX" );
if( attr == null ) return( 0 );
return( attr.size() );
}
}

The output is

>java MXLookup rgagnon.com realhowto.com


rgagnon.com has 1 mail servers

12.9 MiGBase64
realhowto.com : DNS name not found [response code 3]

From T. Orbaker, more infos on that subject (thanks to him).

There are other methods by which to validate an email address to a higher degree of than just the
mail server.

One:
Use the VRFY command (see RFCs 821/2821). Because this was abused by spammers, it have
typically been disabled on most mail servers. Some recent servers don't even support this
command as they are so frequently shut off.

When it works, connect to the server, issue the HELO command and then send 'VRFY '. If it is
enabled, and the address is valid, you should get a 250 if the address is valid and a 550 if it isn't.
Note that some servers (qmail) return 252 as a means of pleading the fifth. Others will return a
failure even if the address exists but the command has been disables (although this is typically a
450 error).

Two (better method):


Connect to the servers determined by your code snippet. BUT (and the code below doesn't do
this) they must be tried from lowest preference to highest to be absolutely correct.

Once you have connected, you create the SMTP envelope, but you don't put anything in it. This is
the point at which most servers will give up the dirt on whether or not an address is valid. If an
envelope cannot be built, we know that the address is invalid.

The reason for connecting in order of preference:

Imagine ABC company has an Internet conneciton and runs their own mail server for abc.com. To
prevent bounces and other mail errors if their connection or server should be down, their provider
isp.com agrees to set up a 'store and forward' scheme for their mail. If abc.com is not available,
then isp.com gets the message and when abc.com is again available, the message gets
forwarded. The MX records would look something like:

MX 1 abc.com
MX 5 isp.com

Now, imagine that you connect to isp.com and try to send a message. The mail server at isp.com
doesn't have the actual user list to know which addresses are valid, it just accepts everything and
relies on abc.com to sort out the bounces.

If these are not checked in the proper order, there will be no errors for invalid addresses.

Yahoo appears to use a store and forward mechanism to its own internal servers, thus
conclusively verifying a yahoo address is not possible. I suspect that hotmail is the same.

It is not possible to verify an address on a domain that uses a catch−all account as the catch
account will receive the mail (it does, however, mean that someone will at least SEE the
message).

import java.io.*;
import java.net.*;
import java.util.*;
import javax.naming.*;

12.9 MiGBase64
import javax.naming.directory.*;

public class SMTP {


private static int hear( BufferedReader in ) throws IOException {
String line = null;
int res = 0;

while ( (line = in.readLine()) != null ) {


String pfx = line.substring( 0, 3 );
try {
res = Integer.parseInt( pfx );
}
catch (Exception ex) {
res = −1;
}
if ( line.charAt( 3 ) != '−' ) break;
}

return res;
}

private static void say( BufferedWriter wr, String text )


throws IOException {
wr.write( text + "\r\n" );
wr.flush();

return;
}

private static ArrayList getMX( String hostName )


throws NamingException {
// Perform a DNS lookup for MX records in the domain
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext( env );
Attributes attrs = ictx.getAttributes
( hostName, new String[] { "MX" });
Attribute attr = attrs.get( "MX" );

// if we don't have an MX record, try the machine itself


if (( attr == null ) || ( attr.size() == 0 )) {
attrs = ictx.getAttributes( hostName, new String[] { "A" });
attr = attrs.get( "A" );
if( attr == null )
throw new NamingException
( "No match for name '" + hostName + "'" );
}

// Huzzah! we have machines to try. Return them as an array list


// NOTE: We SHOULD take the preference into account to be absolutely
// correct. This is left as an exercise for anyone who cares.
ArrayList res = new ArrayList();
NamingEnumeration en = attr.getAll();

while ( en.hasMore() ) {
String x = (String) en.next();
String f[] = x.split( " " );
if ( f[1].endsWith( "." ) )
f[1] = f[1].substring( 0, (f[1].length() − 1));
res.add( f[1] );
}
return res;

12.9 MiGBase64
}

public static boolean isAddressValid( String address ) {


// Find the separator for the domain name
int pos = address.indexOf( '@' );

// If the address does not contain an '@', it's not valid


if ( pos == −1 ) return false;

// Isolate the domain/machine name and get a list of mail exchangers


String domain = address.substring( ++pos );
ArrayList mxList = null;
try {
mxList = getMX( domain );
}
catch (NamingException ex) {
return false;
}

// Just because we can send mail to the domain, doesn't mean that the
// address is valid, but if we can't, it's a sure sign that it isn't
if ( mxList.size() == 0 ) return false;

// Now, do the SMTP validation, try each mail exchanger until we get
// a positive acceptance. It *MAY* be possible for one MX to allow
// a message [store and forwarder for example] and another [like
// the actual mail server] to reject it. This is why we REALLY ought
// to take the preference into account.
for ( int mx = 0 ; mx < mxList.size() ; mx++ ) {
boolean valid = false;
try {
int res;
Socket skt = new Socket( (String) mxList.get( mx ), 25 );
BufferedReader rdr = new BufferedReader
( new InputStreamReader( skt.getInputStream() ) );
BufferedWriter wtr = new BufferedWriter
( new OutputStreamWriter( skt.getOutputStream() ) );

res = hear( rdr );


if ( res != 220 ) throw new Exception( "Invalid header" );
say( wtr, "EHLO orbaker.com" );

res = hear( rdr );


if ( res != 250 ) throw new Exception( "Not ESMTP" );

// validate the sender address


say( wtr, "MAIL FROM: <tim@orbaker.com>" );
res = hear( rdr );
if ( res != 250 ) throw new Exception( "Sender rejected" );

say( wtr, "RCPT TO: <" + address + ">" );


res = hear( rdr );

// be polite
say( wtr, "RSET" ); hear( rdr );
say( wtr, "QUIT" ); hear( rdr );
if ( res != 250 )
throw new Exception( "Address is not valid!" );

valid = true;
rdr.close();
wtr.close();
skt.close();

12.9 MiGBase64
}
catch (Exception ex) {
// Do nothing but try next host
}
finally {
if ( valid ) return true;
}
}
return false;
}

public static void main( String args[] ) {


String testData[] = {
"tim@orbaker.com", // Valid address
"fail.me@nowhere.spam", // Invalid domain name
"arkham@bigmeanogre.net", // Invalid address
"nosuchaddress@yahoo.com" // Failure of this method
};

for ( int ctr = 0 ; ctr < testData.length ; ctr++ ) {


System.out.println( testData[ ctr ] + " is valid? " +
isAddressValid( testData[ ctr ] ) );
}
return;
}
}

S.Boerner has this comments about this HowTo :

The method SMTP::getMX() in the second example throws an ArrayIndexOutOfBoundsException


while getting the mailhost via the "A" attribute at:

while ( en.hasMore() ) {
String x = (String) en.next();
String f[] = x.split( " " );
if ( f[1].endsWith( "." ) )

The "A" attribute returns only an address list, so f.length is always 1. I used something like:

boolean hasMX = "MX".equals(attr.getID());

and later

if (hasMX)
{
mailhost = f[1];
}
else
{
mailhost = f[0];
}

Here my proposed fix :

import java.io.*;
import java.net.*;
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;

12.9 MiGBase64
public class SMTPMXLookup {
private static int hear( BufferedReader in ) throws IOException {
String line = null;
int res = 0;

while ( (line = in.readLine()) != null ) {


String pfx = line.substring( 0, 3 );
try {
res = Integer.parseInt( pfx );
}
catch (Exception ex) {
res = −1;
}
if ( line.charAt( 3 ) != '−' ) break;
}

return res;
}

private static void say( BufferedWriter wr, String text )


throws IOException {
wr.write( text + "\r\n" );
wr.flush();

return;
}
private static ArrayList getMX( String hostName )
throws NamingException {
// Perform a DNS lookup for MX records in the domain
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext( env );
Attributes attrs = ictx.getAttributes
( hostName, new String[] { "MX" });
Attribute attr = attrs.get( "MX" );

// if we don't have an MX record, try the machine itself


if (( attr == null ) || ( attr.size() == 0 )) {
attrs = ictx.getAttributes( hostName, new String[] { "A" });
attr = attrs.get( "A" );
if( attr == null )
throw new NamingException
( "No match for name '" + hostName + "'" );
}
// Huzzah! we have machines to try. Return them as an array list
// NOTE: We SHOULD take the preference into account to be absolutely
// correct. This is left as an exercise for anyone who cares.
ArrayList res = new ArrayList();
NamingEnumeration en = attr.getAll();

while ( en.hasMore() ) {
String mailhost;
String x = (String) en.next();
String f[] = x.split( " " );
// THE fix *************
if (f.length == 1)
mailhost = f[0];
else if ( f[1].endsWith( "." ) )
mailhost = f[1].substring( 0, (f[1].length() − 1));
else
mailhost = f[1];
// THE fix *************

12.9 MiGBase64
res.add( mailhost );
}
return res;
}

public static boolean isAddressValid( String address ) {


// Find the separator for the domain name
int pos = address.indexOf( '@' );

// If the address does not contain an '@', it's not valid


if ( pos == −1 ) return false;

// Isolate the domain/machine name and get a list of mail exchangers


String domain = address.substring( ++pos );
ArrayList mxList = null;
try {
mxList = getMX( domain );
}
catch (NamingException ex) {
return false;
}

// Just because we can send mail to the domain, doesn't mean that the
// address is valid, but if we can't, it's a sure sign that it isn't
if ( mxList.size() == 0 ) return false;

// Now, do the SMTP validation, try each mail exchanger until we get
// a positive acceptance. It *MAY* be possible for one MX to allow
// a message [store and forwarder for example] and another [like
// the actual mail server] to reject it. This is why we REALLY ought
// to take the preference into account.
for ( int mx = 0 ; mx &lt; mxList.size() ; mx++ ) {
boolean valid = false;
try {
int res;
//
Socket skt = new Socket( (String) mxList.get( mx ), 25 );
BufferedReader rdr = new BufferedReader
( new InputStreamReader( skt.getInputStream() ) );
BufferedWriter wtr = new BufferedWriter
( new OutputStreamWriter( skt.getOutputStream() ) );

res = hear( rdr );


if ( res != 220 ) throw new Exception( "Invalid header" );
say( wtr, "EHLO rgagnon.com" );

res = hear( rdr );


if ( res != 250 ) throw new Exception( "Not ESMTP" );

// validate the sender address


say( wtr, "MAIL FROM: <tim@orbaker.com>" );
res = hear( rdr );
if ( res != 250 ) throw new Exception( "Sender rejected" );

say( wtr, "RCPT TO: <" + address + ">" );


res = hear( rdr );

// be polite
say( wtr, "RSET" ); hear( rdr );
say( wtr, "QUIT" ); hear( rdr );
if ( res != 250 )
throw new Exception( "Address is not valid!" );

12.9 MiGBase64
valid = true;
rdr.close();
wtr.close();
skt.close();
}
catch (Exception ex) {
// Do nothing but try next host
ex.printStackTrace();
}
finally {
if ( valid ) return true;
}
}
return false;
}

public static void main( String args[] ) {


String testData[] = {
"real@rgagnon.com",
"you@acquisto.net",
"fail.me@nowhere.spam", // Invalid domain name
"arkham@bigmeanogre.net", // Invalid address
"nosuchaddress@yahoo.com" // Failure of this method
};

for ( int ctr = 0 ; ctr < testData.length ; ctr++ ) {


System.out.println( testData[ ctr ] + " is valid? " +
isAddressValid( testData[ ctr ] ) );
}
return;
}
}

12.11 Send an email using the SMTP protocol


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0079.html

import java.net.*;
import java.io.*;

public class SendElvisMail {


public static void main(String s[]) {
//
// Send fake mail from Elvis Presley
//
// SendElvisMail [mail server] [recipient address]
// mail server can be hostname or IP address
//
// ex. SendElvisMail mail.company.com myFriend@somewhere.qc.ca
//
SendElvisMail t = new SendElvisMail();
t.sendMail(s[0], s[1]);
}

public void sendMail(String mailServer, String recipient) {


try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader

12.11 Send an email using the SMTP protocol


(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));

send(in, out, "HELO theWorld");


// warning : some mail server validate the sender address
// in the MAIL FROm command, put your real address here
send(in, out, "MAIL FROM: <Elvis.Presley@jailhouse.rock>");
send(in, out, "RCPT TO: " + recipient);
send(in, out, "DATA");
send(out, "Subject: In the ghetto");
send(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock>");
send (out, "\n");
// message body
send(out, "I'm alive. Help me!");
send(out, "\n.\n");
send(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public void send(BufferedReader in, BufferedWriter out, String s) {


try {
out.write(s + "\n");
out.flush();
System.out.println(s);
s = in.readLine();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void send(BufferedWriter out, String s) {


try {
out.write(s + "\n");
out.flush();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

A good idea would be to download the JavaMail API from Sun if you're looking for a more object−oriented approach.

12.12 Check if there is mail waiting


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0080.html

import java.net.*;
import java.io.*;

public class CheckMail {

12.12 Check if there is mail waiting


public static void main(String s[]) {
//
// CheckMail [mailServer] [user] [password]
//
try {
CheckMail t = new CheckMail();
int i = t.checkMyMail(s[0], s[1], s[2]);
if (i==0) {
System.out.println("No mail waiting.");
}
else {
System.out.println
("There " + (i==1?"is " :"are ") + i +
" message" +(i==1?"":"s")+ " waiting.");
}
}
catch (Exception e) {
e.printStackTrace();
}
}

private void send(BufferedWriter out, String s) throws IOException {


out.write(s+"\n");
out.flush();
}

private String receive(BufferedReader in) throws IOException {


return in.readLine();
}

private int checkMyMail


(String server, String user, String pass) throws IOException {
Socket s = new Socket(server, 110);
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));

receive(in);
send(out, "USER " + user);
receive(in);
send(out, "PASS " + pass);
receive(in);
return getNumberOfMessages(in, out);
}

public int getNumberOfMessages


(BufferedReader in, BufferedWriter out) throws IOException {
int i = 0;
String s;

send(out, "LIST");
receive(in);
while((s = receive(in)) != null) {
if (!(s.equals("."))) {
i++;
}
else
return i;
}
return 0;
}

12.12 Check if there is mail waiting


}

12.13 Receive email


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0081.html

import java.net.*;
import java.io.*;

public class DisplayMail {

public static void main(String arg[]) {


//
// usage :
// DisplayMail [mailServer] [user] [password]
// (will not delete mail on the server)
//
try {
// connect on port 110 (POP3)
System.out.println("Connect to " + arg[0] + ":110");
Socket s = new Socket(arg[0], 110);
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(s.getOutputStream()));
DisplayMail mail = new DisplayMail();
mail.login(in, out, arg[1], arg[2]);
int i = mail.check(in,out);
if (i==0) {
System.out.println("No mail waiting.");
}
else {
for (int j=1; j <= i; j++) {
String msg = mail.get(in, out, j);
System.out.println("*****");
System.out.println(msg);
System.out.println("*****");
}
//
// If the mail was removed from the server
// (see getMail()) then we must COMMIT with
// the "QUIT" command :
// send(out, "QUIT");
//
}
}
catch (Exception e) {
e.printStackTrace();
}
}

public String get


(BufferedReader in, BufferedWriter out, int i)
throws IOException {
String s = "";
String t = "";
send(out, "RETR "+i);
while (((s = in.readLine()) != null)
)))) {

12.13 Receive email


t += s + "\n";
}
//
// To remove the mail on the server :
// send(out, "DELE "+i);
// receive(in);
//
return t;
}

private void send(BufferedWriter out, String s)


throws IOException {
System.out.println(s);
out.write(s+"\n");
out.flush();
}

private String receive(BufferedReader in)


throws IOException {
String s = in.readLine();
System.out.println(s);
return s;
}

private void login


(BufferedReader in, BufferedWriter out, String user, String pass)
throws IOException {
receive(in);
send(out, "HELO theWorld");
receive(in);
send(out, "USER " + user);
receive(in);
send(out, "PASS " + pass);
receive(in);
}

private int check


(BufferedReader in, BufferedWriter out)
throws IOException {
return getNumberOfMessages(in, out);
}

public int getNumberOfMessages


(BufferedReader in, BufferedWriter out)
throws IOException {
int i = 0;
String s;

send(out, "LIST");
receive(in);
while((s = receive(in)) != null) {
if (!(s.equals("."))) {
i++;
}
else {
return i;
}
}
return 0;
}
}

12.13 Receive email


12.14 Send email with an attachment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0083.html

In this example, Elvis is sending a GIF of his old Gumby friend. The attachment is encodded
using the BASE64 algorithm.

In this example, we are sending as attachment this image :

import java.io.*;
import java.net.*;

public class TestMailMIME {


static int SMTPport = 25;
static Socket socket;
static DataInputStream in;
static DataOutputStream out;
static PrintStream prout;

/* Name of file to be sent. */


String FileName = "gumby.gif";

public static void main(String s[]) {


/*
** TestMailMIME [server] [recipient]
*/
TestMailMIME t = new TestMailMIME();
t.sendMail(s[0], s[1]);
}

public void sendMail(String mailServer, String recipient) {


System.out.println("Send mail with attached file ");
try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));

String boundary = "DataSeparatorString";

// here you are supposed to send your username


sendln(in, out, "HELO theWorld");
// warning : some mail server validate the sender address
// in the MAIL FROM command, put your real address here
sendln(in, out, "MAIL FROM: ");
sendln(in, out, "RCPT TO: <" + recipient + ">" );
// to have more than one recipient, repeat
// sendln(in, out, "RCPT TO: <" + recipient2 + ">" );
// sendln(in, out, "RCPT TO: <" + recipient3 + ">" );
// etc...
// thanks to P−Y Colle for the tip!
sendln(in, out, "DATA");
sendln(out, "MIME−Version: 1.0");
sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock>");
sendln

12.14 Send email with an attachment


(out, "Content−Type: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n−−" + boundary);

// Send the body


sendln(out, "Content−Type: text/plain; charset=\"us−ascii\"\r\n");
sendln(out, "I'm alive. Help me!\r\n\r\n");
sendln(out, "\r\n−−" + boundary );

// send the GIF


sendln(out, "Content−Type:image/gif; name="+FileName);
sendln
(out, "Content−Disposition: attachment;filename=\""+FileName+"\"");
sendln(out, "Content−transfer−encoding: base64\r\n");
MIMEBase64.encode(FileName, out);
sendln(out, "\r\n−−" + boundary);

sendln(out, "\r\n\r\n−−" + boundary + "−−\r\n");


sendln(in, out,".");
sendln(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public void sendln(BufferedReader in, BufferedWriter out, String s) {


try {
out.write(s + "\r\n");
out.flush();
// System.out.println(s);
s = in.readLine();
// System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}

public void sendln(BufferedWriter out, String s) {


try {
out.write(s + "\r\n");
out.flush();
System.out.println(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

And the MIMEBase64 class

import java.io.*;

public class MIMEBase64 {


/*
Base64 uses a 65 character subset of US−ASCII,
allowing 6 bits for each character so the character
"m" with a Base64 value of 38, when represented
in binary form, is 100110.

With a text string, let's say "men" is encoded this

12.14 Send email with an attachment


is what happens :

The text string is converted into its US−ASCII value.

The character "m" has the decimal value of 109


The character "e" has the decimal value of 101
The character "n" has the decimal value of 110

When converted to binary the string looks like this :

m 01101101
e 01100101
n 01101110

These three "8−bits" are concatenated to make a


24 bit stream
011011010110010101101110

This 24 bit stream is then split up into 4 6−bit


sections
011011 010110 010101 101110

We now have 4 values. These binary values are


converted to decimal form
27 22 21 46

And the corresponding Base64 character are :


b W V u

The encoding is always on a three characters basis


(to have a set of 4 Base64 characters). To encode one
or two then, we use the special character "=" to pad
until 4 base64 characters is reached.

ex. encode "me"

01101101 01100101
0110110101100101
011011 010110 0101
111111 (AND to fill the missing bits)
011011 010110 010100
b W U
b W U = ("=" is the padding character)

so "bWU=" is the base64 equivalent.

encode "m"

01101101
011011 01
111111 (AND to fill the missing bits)
011011 010000
b Q = = (two paddings are added)

Finally, MIME specifies that lines are 76 characters wide maximum.

*/

static String BaseTable[] = {


"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
"Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
"g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
"w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"

12.14 Send email with an attachment


};

public static void encode(String filename, BufferedWriter out) {


try {
File f = new File(filename);
FileInputStream fin = new FileInputStream(filename);

// read the entire file into the byte array


byte bytes[] = new byte[(int)(f.length())];
int n = fin.read(bytes);

if (n < 1) return; // no bytes to encode!?!

byte buf[] = new byte[4]; // array of base64 characters

int n3byt = n / 3; // how 3 bytes groups?


int nrest = n % 3; // the remaining bytes from the grouping
int k = n3byt * 3; // we are doing 3 bytes at a time
int linelength = 0; // current linelength
int i = 0; // index

// do the 3−bytes groups ...


while ( i < k ) {
buf[0] = (byte)(( bytes[i] &0xFC) >> 2);
buf[1] = (byte)(((bytes[i] &0x03) << 4) |
((bytes[i+1] &0xF0) >> 4));
buf[2] = (byte)(((bytes[i+1] &0x0F) << 2) |
((bytes[i+2] &0xC0) >> 6));
buf[3] = (byte)( bytes[i+2] &0x3F);
send(out, BaseTable[buf[0]]);
send(out, BaseTable[buf[1]]);
send(out, BaseTable[buf[2]]);
send(out, BaseTable[buf[3]]);
/*
The above code can be written in more "optimized"
way. Harder to understand but more compact.
Thanks to J. Tordera for the tip!
buf[0]= (byte)(b[i] >> 2);
buf[1]= (byte)(((b[i] &0x03) << 4)|(b[i+1]>> 4));
buf[2]= (byte)(((b[i+1] &0x0F)<< 2)|(b[i+2]>> 6));
buf[3]= (byte)(b[i+2] &0x3F);
send(out,BaseTable[buf[0]]+BaseTable[buf[1]]+
BaseTable[buf[2]]+BaseTable[buf[3]]);
*/

if ((linelength += 4) >= 76) {


send(out, "\r\n");
linelength = 0;
}
i += 3;
}

// deals with with the padding ...


if (nrest==2) {
// 2 bytes left
buf[0] = (byte)(( bytes[k] &0xFC) >> 2);
buf[1] = (byte)(((bytes[k] &0x03) << 4) |
((bytes[k+1] &0xF0) >> 4));
buf[2] = (byte)(( bytes[k+1] &0x0F) << 2);
}
else if (nrest==1) {
// 1 byte left
buf[0] = (byte)((bytes[k] &0xFC) >> 2);

12.14 Send email with an attachment


buf[1] = (byte)((bytes[k] &0x03) << 4);
}
if (nrest > 0) {
// send the padding
if ((linelength += 4) >= 76) send(out, "\r\n");
send(out, BaseTable[buf[0]]);
send(out, BaseTable[buf[1]]);
// Thanks to R. Claerman for the bug fix here!
if (nrest==2) {
send(out, BaseTable[buf[2]]);
}
else {
send(out, "=");
}
send(out, "=");
}
out.flush();
}
catch (Exception e) {
e.printStackTrace();
}
}

public static void send(BufferedWriter out, String s) {


try {
out.write(s);
System.out.print(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

If Elvis want to send a GIF and a text file about his Gumby old friend then he would change his
sendMail() for something like this

...

/* Name of files to be sent. */


String FileName1 = "gumby.gif";
String FileName2 = "gumby.txt";

...

public void sendMail(String mailServer, String recipient) {


System.out.println("Send mail with attached file");
try {
Socket s = new Socket(mailServer, 25);
BufferedReader in = new BufferedReader
(new InputStreamReader(s.getInputStream(), "8859_1"));
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(s.getOutputStream(), "8859_1"));

String boundary = "DataSeparatorString";

// here you are supposed to send your username


sendln(in, out, "HELO world");
sendln(in, out, "MAIL FROM: <real@gagnon.com>");
sendln(in, out, "RCPT TO: <" + recipient + ">" );
sendln(in, out, "DATA");
sendln(out, "MIME−Version: 1.0");

12.14 Send email with an attachment


sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock<");
sendln
(out,"Content−Type: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n−−" + boundary);

// send the GIF


sendln(out, "Content−Type: text/plain; charset=\"us−ascii\"\r\n");
sendln(out, "I'm alive. Help me!\n\n");
sendln(out, "\r\n" + "−−" + boundary );
sendln(out, "Content−Type:image/gif; name="+FileName1);
sendln
(out, "Content−Disposition: attachment;filename=\""+FileName1+"\"");
sendln(out, "Content−transfer−encoding: base64\r\n");
MIMEBase64.encode(FileName1, out);
sendln(out, "\r\n−−" + boundary);

// the text file


sendln(out, "Content−Type: text/plain; name="+FileName2);
sendln(out, "Content−Disposition: inline;filename=\""+FileName2+"\"");
// to send the file as an attachment instead of "inline" use :
// sendln
// (out, "Content−Type: text/plain; name="+FileName2);
// sendln
// (out,"Content−Disposition: attachment;filename=\""+FileName2+"\"");
sendln(out, "Content−Transfer−Encoding: base64\r\n");
MIMEBase64.encode(FileName2, out);
sendln(out, "\r\n\r\n−−" + boundary + "−−\r\n");

// done
sendln(in, out,".");
sendln(in, out, "QUIT");
s.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
...

NOTE: A compact algorithm to encode string as Base64 can be found here. Check out the Javascript, it is very short!

NOTE: Check this related HowTo.

12.15 Send email with JavaMail


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0321.html

The JavaMail API can found here.


You need 2 jars : mail.jar and activation.jar.
It's a good idea to read the JavaMail FAQ.

Simple email

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

12.15 Send email with JavaMail


class SimpleMail {
public static void main(String[] args) throws Exception{
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "mymail.server.org");
props.setProperty("mail.user", "emailuser");
props.setProperty("mail.password", "");

Session mailSession = Session.getDefaultInstance(props, null);


Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("Testing javamail plain");
message.setContent("This is a test", "text/plain");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("elvis@presley.org"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

HTML Email
import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

class SimpleHTMLMail {
public static void main(String[] args) throws Exception{
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "mymail.server.org");
props.setProperty("mail.user", "emailuser");
props.setProperty("mail.password", "");

Session mailSession = Session.getDefaultInstance(props, null);


Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("Testing javamail html");
message.setContent
("This is a test <b>HOWTO<b>", "text/html; charset=ISO−8859−1");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("elvis@presley.org"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

Email with attachment


import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.FileDataSource;
import javax.activation.DataHandler;

12.15 Send email with JavaMail


import java.util.Properties;

class SimpleMailWithAttachment {
public static void main(String[] args) throws Exception{
boolean debug = false;
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "mymail.server.org");
props.setProperty("mail.user", "emailuser");
props.setProperty("mail.password", "");

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(debug);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("Testing javamail with attachment");

MimeBodyPart textPart = new MimeBodyPart();


textPart.setContent("<h1>Check attachment</h1>", "text/html");

MimeBodyPart attachFilePart = new MimeBodyPart();


FileDataSource fds =
new FileDataSource("SimpleMailWithAttachment.java");
attachFilePart.setDataHandler(new DataHandler(fds));
attachFilePart.setFileName(fds.getName());

Multipart mp = new MimeMultipart();


mp.addBodyPart(textPart);
mp.addBodyPart(attachFilePart);

message.setContent(mp);
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("elvis@presley.org"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

12.16 Send email with authentication


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0538.html

import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

import java.util.Properties;

public class SimpleMail {

private static final String SMTP_HOST_NAME = "smtp.myserver.com";


private static final String SMTP_AUTH_USER = "myusername";

12.16 Send email with authentication


private static final String SMTP_AUTH_PWD = "mypwd";

public static void main(String[] args) throws Exception{


new SimpleMail().test();
}

public void test() throws Exception{


Properties props = new Properties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.host", SMTP_HOST_NAME);
props.put("mail.smtp.auth", "true");

Authenticator auth = new SMTPAuthenticator();


Session mailSession = Session.getDefaultInstance(props, auth);
// uncomment for debugging infos to stdout
// mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setContent("This is a test", "text/plain");
message.setFrom(new InternetAddress("me@myhost.org"));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("elvis@presley.org"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}

private class SMTPAuthenticator extends javax.mail.Authenticator {


public PasswordAuthentication getPasswordAuthentication() {
String username = SMTP_AUTH_USER;
String password = SMTP_AUTH_PWD;
return new PasswordAuthentication(username, password);
}
}
}

NOTE : The JavaMail Authenticator is found in the javax.mail package and is different from the java.net class of the same name. The two
don't share the same Authenticator as the JavaMail API works with Java 1.1, which didn't have the java.net variety.

12.17 Handle EML file with JavaMail


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0458.html

When saving an email to a file, the resulting file has an eml extension (email files−−which are in
RFC 822 format). This kind of file can be read and parsed by JavaMail.

import java.util.*;
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;

public class ReadEmail {

public static void main(String args[]) throws Exception{


display(new File("C:\\temp\\message.eml"));

12.17 Handle EML file with JavaMail


}

public static void display(File emlFile) throws Exception{


Properties props = System.getProperties();
props.put("mail.host", "smtp.dummydomain.com");
props.put("mail.transport.protocol", "smtp");

Session mailSession = Session.getDefaultInstance(props, null);


InputStream source = new FileInputStream(emlFile);
MimeMessage message = new MimeMessage(mailSession, source);

System.out.println("Subject : " + message.getSubject());


System.out.println("From : " + message.getFrom()[0]);
System.out.println("−−−−−−−−−−−−−−");
System.out.println("Body : " + message.getContent());
}
}

A typical eml looks like this :

X−Mozilla−Status: 0001
X−Mozilla−Status2: 00000000
Received: from tomts25−srv.bellnexxia.net
(tomts25.bellnexxia.net [209.226.175.188])
by tactika.com (8.9.3/8.9.3) with ESMTP id NAA07621
for ; Sun, 1 Feb 2004 13:25:33 −0500 (EST)
Date: Sun, 01 Feb 2004 13:31:40 −0500
From: real gagnon
Reply−To: real@rgagnon.com
User−Agent: Mozilla/5.0
(Windows; U; Windows NT 5.1; en−US; rv:1.4)
Gecko/20030624 Netscape/7.1 (ax)
X−Accept−Language: en−us, en
MIME−Version: 1.0
To: real@rgagnon.com
Subject: Example for HowTo
Content−Type: text/plain; charset=us−ascii; format=flowed
Content−Transfer−Encoding: 7bit
X−UIDL: oP#!!c]^!!1;−!!T@1"!

This is an example for HowTo

Running the above HowTo gives this output :

Subject : Example for HowTo


From : real gagnon
−−−−−−−−−−−−−−
Body :
This is an example for HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

12.17 Handle EML file with JavaMail


12.18 Send HTML mail with images (Javamail)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0504.html

It's easy to send HTML mail with JavaMail. Simply set the content type to "text/html".

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

class SimpleMail {
public static void main(String[] args) throws Exception{
System.out.println("Sending mail...");
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "smtp.mymailserver.com");
props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("HTML mail with images");
message.setFrom(new InternetAddress("me@sender.com"));
message.setContent("<h1>Hello world</h1>", "text/html");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("you@receiver.com"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

One approach to include images in the mail body is to use the IMG tag and make the images
available on a server.

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

class SimpleMail1 {
public static void main(String[] args) throws Exception{
System.out.println("Sending mail...");
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "smtp.mymailserver.com");
props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

12.18 Send HTML mail with images (Javamail)


MimeMessage message = new MimeMessage(mailSession);
message.setSubject("HTML mail with images");
message.setFrom(new InternetAddress("me@sender.com"));
message.setContent
("<h1>This is a test</h1>"
+ "<img src=\"http://www.rgagnon.com/images/jht.gif\">",
"text/html");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("you@receiver.com"));

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

The browser accesses these images just as if it were displaying an image in a Web page.
Unfortunately, spammers have used this mechanism as a sneaky way to record who visits their
site (and mark your email as valid). To protect your privacy, many Web−based (and other) email
clients don't display images in HTML emails.

An alternative to placing absolute URLs to images in your HTML is to include the images as
attachments to the email. The HTML can reference the image in an attachment by using the
protocol prefix cid: plus the content−id of the attachment.

import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

import java.util.Properties;

class SimpleMail2 {
public static void main(String[] args) throws Exception{
System.out.println("Sending mail...");
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "smtp");
props.setProperty("mail.host", "smtp.mymailserver.com");
props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("HTML mail with images");
message.setFrom(new InternetAddress("me@sender.com"));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("you@receiver.com"));

//
// This HTML mail have to 2 part, the BODY and the embedded image
//
MimeMultipart multipart = new MimeMultipart("related");

// first part (the html)


BodyPart messageBodyPart = new MimeBodyPart();
String htmlText = "<H1>Hello</H1><img src=\"cid:image\">";
messageBodyPart.setContent(htmlText, "text/html");

12.18 Send HTML mail with images (Javamail)


// add it
multipart.addBodyPart(messageBodyPart);

// second part (the image)


messageBodyPart = new MimeBodyPart();
DataSource fds = new FileDataSource
("C:\\images\\jht.gif");
messageBodyPart.setDataHandler(new DataHandler(fds));
messageBodyPart.setHeader("Content−ID","<image>");

// add it
multipart.addBodyPart(messageBodyPart);

// put everything together


message.setContent(multipart);

transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

12.19 Debug a Javamail Program


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0552.html

Set the Javamail DEBUG mode "on" :

Session mailSession = Session.getDefaultInstance(props, null);


mailSession.setDebug(true);

This setting puts the Javamail classes in verbose mode to System.out.

Verify connectivity to the MailServer with Telnet :

telnet mymailserver 25

for example, you can detect if your firewall is blocking your connection.

Use a Javamail server mock−up to act as "in−memory" mail server :


See https://mock−javamail.dev.java.net/ and http://quintanasoft.com/dumbster/. These mock−ups
are designed to act a mail server but the actual email is not delivered to the mail recipient which
can be useful in a testing stage.

12.19 Debug a Javamail Program


12.20 Send email with SMTPS (eg. Google GMail) (Javamail)
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0570.html

It's not uncommon that the outgoing mail needs to be encrypted using the SMTPS protocol.

It's the case for GMAIL for example.

You need Javamail 1.4 to use the SMTPS protocol.

import javax.mail.*;
import javax.mail.internet.*;

import java.util.Properties;

public class SimpleSSLMail {

private static final String SMTP_HOST_NAME = "smtp.gmail.com";


private static final int SMTP_HOST_PORT = 465;
private static final String SMTP_AUTH_USER = "myaccount@gmail.com";
private static final String SMTP_AUTH_PWD = "mypwd";

public static void main(String[] args) throws Exception{


new SimpleSSLMail().test();
}

public void test() throws Exception{


Properties props = new Properties();

props.put("mail.transport.protocol", "smtps");
props.put("mail.smtps.host", SMTP_HOST_NAME);
props.put("mail.smtps.auth", "true");
// props.put("mail.smtps.quitwait", "false");

Session mailSession = Session.getDefaultInstance(props);


mailSession.setDebug(true);
Transport transport = mailSession.getTransport();

MimeMessage message = new MimeMessage(mailSession);


message.setSubject("Testing SMTP−SSL");
message.setContent("This is a test", "text/plain");

message.addRecipient(Message.RecipientType.TO,
new InternetAddress("elvis@presley.org"));

transport.connect
(SMTP_HOST_NAME, SMTP_HOST_PORT, SMTP_AUTH_USER, SMTP_AUTH_PWD);

transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

The property

props.put("mail.smtps.quitwait", "false");

12.20 Send email with SMTPS (eg. Google GMail) (Javamail)


is required to get rid of a strange SSL exception :

javax.mail.MessagingException: Exception reading response;


nested exception is:
javax.net.ssl.SSLException: Unsupported record version Unknown−50.49
...

The mail is sent but the exception is unwanted...

The property quitwait means

If set to false, the QUIT command is sent and the connection


is immediately closed. If set to true (the default), causes
the transport to wait for the response to the QUIT command.

ref : http://java.sun.com/products/javamail/javadocs/com/sun/mail/smtp/package−summary.html

This setting, mail.smtps.quitwait, is not required anymore! (july2007)

12.20.1 Settings for well known mail providers

Yahoo
Incoming Mail Server − pop.mail.yahoo.com (POP3 − port 110)
Outgoing Mail Server − smtp.mail.yahoo.com (SMPTP − port 25)
Google GMail
Incoming Mail Server − pop.gmail.com (POP3S SSL enabled, port 995)
Outgoing Mail Server − gmail.com (SMPTS SSL enabled, port 465)

12.21 Mix plain text and HTML content in a mail


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0471.html

Properties props = new Properties();


props.put("mail.smtp.host", "MYMAILSERVER");
Session session = Session.getInstance(props,null);
MimeMessage message = new MimeMessage(session);

InternetAddress from = new InternetAddress("from@me.com");


InternetAddress to = new InternetAddress("to@you.com");

message.setSubject("I am a multipart text/html email" );


message.setFrom(from);
message.addRecipient(Message.RecipientType.TO, to);

Multipart multipart = new MimeMultipart();

// PLAIN TEXT
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText("Here is your plain text message");
multipart.addBodyPart(messageBodyPart);

// HTML TEXT
messageBodyPart = new MimeBodyPart();
String htmlText = "<H1>I am the html part</H1>";
messageBodyPart.setContent(htmlText, "text/html");

12.20.1 Settings for well known mail providers


multipart.addBodyPart(messageBodyPart);

message.setContent(multipart);
Transport.send(message);

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

12.22 Check if a file was modified on the server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0069.html

URL u =null;

long timestamp = 0;

try {
u = new URL(getDocumentBase(), "test.gif");
URLConnection uc = u.openConnection();
uc.setUseCaches(false);
/*
** use timestamp has a reference, re−open an URLConnection
** to the same file to check if the timestamp is different
** with the getLastModified() method.
*/
timestamp = uc.getLastModified();
}
catch (Exception e) {
e.printStackTrace();
}
}

12.23 Check if a page exists


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0059.html

[JDK1.1]

import java.net.*;
import java.io.*;

public class URLUtils {

public static void main(String s[]) {


System.out.println(URLUtils.exists("http://www.rgagnon.com/howto.html"));
System.out.println(URLUtils.exists("http://www.rgagnon.com/pagenotfound.html"));
/*
output :
true
false
*/
}

12.22 Check if a file was modified on the server


public static boolean exists(String URLName){
try {
HttpURLConnection.setFollowRedirects(false);
// note : you may also need
// HttpURLConnection.setInstanceFollowRedirects(false)
HttpURLConnection con =
(HttpURLConnection) new URL(URLName).openConnection();
con.setRequestMethod("HEAD");
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
}

Thanks to Steve B. for the bug fix!

The following is doing the same thing but this time we identify ourself to a proxy. See also this
HowTo.

import java.net.*;
import java.io.*;
import java.util.Properties;

public class URLUtils {

public static void main(String s[]) {


System.out.println(exists("http://www.rgagnon.com"));
System.out.println(exists("http://www.yahoo.com"));
}

public static boolean exists(String URLName){


try {
Properties systemSettings = System.getProperties();
systemSettings.put("proxySet", "true");
systemSettings.put("http.proxyHost","proxy.mycompany.local") ;
systemSettings.put("http.proxyPort", "80") ;

URL u = new URL(URLName);


HttpURLConnection con = (HttpURLConnection) u.openConnection();
//
// it's not the greatest idea to use a sun.misc.* class
// Sun strongly advises not to use them since they can
// change or go away in a future release so beware.
//
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String encodedUserPwd =
encoder.encode("domain\\username:password".getBytes());
con.setRequestProperty
("Proxy−Authorization", "Basic " + encodedUserPwd);
con.setRequestMethod("HEAD");
System.out.println
(con.getResponseCode() + " : " + con.getResponseMessage());
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
}
catch (Exception e) {
e.printStackTrace();
return false;

12.22 Check if a file was modified on the server


}
}
}

12.24 Connect through a Proxy


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0085.html

You have to set the following properties :

http.proxyHost (default: <none>)


http.proxyPort (default: 80 if http.proxyHost specified)
http.nonProxyHosts (default: <none>)

NOTE: proxyHost, proxyPort are deprecated. you have to prefix them with "http.".
NOTE: Those properties are documented here :
http://java.sun.com/j2se/1.4/docs/guide/net/properties.html.

You can set the required properties when starting the JVM for a JAVA application from the
command line:

java −Dhttp.proxyhost=myproxyserver.com −Dhttp.proxyport=80 MyJavaApp

Or in your source :

import java.util.Properties;
...
Properties systemSettings = System.getProperties();
systemSettings.put("http.proxyHost", "myProxyServer.com");
systemSettings.put("http.proxyPort", "80");
System.setProperties(systemSettings);

You might need to identify yourself to the proxy server.

One way is to use the HTTP property "Proxy−Authorization" with a username:password base64
encoded.

Properties systemSettings = System.getProperties();


...
System.setProperties(systemSettings);

URL url=new URL("http://someserver/somepage");


URLConnection uc = url.openConnection ();
String encoded = new String
(Base64.base64Encode(new String("username:password").getBytes()));
uc.setRequestProperty("Proxy−Authorization", "Basic " + encoded);
uc.connect();

NOTE: For a base64 function, see this How−to.

The following example dumps the content of a URL but before we identify ourself to the proxy
import java.net.*;
import java.io.*;
import java.util.Properties;

12.24 Connect through a Proxy


public class URLUtils {
public static void main(String s[]) {
URLUtils.dump("http://www.yahoo.com");
System.out.println("**************");
URLUtils.dump("https://www.paypal.com");
System.out.println("**************");
}

public static void dump(String URLName){


try {
DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];

// PROXY
Properties systemSettings = System.getProperties();
systemSettings.put("http.proxyHost","proxy.mydomain.local") ;
systemSettings.put("http.proxyPort", "80") ;

URL u = new URL(URLName);


HttpURLConnection con = (HttpURLConnection) u.openConnection();
//
// it's not the greatest idea to use a sun.misc.* class
// Sun strongly advises not to use them since they can
// change or go away in a future release so beware.
//
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String encodedUserPwd =
encoder.encode("mydomain\\MYUSER:MYPASSWORD".getBytes());
con.setRequestProperty
("Proxy−Authorization", "Basic " + encodedUserPwd);
// PROXY −−−−−−−−−−

di = new DataInputStream(con.getInputStream());
while(−1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

With JDK1.2, the java.net.Authenticator can be used to send the credentials when needed. When
no username/password are provided then popup is shown to ask for the credentials.

public static void dump(String URLName){


try {
DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];

// PROXY
Properties systemSettings = System.getProperties();
systemSettings.put("http.proxyHost","proxy.mydomain.local") ;
systemSettings.put("http.proxyPort", "80") ;

Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new
PasswordAuthentication("mydomain\\username","password".toCharArray());

12.24 Connect through a Proxy


}});

URL u = new URL(URLName);


HttpURLConnection con = (HttpURLConnection) u.openConnection();
di = new DataInputStream(con.getInputStream());
while(−1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}

In intranet environment, you may need to bypass the proxy server and go directly to the http
server.

The http.nonProxyHosts property indicates the hosts which should be connected too directly and
not through the proxy server. The value can be a list of hosts, each seperated by a |, and in
addition a wildcard character (*) can be used for matching.

java.exe
−Dhttp.nonProxyHosts="*.mycompany.com|*.mycompany.local|localhost"
MyClass

12.25 Identify yourself using HTTP Authentification


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0084.html

import java.net.*;
import java.io.*;

public class TestAuth {

public static void main (String args[]){


/*
** args[0] is the URL protected
** args[1] is the username
** args[2] is the password
*/
try {
BufferedReader in = new BufferedReader(
new InputStreamReader
(openURLForInput(new URL(args[0]), args[1], args[2])));
String line;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
}
catch (IOException e) {
e.printStackTrace();
}
}

public static InputStream openURLForInput


(URL url, String uname, String pword)
throws IOException

12.25 Identify yourself using HTTP Authentification


{
URLConnection conn = url.openConnection();
conn.setDoInput (true);
conn.setRequestProperty ("Authorization",
userNamePasswordBase64(uname,pword));
conn.connect ();
return conn.getInputStream();
}

public static String userNamePasswordBase64


(String username, String password)
{
return "Basic " + base64Encode (username + ":" + password);
}

private final static char base64Array [] = {


'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};

private static String base64Encode (String string) {


String encodedString = "";
byte bytes [] = string.getBytes ();
int i = 0;
int pad = 0;
while (i < bytes.length) {
byte b1 = bytes [i++];
byte b2;
byte b3;
if (i >= bytes.length) {
b2 = 0;
b3 = 0;
pad = 2;
}
else {
b2 = bytes [i++];
if (i >= bytes.length) {
b3 = 0;
pad = 1;
}
else
b3 = bytes [i++];
}
byte c1 = (byte)(b1 >> 2);
byte c2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4));
byte c3 = (byte)(((b2 & 0xf) << 2) | (b3 >> 6));
byte c4 = (byte)(b3 & 0x3f);
encodedString += base64Array [c1];
encodedString += base64Array [c2];
switch (pad) {
case 0:
encodedString += base64Array [c3];
encodedString += base64Array [c4];
break;
case 1:

12.25 Identify yourself using HTTP Authentification


encodedString += base64Array [c3];
encodedString += "=";
break;
case 2:
encodedString += "==";
break;
}
}
return encodedString;
}
}

A better alternative is the Authenticator class, see this HowTo.

NOTE: a simple explanation about the base64 encoding principle is shown in this How−to.

An alternative way to Base64 encoding is to use the Base64 class in the sun.misc.* package.

sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();


String encodedUserPwd =
encoder.encode("domain\\username:password".getBytes());
con.setRequestProperty("Proxy−Authorization", "Basic " + encodedUserPwd);

Use of the sun.* package is "discouraged" by sun and not formally supported. Those classes can
be missing in your JDK release.

Check this HowTo for a more official way to encode/decode to/from Base64.

12.26 Talk to a CGI/Servlet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0082.html

From the client point of view, there is no difference talking to CGI or Servlet. There is two ways to
send a request to a CGI. The GET method contains encoded parameters in the URL. A typical
URL talking to CGI using the GET method would be:

new URL("http://www.server.com/cgi−bin/acgi.pl?name=real);

Here we calling a script called aCGI.pl (a PERL script) passing the parameters name and site.
Parameters are encoded, spaces are changed to "+" and special character to hexadecimal using
a 3−letter escape sequence. Each parameter is delimited by the character "Habitually the
encoding is done through the static method encode of the java.net.URLencoder class.

String theCGI = "http://www.server.com/cgi−bin/aCGI.pl?";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL cgiurl = new URL(thecgi + encoded);

Once the URL is constructed, you call the CGI using the showDocument method (Applet).

getAppletContext().showDocument(cgiurl);

The CGI will process the result and produce a page to be displayed.

12.26 Talk to a CGI/Servlet


The POST method allows the programmer to manipulate the data received from the CGI. First a
connection is made to the CGI, an OutputStream is open to send the parameters (if any). Then
InputStream is created to receive the result.

String theCGI = "http://www.server.com/cgi−bin/aCGI.pl";


String encoded = "name=" + URLencoder.encode("Real Gagnon");
URL CGIurl = new URL(theCGI);

URLConnection c = CGIurl.openConnection();
c.setDoOutput(true);
c.setUseCaches(false);
c.setRequestProperty("content−type","application/x−www−form−urlencoded");
DataOutputStream out = new DataOutputStream(c.getOutputStream());
out.writeBytes(encoded);
out.flush(); out.close();

BufferedReader in =
new BufferedReader(new InputStreamReader(c.getInputStream());

String aLine;
while ((aLine = in.readLine()) != null) {
// data from the CGI
System.out.println(aLine);
}

You can't do some output then some input and do again some output. You must do all the output
and then the input. There is no "dialog" between the client and the server. The client make a
request and the server send back the result and close the connection.

12.27 Write/Read cookies using HTTP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0092.html

For a Java−Javascript solution, check this How−to.

import java.net.*;
import java.io.*;
import java.util.*;

class CookiesInJava {
static Hashtable theCookies = new Hashtable();
/**
* Send the Hashtable (theCookies) as cookies, and write them to
* the specified URLconnection
*
* @param urlConn The connection to write the cookies to.
* @param printCookies Print or not the action taken.
*
* @return The urlConn with the all the cookies in it.
*/
public URLConnection writeCookies
(URLConnection urlConn, boolean printCookies){
String cookieString = "";
Enumeration keys = theCookies.keys();
while (keys.hasMoreElements()) {
String key = (String)keys.nextElement();
cookieString += key + "=" + theCookies.get(key);

12.27 Write/Read cookies using HTTP


if (keys.hasMoreElements())
cookieString += "; ";
}
urlConn.setRequestProperty("Cookie", cookieString);
if (printCookies)
System.out.println("Wrote cookies:\n " + cookieString);
return urlConn;
}

/**
* Read cookies from a specified URLConnection, and insert them
* to the Hashtable
* The hashtable represents the Cookies.
*
* @param urlConn the connection to read from
* @param printCookies Print the cookies or not, for debugging
* @param reset Clean the Hashtable or not
*/
public void readCookies(URLConnection urlConn, boolean printCookies,
boolean reset){
if (reset)
theCookies.clear();
int i=1;
String hdrKey;
String hdrString;
String aCookie;
while ((hdrKey = urlConn.getHeaderFieldKey(i)) != null) {
if (hdrKey.equals("Set−Cookie")) {
hdrString = urlConn.getHeaderField(i);
StringTokenizer st = new StringTokenizer(hdrString,",");
while (st.hasMoreTokens()) {
String s = st.nextToken();
aCookie = s.substring(0, s.indexOf(";"));
// aCookie = hdrString.substring(0, s.indexOf(";"));
int j = aCookie.indexOf("=");
if (j != −1) {
if (!theCookies.containsKey(aCookie.substring(0, j))){
// if the Cookie do not already exist then when keep it,
// you may want to add some logic to update
// the stored Cookie instead. thanks to rwhelan
theCookies.put
(aCookie.substring(0, j),aCookie.substring(j + 1));
if (printCookies){
System.out.println("Reading Key: "
+ aCookie.substring(0, j));
System.out.println(" Val: "
+ aCookie.substring(j + 1));
}
}
}
}
}
i++;
}
}

/**
* Display all the cookies currently in the HashTable
*
*/
public void viewAllCookies() {
System.out.println("All Cookies are:");
Enumeration keys = theCookies.keys();

12.27 Write/Read cookies using HTTP


String key;
while (keys.hasMoreElements()){
key = (String)keys.nextElement();
System.out.println(" " + key + "=" +
theCookies.get(key));
}
}

/**
* Display the current cookies in the URLConnection,
* searching for the: "Cookie" header
*
* This is Valid only after a writeCookies operation.
*
* @param urlConn The URL to print the associates cookies in.
*/
public void viewURLCookies(URLConnection urlConn) {
System.out.print("Cookies in this URLConnection are:\n ");
System.out.println(urlConn.getRequestProperty("Cookie"));
}

/**
* Add a specific cookie, by hand, to the HastTable of the Cookies
*
* @param _key The Key/Name of the Cookie
* @param _val The Calue of the Cookie
* @param printCookies Print or not the result
*/
public void addCookie(String _key, String _val, boolean printCookies){
if (!theCookies.containsKey(_key)){
theCookies.put(_key,_val);
if (printCookies){
System.out.println("Adding Cookie: ");
System.out.println(" " + _key + " = " + _val);
}
}
}
}

Thanks to Saar Machtiner for the bug fix

12.28 Read a GIF or CLASS from an URL save it locally


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0060.html

import java.io.*;
import java.net.*;

public class SuckURL {


String aFile;
String aURL;

public static void main(String args[]) {


// GIF JAVA How−to at Real's Home
String url =
"http://www.rgagnon.com/images/";
SuckURL b = new SuckURL(url, "jht.gif");
b.doit();
}

12.28 Read a GIF or CLASS from an URL save it locally


SuckURL(String u, String s){
aURL = u;
aFile = s;
}

public void doit() {


DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];

try {
System.out.println("Sucking " + aFile);
System.out.println(" at " + aURL );
// input
URL url = new URL(aURL + aFile);
URLConnection urlConnection = url.openConnection();
urlConnection.connect();
di = new DataInputStream(urlConnection.getInputStream());

// output
fo = new FileOutputStream(aFile);

// copy the actual file


// (it would better to use a buffer bigger than this)
while(−1 != di.read(b,0,1))
fo.write(b,0,1);
di.close();
fo.close();
}
catch (Exception ex) {
System.out.println("Oups!!!");
ex.printStackTrace();
System.exit(1);
}
System.out.println("done.");
}
}

This example dumps a page using the HTTPS protocol :

import java.io.*;
import java.net.*;
public class URLReader {
public static void main(String[] args) throws Exception {
// no longer necessary since JSSE is now included in
// recent jdk release...
// Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
// System.setProperty("java.protocol.handler.pkgs",
// "com.sun.net.ssl.internal.www.protocol");

URL url = new URL("https://www.thawte.com");


HttpURLConnection con = (HttpURLConnection) url.openConnection();

BufferedReader in = new BufferedReader(


new InputStreamReader(
con.getInputStream()));
String inputLine;

while ((inputLine = in.readLine()) != null)


System.out.println(inputLine);
in.close();
}

12.28 Read a GIF or CLASS from an URL save it locally


}

There is an issue with root certificate from Verisign (jdk142 or less, you have exception talking
about "untrusted server"), you may want to review this note :
http://sunsolve.sun.com/search/document.do?assetkey=1−26−57436−1.

12.29 Resolve a relative URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0297.html

import java.net.URL;

public class ResolveRelativeURL {


public static void main (String[] args) throws
java.net.MalformedURLException {
URL relativeURL, baseURL;
baseURL = new URL ("http://www.rgagnon.com/");
relativeURL = new URL ( baseURL, "./javadetails/java−0001.html");
System.out.println ( relativeURL.toExternalForm ());
/*
output :
http://www.rgagnon.com/javadetails/java−0001.html
*/
}
}

12.30 File size from URL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0298.html

import java.io.*;
import java.net.*;

public class FileSizeFromURL {


public static final void main(String[] args) {
URL url;
URLConnection conn;
int size;

if(args.length != 1) {
System.out.println("Usage: FileSizeFromURL ");
return;
}

try {
url = new URL(args[0]);
conn = url.openConnection();
size = conn.getContentLength();
if(size <0)
System.out.println("Could not determine file size.");
else
System.out.println(args[0] + "\nSize: " + size);
conn.getInputStream().close();
}

12.29 Resolve a relative URL


catch(Exception e) {
e.printStackTrace();
}
}
}

12.31 Use the HTTPS protocol


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0308.html

For Applets, both IE and NN have implemented https in their java.net.URL class so just use it
exactly as you would for a regular http URL.

URL ssl = new URL("https://www.secureserver.com);


InputStream is = ssl.openStream();

For application, take a look at the Sun's Secure Socket Extension (JSSE).

Before connecting with a secure URL, we must do this first :

java.security.Security.addProvider(new
com.sun.net.ssl.internal.ssl.Provider());

System.setProperty
("java.protocol.handler.pkgs",
"com.sun.net.ssl.internal.www.protocol");

A useful link for that is this JavaWorld's Tip

Since JDK 1.4, the JSSE package is included so you don't have to add anything special. However
you may need to import the certificate from the host (that is the server that you are connecting to
using the https: protocol). One easy way to do this is to open a secured page (say
https://mysecuredhost.com) with IE, click on the SSL−symbol (bottom right) and exported the key
into the file "c:\cacerts.ce". Go in "%java_home%\bin" and type this:

keytool −import −v −alias meincert −trustcacerts −file c:\

12.32 Fetch a page from Google


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0399.html

You can't directly fetch a page from Google because a check is made (by Google) to restrict
access to "real" browser so a "403" HTTP code is returned to your Java program.

You need to fool Google by pretending to be a legitimate browser.

String search= "What you want to search for";


String google="http://www.google.ca/search?q="
+ search + "e=UTF8";

12.31 Use the HTTPS protocol


URL urlObject = new URL(google);
URLConnection con = urlObject.openConnection();
con.setRequestProperty
( "User−Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" );
webData = new BufferedReader(new InputStreamReader(con.getInputStream()));
...

Note : You may want to take a look at http://www.google.com/apis/ to learn how to interact with
Google via the official API's.

As seen above, you can directly override the HTTP header. Another way is to start the program
with a modified System.property http.agent.

>java
"−Dhttp.agent=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" MyClass

or in your program

System.setProperty
("http.agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");

12.33 Upload a file to a server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0543.html

To upload a file to a server you need something on the server side to accept the file, you can't do
it with client−side code only. A simple way to use the HTML tag in a FORM

<FORM METHOD=POST ENCTYPE="multipart/form−data" ACTION="../myuploadscript">


File to upload: <INPUT TYPE=FILE NAME="upfile"><
<INPUT TYPE=SUBMIT VALUE="Submit">
</FORM>

which looks like

File to upload:

The associated FORM target is a script on the server side that can handle HTTP file upload.
Typically in Java, it's a servlet.

The 2 most popular Java packages (server−side) to handle file upload are :
• Jakarta Commons File Upload
• O'reilly MultipartRequest (com.oreilly.servlet)

On the client side, a java application can use Jakarta Commons HTTP client to initiate a file
upload.

Postlet is a Java applet used to enable websites to allow their users to send multiple files to a
webserver with a few simple clicks. Postlet is useable with any server side scripting language that
is capable of handling file uploads.

12.33 Upload a file to a server


12.34 Connect through a Proxy
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0085.html

You have to set the following properties :

http.proxyHost (default: <none>)


http.proxyPort (default: 80 if http.proxyHost specified)
http.nonProxyHosts (default: <none>)

NOTE: proxyHost, proxyPort are deprecated. you have to prefix them with "http.".
NOTE: Those properties are documented here :
http://java.sun.com/j2se/1.4/docs/guide/net/properties.html.

You can set the required properties when starting the JVM for a JAVA application from the
command line:

java −Dhttp.proxyhost=myproxyserver.com −Dhttp.proxyport=80 MyJavaApp

Or in your source :

import java.util.Properties;
...
Properties systemSettings = System.getProperties();
systemSettings.put("http.proxyHost", "myProxyServer.com");
systemSettings.put("http.proxyPort", "80");
System.setProperties(systemSettings);

You might need to identify yourself to the proxy server.

One way is to use the HTTP property "Proxy−Authorization" with a username:password base64
encoded.

Properties systemSettings = System.getProperties();


...
System.setProperties(systemSettings);

URL url=new URL("http://someserver/somepage");


URLConnection uc = url.openConnection ();
String encoded = new String
(Base64.base64Encode(new String("username:password").getBytes()));
uc.setRequestProperty("Proxy−Authorization", "Basic " + encoded);
uc.connect();

NOTE: For a base64 function, see this How−to.

The following example dumps the content of a URL but before we identify ourself to the proxy
import java.net.*;
import java.io.*;
import java.util.Properties;

public class URLUtils {


public static void main(String s[]) {
URLUtils.dump("http://www.yahoo.com");
System.out.println("**************");
URLUtils.dump("https://www.paypal.com");

12.34 Connect through a Proxy


System.out.println("**************");
}

public static void dump(String URLName){


try {
DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];

// PROXY
Properties systemSettings = System.getProperties();
systemSettings.put("http.proxyHost","proxy.mydomain.local") ;
systemSettings.put("http.proxyPort", "80") ;

URL u = new URL(URLName);


HttpURLConnection con = (HttpURLConnection) u.openConnection();
//
// it's not the greatest idea to use a sun.misc.* class
// Sun strongly advises not to use them since they can
// change or go away in a future release so beware.
//
sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
String encodedUserPwd =
encoder.encode("mydomain\\MYUSER:MYPASSWORD".getBytes());
con.setRequestProperty
("Proxy−Authorization", "Basic " + encodedUserPwd);
// PROXY −−−−−−−−−−

di = new DataInputStream(con.getInputStream());
while(−1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

With JDK1.2, the java.net.Authenticator can be used to send the credentials when needed. When
no username/password are provided then popup is shown to ask for the credentials.

public static void dump(String URLName){


try {
DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];

// PROXY
Properties systemSettings = System.getProperties();
systemSettings.put("http.proxyHost","proxy.mydomain.local") ;
systemSettings.put("http.proxyPort", "80") ;

Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new
PasswordAuthentication("mydomain\\username","password".toCharArray());
}});

URL u = new URL(URLName);


HttpURLConnection con = (HttpURLConnection) u.openConnection();
di = new DataInputStream(con.getInputStream());

12.34 Connect through a Proxy


while(−1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}

In intranet environment, you may need to bypass the proxy server and go directly to the http
server.

The http.nonProxyHosts property indicates the hosts which should be connected too directly and
not through the proxy server. The value can be a list of hosts, each seperated by a |, and in
addition a wildcard character (*) can be used for matching.

java.exe
−Dhttp.nonProxyHosts="*.mycompany.com|*.mycompany.local|localhost"
MyClass

12.35 Have timeout on socket connection


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0086.html

[JDK11]

ServerSocket server = new ServerSocket(port);


// timeout after 60 seconds
server.setSoTimeout(60000);
try {
Socket socket=server.accept();
}
catch ( java.io.InterruptedIOException e ) {
System.err.println( "Timed Out (60 sec)!" );
}

This is true for READ operation too. Since READ operation blocks as long necessary it may be
wise to use the setSoTimeout() method. Note that when the TIMEOUT expires, an
InterruptException is thrown. However, the socket is still connected even though the Exception
was raised.

12.36 Ping a server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0093.html

It's not possible to really "ping" a machine to check if it's alive or not (it's a long story, but to keep
it short I will just say that the Socket class is not low−level enough for that operation). But we can
emulate a ping by talking the "echo port". On a server, the echo port is always port 7. We write a
string to that port and the server will echo the string.

import java.io.*;

12.35 Have timeout on socket connection


import java.net.*;

public class PseudoPing {


public static void main(String args[]) {
try {
Socket t = new Socket(args[0], 7);
DataInputStream dis = new DataInputStream(t.getInputStream());
PrintStream ps = new PrintStream(t.getOutputStream());
ps.println("Hello");
String str = dis.readLine();
if (str.equals("Hello"))
System.out.println("Alive!") ;
else
System.out.println("Dead or echo port not responding");
t.close();
}
catch (IOException e) {
e.printStackTrace();}
}
}
}

NOTE: To make this a more "complete PING", you may want to check this How−to to display the response time.

Since JDK1.5, java.net.InetAddress.isReachable(int) can be used to check if a server is


reachable or not.

import java.io.*;
import java.net.*;

public class ReachableTest {


public static void main(String args[]) {
try {
InetAddress address = InetAddress.getByName("web.mit.edu");
System.out.println("Name: " + address.getHostName());
System.out.println("Addr: " + address.getHostAddress());
System.out.println("Reach: " + address.isReachable(3000));
}
catch (UnknownHostException e) {
System.err.println("Unable to lookup web.mit.edu");
}
catch (IOException e) {
System.err.println("Unable to reach web.mit.edu");
}
}
}

isReachable() will use ICMP ECHO REQUESTs if the privilege can be obtained, otherwise it will
try to establish a TCP connection on port 7 (Echo) of the destination host. But most Internet sites
have disabled the service or blocked the requests (except some university web sites like the
example above) .

12.37 Get the Date from server


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0094.html

This can be done by opening a socket to the port "daytime" (port 13) (on Unix or NT machine).

12.37 Get the Date from server


import java.net.*;
import java.io.*;

public class GetTime {


public static void main(String args[]) {
if (args.length != 1) {
System.out.println("Usage: GetTime HOST");
return;
}
try {
Socket s = new Socket(args[0],13);
InputStream is = s.getInputStream();
while (true) {
byte b[] = new byte[100];
int i=is.read(b);
if (i==−1) return;
System.out.print(new String(b,0,i));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

12.38 Get the client IP address


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0095.html

import java.net.*;
import java.io.*;
import java.applet.*;

public class GetClientIP extends Applet {


public void init() {
try {
InetAddress thisIp =
InetAddress.getLocalHost();
System.out.println("IP:"+thisIp.getHostAddress());
}
catch(Exception e) {
e.printStackTrace();
}
}
}

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="GetClientIP.class"
HEIGHT=10 WIDTH=10>
</APPLET>
Check JAVA console for output
/BODY

Try it here

NOTE: Netscape returns the IP address with the default security settings so it's not problem. With IE5, you must go to the security TAB,
Internet, Java Custom, Edit and select "Allow access to all IP address".

12.38 Get the client IP address


Using a Servlet, this can be done with :

public void service(HttpServletRequest req, HttpServletResponse res)


throws IOException {
String IP = req.getRemoteAddr();
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

12.39 Use the java.net.Socket.setSoLinger method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0293.html

By using the setSoLinger() method, you can explicitly set a delay before a reset is sent, giving
more time for data to be read or send, or you can specify a delay of zero, meaning a reset will be
sent as soon as the java.net.Socket.close() method is invoked. You can possibly increase
performance with a delay of zero. Note that if a linger time is set to zero, then any unsent packets
are thrown away when the socket is closed otherwise the close() method blocks while waiting the
specified number of seconds for the data to be sent, and acknowledgements to be received.

The java.net.Socket.setSoLinger() method accepts as parameters a boolean and an int. The


boolean flag activates or deactivates the SO_LINGER option, and the int controls the delay time
(in seconds, max 65535).

You get the current "linger" setting with java.net.Socket.getSoLinger()

12.40 Use the java.net.Socket.setTcpNoDelay method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0294.html

java.net.Socket.setTcpNoDelay() is used to enable/disable TCP_NODELAY which disable/enable


Nagle's algorithm.

Nagle's algorithm try to conserve bandwidth by minimizing the number of segments that are sent.
When applications wish to decrease network latency and increase performance, they can disable
Nagle's algorithm (that is enable TCP_NODELAY). Data will be sent earlier, at the cost of an
increase in bandwidth consumption. The Nagle's algorithm is described in RFC 896.

You get the current "TCP_NODELAY" setting with java.net.Socket.getTcpNoDelay()

12.39 Use the java.net.Socket.setSoLinger method


12.41 Find out who is accessing my ServerSocket
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0295.html

Socket aSock = myServerSocket.accept();

System.out.println
("Connection from : "
+ aSock.getInetAddress().getHostAddress()
+ ':' + aSock.getPort());

12.42 Transfer a file via Socket


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0542.html

A client module connects to a server then a file is sent to the client. This exemple is very simple with no
authentication and hard−coded filename!

First a server module.

import java.net.*;
import java.io.*;

public class FileServer {


public static void main (String [] args ) throws IOException {
// create socket
ServerSocket servsock = new ServerSocket(13267);
while (true) {
System.out.println("Waiting...");

Socket sock = servsock.accept();


System.out.println("Accepted connection : " + sock);

// sendfile
File myFile = new File ("source.pdf");
byte [] mybytearray = new byte [(int)myFile.length()];
FileInputStream fis = new FileInputStream(myFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
OutputStream os = sock.getOutputStream();
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
os.flush();
sock.close();
}
}
}

The client module

import java.net.*;
import java.io.*;

public class FileClient{

12.41 Find out who is accessing my ServerSocket


public static void main (String [] args ) throws IOException {
int filesize=6022386; // filesize temporary hardcoded

long start = System.currentTimeMillis();


int bytesRead;
int current = 0;
// localhost for testing
Socket sock = new Socket("127.0.0.1",13267);
System.out.println("Connecting...");

// receive file
byte [] mybytearray = new byte [filesize];
InputStream is = sock.getInputStream();
FileOutputStream fos = new FileOutputStream("source−copy.pdf");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;

// thanks to A. Cádiz for the bug fix


do {
bytesRead =
is.read(mybytearray, current, (mybytearray.length−current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > −1);

bos.write(mybytearray, 0 , current);
long end = System.currentTimeMillis();
System.out.println(end−start);
bos.close();
sock.close();
}
}

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

12.41 Find out who is accessing my ServerSocket


13 Security
13.1 java−security

13.2 Encrypt a password


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0400.html

Message digests are secure one−way hash functions that take arbitrary−sized data and output a
fixed−length hash value.

public class CryptoUtils {

public static void main(String arg[]) {


try {
// quick way to do input from the keyboard, now deprecated...
java.io.StreamTokenizer Input=new java.io.StreamTokenizer(System.in);
//
System.out.print("Input your secret password : ");
Input.nextToken();
String secret = new String(CryptoUtils.encrypt(Input.sval));
System.out.println("the encrypted result : " + secret);
boolean ok = true;
String s = "";
while (ok) {
System.out.print("Now try to enter a password : " );
Input.nextToken();
s = new String(CryptoUtils.encrypt(Input.sval));
if (secret.equals(s)){
System.out.println("You got it!");
ok = false;
}
else
System.out.println("Wrong, try again...!");
}
}
catch (Exception e){
e.printStackTrace();
}

public static byte[] encrypt(String x) throws Exception


{
java.security.MessageDigest d =null;
d = java.security.MessageDigest.getInstance("SHA−1");
d.reset();
d.update(x.getBytes());
return d.digest();
}
}

The output is :

13 Security
Input your secret password : howto
the encrypted result : ûóbf−m¦esd
Now try to enter a password : Howto
Wrong, try again...!
Now try to enter a password : howTo
Wrong, try again...!
Now try to enter a password : howto
You got it!

If you need to save the encrypted string into a file, you may need to transform it into a hexadecimal
string because the encrypted string may contains non−printable characters.

One technique is to encode using Base64 the encrypted string.

sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();


String encoded=encoder.encode(secret.getBytes());
// encoded is a string with printable characters.

Or we can simply convert the byte array into an hexadecimal string:

public class StringUtils {

public static void main(String arg[]) {


byte b[] = { 7, 42, −1, −127 }; // 7, 2A, FF, 81

System.out.println(byteArrayToHexString(b));
/*
output :
072AFF81
*/
b = hexStringToByteArray(byteArrayToHexString(b));
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
/*
output :
7
42
−1
−127
*/

public static String byteArrayToHexString(byte[] b){


StringBuffer sb = new StringBuffer(b.length * 2);
for (int i = 0; i < b.length; i++){
int v = b[i] &0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}

public static byte[] hexStringToByteArray(String s) {


byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++){
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);

13 Security
b[i] = (byte)v;
}
return b;
}
}

13.3 Create a checksum


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0416.html

MD5 digests have been widely used in the software world to provide some assurance that a
downloaded file has not been altered. A user can compare a published MD5 sum with the
checksum of a downloaded file.

import java.io.*;
import java.security.MessageDigest;

public class MD5Checksum {

public static byte[] createChecksum(String filename) throws


Exception{
InputStream fis = new FileInputStream(filename);

byte[] buffer = new byte[1024];


MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != −1);
fis.close();
return complete.digest();
}

// see this How−to for a faster way to convert a byte array to


// a HEX string
public static String getMD5Checksum(String filename) throws Exception {
byte[] b = createChecksum(filename);
String result = "";
for (int i=0; i < b.length; i++) {
result +=
Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}

public static void main(String args[]) {


try {
System.out.println(getMD5Checksum("apache−tomcat−5.5.17.exe"));
// output :
// 0bb2827c5eacf570b6064e24e0e6653b
// ref :
// http://www.apache.org/dist/
// tomcat/tomcat−5/v5.5.17/bin
// /apache−tomcat−5.5.17.exe.MD5
// 0bb2827c5eacf570b6064e24e0e6653b *apache−tomcat−5.5.17.exe

13.3 Create a checksum


}
catch (Exception e) {
e.printStackTrace();
}
}
}

The next example is used to create a .chk file which contains a MD5 checksum of a given file. The
same program is used to check if a file has been altered by looking at previously generated .chk file
and compared with current checksum of the given file.

import java.security.*;
import java.io.*;

public class Checksum {

//
// return 0 error
// 1 ok (create)1
// 1 same (check)
// 2 different (check)
//
public static void main(String args[]) {
if (args.length == 2) {
if (args[0].equals("create")) {
System.exit(new Checksum().create(args[1]));
}
else if (args[0].equals("check")) {
System.exit(new Checksum().check(args[1]));
}
}
else {
System.out.println("Usage : java Checksum create [filename]\n"+
" java Checksum check [filename]");
}
}

public int create(String filename){


try {
byte[] chk = createChecksum(filename);
File f = new File(filename + ".chk");
OutputStream os = new FileOutputStream(f);
os.write(chk);
os.close();
return 1;
}
catch(Exception e) {
e.printStackTrace();
return 0;
}
}

public int check(String filename){


int rc = 0;
try {
byte[] chk1 = createChecksum(filename);
byte[] chk2 = new byte[chk1.length];
File f = new File(filename + ".chk");
InputStream is = new FileInputStream(f);

is.read(chk2);

13.3 Create a checksum


if (new String(chk2).equals(new String(chk1))) {
System.out.println("Same!");
rc = 1;
}
else {
System.out.println("Different!");
rc = 2;
}
is.close();
return rc;
}
catch(Exception e) {
e.printStackTrace();
return rc;
}
}

public byte[] createChecksum(String filename) throws Exception{


InputStream fis = new FileInputStream(filename);

byte[] buffer = new byte[1024];


MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != −1);
fis.close();
return complete.digest();
}
}

The java.util.zip package can be used to create a checksum.


import java.io.*;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

public class ComputeCRC32 {


public static long getChecksumValue(Checksum checksum, String fname) {
try {
BufferedInputStream is = new BufferedInputStream(
new FileInputStream(fname));
byte[] bytes = new byte[1024];
int len = 0;

while ((len = is.read(bytes)) >= 0) {


checksum.update(bytes, 0, len);
}
is.close();
}
catch (IOException e) {
e.printStackTrace();
}
return checksum.getValue();
}

public static void main(String[] args) {


if (args.length != 1) {
System.err.println("Usage: java ComputeCRC32 <file>");
System.exit(1);

13.3 Create a checksum


}
long cs = getChecksumValue(new CRC32(), args[0]);
System.out.println("crc32 " + args[0] + " : " + cs);
}
}

MD5 checksum can be used to validate a password without passing the actual password.

1. The server sends a random string to the client.


2. The client appends his password to the random string, and returns an MD5 sum of the result
to the server.
3. On the server, do the same and compare the MD5 sums.
4. If both MD5 are identicals then the password is good.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

13.4 Get the user name


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0048.html

In application :

String username;
username = System.getProperty("user.name");

or in JDK1.5

public class Test {


public static void main(String args[]) {
com.sun.security.auth.module.NTSystem NTSystem = new
com.sun.security.auth.module.NTSystem();
System.out.println(NTSystem.getName());
}
}

In Applet there is no way unless you ask for it or use a signed applet. If you have access to a
server−side, something like an ASP page can be used to detect the current NT user name if the
client is configured correcty.

See this related HowTo for a JSP hack!

13.5 Get username using NT Challenge (NTLM)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0441.html

13.4 Get the user name


Even if the application server do not support NTLM protocol, it is possible to use it to extract the
Windows username. From the server, we ask the browser to identify the current user, and "by
hand", we extract the response from the answer.

The browser client must support NT Challenge authentification mechanism (IE does).

This is a quick HACK to extract the username! There is no security into this. Beware...

[username.jsp]

<%@ page import="sun.misc.BASE64Encoder" %>


<p><h1>Network Windows USERNAME without any login (ie)</h1></p>
<%
String auth = request.getHeader("Authorization");
if (auth == null) {
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW−Authenticate", "NTLM");
return;
}
if (auth.startsWith("NTLM ")) {
byte[] msg =
new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;
String s;

if (msg[8] == 1) {
off = 18;

byte z = 0;
byte[] msg1 =
{(byte)'N', (byte)'T', (byte)'L', (byte)'M', (byte)'S',
(byte)'S', (byte)'P', z,
(byte)2, z, z, z, z, z, z, z,
(byte)40, z, z, z, (byte)1, (byte)130, z, z,
z, (byte)2, (byte)2, (byte)2, z, z, z, z, //
z, z, z, z, z, z, z, z};
//
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWW−Authenticate", "NTLM "
+ new sun.misc.BASE64Encoder().encodeBuffer(msg1).trim());
return;
}
else if (msg[8] == 3) {
off = 30;
length = msg[off+17]*256 + msg[off+16];
offset = msg[off+19]*256 + msg[off+18];
s = new String(msg, offset, length);
//out.println(s + " ");
}
else
return;

length = msg[off+1]*256 + msg[off];


offset = msg[off+3]*256 + msg[off+2];
s = new String(msg, offset, length);
//out.println(s + " ");
length = msg[off+9]*256 + msg[off+8];
offset = msg[off+11]*256 + msg[off+10];
s = new String(msg, offset, length);
out.println("Hello <span style='position:relative; width:190;"
+ " height:10;filter:glow(Color=#009966,Strength=1)'>");

13.4 Get the user name


out.println(s + "</SPAN>");
}
%></BODY>

NOTE: A comment from Weijun Ji : This technique only works if a user has its IE browser security setting set at middle/low (or if the server is
trusted like in an intranet environment). With this setting, browser will grab login username automatically. If the security setting is at high, then a
window will prompt user for input. At that time, whatever username the user put in will be passed to the "NTLM program". Since the user is not
authenticated, you have no way to know if this user is a true user or not. In this way, any user can pretend to be anybody else as long as he has
his security level set as high.

You want to deeper into this subject, take a look at these sites :
http://www.innovation.ch/java/ntlm.html
http://free.tagish.net/jaas/index.jsp
http://www.luigidragone.com/networking/ntlm.html

Starting from jdk1.4.2, Sun provides support for NTLM, see


http://java.sun.com/j2se/1.4.2/changes.html#networking

For a complete solution see JCIFS (for Tomcat and others) at http://jcifs.samba.org

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

13.6 Check if the current user belongs a specific Windows


group/role
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb−0227.html

You can connect to the ActiveDirectory or use some API but an easy way is to use a connection to
SQL Server. Send the query :

SELECT is_member('mydomain\g_dept')

and the result can be

0 Current user is not a member of group or role.

1 Current user is a member of group or role.

NULL Either group or role is not valid.

13.7 Prompt for password from the console


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0375.html

A separate thread is used to send to the console the backspace character to erase the last−typed
character.

import java.io.*;

13.6 Check if the current user belongs a specific Windows group/role


import java.awt.*;

public class PwdConsole {


public static void main(String[] args) throws Exception {
ConsoleEraser consoleEraser = new ConsoleEraser();
System.out.print("Password? ");
BufferedReader stdin = new BufferedReader(new
InputStreamReader(System.in));
consoleEraser.start();
String pass = stdin.readLine();
consoleEraser.halt();
System.out.print("\b");
System.out.println("Password: '" + pass + "'");
}
}

class ConsoleEraser extends Thread {


private boolean running = true;
public void run() {
while (running) {
System.out.print("\b ");
}
}

public synchronized void halt() {


running = false;
}
}

Java SE6 provides a buiilt−in mechanism to input a password from the console.

java.io.Console cons;
char[] passwd;
if ((cons = System.console()) != null &
(passwd = cons.readPassword("[%s]", "Password:")) != null) {
...
}

13.8 Display a simple username/password Dialog from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0128.html

NOTE: This way to authenticate a user is NOT secured at all since the required information is
embedded in the Applet.

[MyApplet.java]

import java.awt.*;
import java.net.*;

public class MyApplet extends java.applet.Applet {

public String username = "";


public String password = "";

public void init() {

13.8 Display a simple username/password Dialog from an Applet


if (!login()) {
try {
getAppletContext().showDocument
(new URL(getCodeBase()+"accessdenied.html"),"_top");
}
catch (Exception e) {e.printStackTrace(); }
}
else {
// here the username and password are OK
}
}

public boolean login() {


boolean userValid = false;
MyLogin login = new MyLogin (new Frame(""));
requestFocus();
if (login.id) {
username = login.username.getText();
password = login.password.getText();
userValid = validateUser(username , password);
System.out.println
("The password for " + username
+ " is " + (userValid?"valid":"invalid"));
}
else
System.out.println
("Cancel was pressed.");

login.dispose();
return userValid;

private boolean validateUser(String usr, String pwd) {


// here you will code some logic to validate the username
// password... for testing purpose :
// username = java password = avaj
return (usr.equals("java") &pwd.equals("avaj"));
}
}

[MyLogin.java]

import java.awt.*;
import java.awt.event.*;

public class MyLogin extends Dialog implements ActionListener {


boolean id = false;
Button ok,can;
TextField username;
TextField password;

MyLogin(Frame frame){
super(frame, "Welcome", true);
setLayout(new FlowLayout());
username = new TextField(15);
password = new TextField(15);
password.setEchoChar('*');
add(new Label("User :"));
add(username);
add(new Label("Password :"));
add(password);

13.8 Display a simple username/password Dialog from an Applet


addOKCancelPanel();
createFrame();
pack();
setVisible(true);
}

void addOKCancelPanel() {
Panel p = new Panel();
p.setLayout(new FlowLayout());
createButtons( p );
add( p );
}

void createButtons(Panel p) {
p.add(ok = new Button("OK"));
ok.addActionListener(this);
p.add(can = new Button("Cancel"));
can.addActionListener(this);
}

void createFrame() {
Dimension d = getToolkit().getScreenSize();
setLocation(d.width/4,d.height/3);
}

public void actionPerformed(ActionEvent ae){


if(ae.getSource() == ok) {
id = true;
setVisible(false);
}
else if(ae.getSource() == can) {
id = false;
setVisible(false);
}
}
}

the HTML to test it out :


[login.html]

<HTML><HEAD><BODY>
<TABLE><TR><TD>
<APPLET CODE=MyApplet.class WIDTH=300 HEIGHT=300>
</APPLET></TABLE>
NOTE: View the java console for infos about the login process
</BODY></HEAD>
</HMTL>

A simple "Access is denied" page :


[accessdenied.html]

<HTML>
access is denied
</HMTL>

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

13.8 Display a simple username/password Dialog from an Applet


13.8 Display a simple username/password Dialog from an Applet
14 Swing
14.1 java−swing

14.2 * Read me *
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0193.html

NOTE: With the JDK1.2 release, it's recommended to use

import javax.swing.*;

instead of

import com.sun.java.swing.*;

IE or Netscape don't support directly Swing Applet. You must use the Java plugins. Then you will
need to use the <OBJECT> (IE) or <EMBED> (Netscape) HTML tag instead of the regular
<APPLET> tag.

14.3 Change component default font


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0335.html

public static void setUIFont (javax.swing.plaf.FontUIResource f){


//
// sets the default font for all Swing components.
// ex.
// setUIFont (new javax.swing.plaf.FontUIResource
// ("Serif",Font.ITALIC,12));
//
java.util.Enumeration keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = UIManager.get (key);
if (value instanceof javax.swing.plaf.FontUIResource)
UIManager.put (key, f);
}
}

For a particuliar component

UIManager.put("Label.font",new Font("Serif",Font.ITALIC,12));

Swing UI default

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

14 Swing
Written and compiled by Réal Gagnon ©1998−2005
[ home ]

14.4 Repaint problem under the mouse cursor (JDK1.2)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0206.html

You probably have installed a Microsoft Theme on your desktop. Simply switch the mouse cursor to
the regular Windows mouse cursor to correct the problem.

14.5 Set the LookAndFeel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0207.html

By default, Swing will use the Metal LookAndFeel. To set the LookAndFeel to the current OS under
which the JVM is running, use this snippet :

try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
e.printStackTrace();
}

Even with the new naming mecanism in JDK1.2, some LookAndFeel packages are keeping the
oldname.

Windows com.sun.java.swing.plaf.windows (no change)


Motif com.sun.java.swing.plaf.motif (no change)
Mac com.sun.java.swing.plaf.mac (no change)
Metal javax.swing.plaf.metal (new)
Basic javax.swing.plaf.basic (new)
Multi javax.swing.plaf.multi (new)

These packages are located in the rt.jar file.

14.6 Use any LookAndFeel on any plateform


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0208.html

There is some restriction to the usage of LookAndFeel when there are some copyright involved. For
example, you can't activate the Mac LookAndFeel in a Windows environment.

14.4 Repaint problem under the mouse cursor (JDK1.2)


The trick is to fool Swing by setting the property os.name to a different value than real one to enable
the use of "forbidden" LookAndFeel.

From the command line,


to activate Windows LookAndFeel on a non−Windows environment

java −Dos.name=windows MySwingApp

to activate Mac LookAndFeel on a non−Mac environment

java −Dos.name=mac MySwingApp

or you can do it in your source by doing something like:

Properties p = System.getProperties();
p.put("os.name", "Mac");
System.setProperties(p);

NOTE: Current Swing release for Windows does not include the necessary classes for the Mac's LookAndFeel anymore.

It's not bad idea to set the look and feel to a known good value and then try the not−so−sure value.

try {
// sure look and feel
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");

// not−so−sure look and feel


System.setProperty("os.name", "Windows");
System.setProperty("os.version", "5.1");
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch (Exception ex) {
ex.printStackTrace();
}

14.7 Use a Timer


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0220.html

See this How−to.

14.8 Share ActionEvent handler


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0212.html

In this example, a JMenu, JToolbar and JButtons on a JFrame are sharing common ActionEvent
handlers.

import javax.swing.*;
import java.awt.event.*;

14.7 Use a Timer


import java.awt.*;

public class ShareAction extends JFrame {


OpenAction openAction = new OpenAction();
SaveAction saveAction = new SaveAction();
QuitAction quitAction = new QuitAction();

public static void main(String argv[]) {


new ShareAction().setVisible(true);
}

ShareAction() {
createMenu();
createToolBar();
createButtons();
pack();

// deal closing via the upper right "X" by redirecting to


// quitAction
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
ActionEvent ae =
new ActionEvent (quitAction,
ActionEvent.ACTION_PERFORMED,
"bebye");
JFrame j = (JFrame)e.getSource();
j.dispatchEvent(ae);
}
}
);
}

public Dimension getPreferredSize() {


return new Dimension(300,300);
}

private void createMenu(){


JMenuBar mb = new JMenuBar();
JMenu file = new JMenu("File");
mb.add(file);
file.add(openAction);
file.add(saveAction);
file.add(quitAction);
setJMenuBar(mb);
}

private void createToolBar() {


JToolBar bar = new JToolBar();
bar.add(openAction);
bar.add(saveAction);
bar.add(quitAction);
getContentPane().add(bar, "North");
}

private void createButtons() {


JPanel j = new JPanel();
JButton b1 = new JButton("Open");
JButton b2 = new JButton("Save");
JButton b3 = new JButton("Quit");
b1.addActionListener(openAction);
b2.addActionListener(saveAction);
b3.addActionListener(quitAction);

14.7 Use a Timer


j.add(b1);
j.add(b2);
j.add(b3);
getContentPane().add(j, "East");
}
}

class OpenAction extends AbstractAction {


public OpenAction() {
super("Open", new ImageIcon("open.gif"));
}
public void actionPerformed(ActionEvent e) {
System.out.println("Open action");
}
}

class SaveAction extends AbstractAction {


public SaveAction() {
super("Save", new ImageIcon("save.gif"));
}
public void actionPerformed(ActionEvent e) {
System.out.println("Save action");
}
}

class QuitAction extends AbstractAction {


public QuitAction() {
super("Quit", new ImageIcon("quit.gif"));
}
public void actionPerformed(ActionEvent e) {
System.out.println("Quit action");
System.out.println("Bye.");
System.exit(0);
}
}

14.9 Trigger a click on a Button


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0468.html

Regular AWT

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class TestEvent extends Applet implements ActionListener {


Button b2, b1;
TextField t1;

public void init() {


setLayout(new FlowLayout());
t1 = new TextField(30);
b1 = new Button("Output");
add(b1); add(t1);
b2 = new Button("Fire event 1st button");
add(b2);

b1.addActionListener(this);

14.9 Trigger a click on a Button


b2.addActionListener(this);

public void actionPerformed(ActionEvent e) {


if (e.getSource() == b1) {
t1.setText("1st button clicked");
}
if (e.getSource() == b2) {
// from the b2 button, we creating an event to trigger a click
// on the b1 button
ActionEvent ae =
new ActionEvent((Object)b1, ActionEvent.ACTION_PERFORMED, "");
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
// b1.dispatchEvent(ae); can be used too.
}
}
}

With Swing

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class TestEventSwing extends JApplet implements ActionListener {


JButton b1, b2;
JTextField t1;

public void init() {


setLayout(new FlowLayout());
t1 = new JTextField(30);
b1 = new JButton("Output");
add(b1); add(t1);
b2 = new JButton("Fire event 1st button");
add(b2);

b1.addActionListener(this);
b2.addActionListener(this);
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == b1) {
t1.setText("first button clicked");
}
if (e.getSource() == b2) {
// from the b2 button, we trigger a click on the b1 button.
// As an added bonus, a visual effect on b1 is visible!
b1.doClick();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.9 Trigger a click on a Button


14.10 Get default values for Swing−based user interface
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0507.html

This little class will dump to stdout the default values used by Swing. You can redirect the result to a
file with

>java UIDefaults > swing.props

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.UIManager;

public class UIDefaults {


public static void main(String[] args) {
try {
Set defaults = UIManager.getLookAndFeelDefaults().entrySet();
// this TreeSet will hold the sorted properties
TreeSet ts = new TreeSet(new Comparator() {
public int compare(Object a, Object b) {
Map.Entry ea = (Map.Entry) a;
Map.Entry eb = (Map.Entry) b;
return
((String) ea.getKey()).compareTo(((String)eb.getKey()));
}
});
ts.addAll(defaults);
for (Iterator i = ts.iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
System.out.print(entry.getKey() + " = " );
System.out.println(entry.getValue());
}

} catch (Exception ex) {


ex.printStackTrace();
}
}
}

• For an example on how to change a default value see this HowTo


• To change a value for a particuliar component, see this HowTo
• Here a sample list for JavaUIDefaults

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.10 Get default values for Swing−based user interface


14.11 Close a JFrame under condition
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0340.html

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class CloseOrNot extends JFrame {

JTextField field1;
JPanel panel;

public CloseOrNot() {
super( "CloseOrNot Frame" );
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
panel = new JPanel();
field1 = new JTextField( 10 );
panel.add( new JLabel("type yes to close the Frame "));
panel.add( field1 );
getContentPane().add( "Center", panel );
addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
field1.requestFocus();
}
public void windowClosing( WindowEvent e ){
if (field1.getText().equals("yes")) {
if (JOptionPane.showConfirmDialog
(null,"Are you sure ?")==JOptionPane.YES_OPTION) {
setVisible(false);
dispose();
}
}
}
} );
pack();
setVisible( true );
}

public static void main(String args[]) {


new CloseOrNot();
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.12 Maximize a JFrame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0479.html

import java.awt.*;
import javax.swing.*;

14.11 Close a JFrame under condition


public class TestMaxJFrame extends JFrame {
public TestMaxJFrame() {
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
/*
The next line determines if the taskbar (win) is covered
if unremarked, the task will not be covered by
the maximized JFRAME.
*/
// this.setMaximizedBounds(env.getMaximumWindowBounds());
this.setExtendedState(this.getExtendedState() | this.MAXIMIZED_BOTH);
}

public static void main(String[] args) {


JFrame.setDefaultLookAndFeelDecorated(true);
TestMaxJFrame t = new TestMaxJFrame();
t.setVisible(true);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.13 Capture System.out into a JFrame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0435.html

import java.awt.*;
import javax.swing.*;
import java.io.*;

/**
* http://tanksoftware.com/juk/developer/src/com/
* tanksoftware/util/RedirectedFrame.java
* A Java Swing class that captures output to the command line
** (eg, System.out.println)
* RedirectedFrame
* <p>
* This class was downloaded from:
* Java CodeGuru (http://codeguru.earthweb.com/java/articles/382.shtml) <br>
* The origional author was Real Gagnon (real.gagnon@tactika.com);
* William Denniss has edited the code, improving its customizability
*
* In breif, this class captures all output to the system and prints it in
* a frame. You can choose weither or not you want to catch errors, log
* them to a file and more.
* For more details, read the constructor method description
*/

public class RedirectedFrame extends JFrame {

// Class information
public static final String PROGRAM_NAME = "Redirect Frame";
public static final String VERSION_NUMBER = "1.1";
public static final String DATE_UPDATED = "13 April 2001";

14.13 Capture System.out into a JFrame


public static final String AUTHOR =
"Real Gagnon − edited by William Denniss";

private boolean catchErrors;


private boolean logFile;
private String fileName;
private int width;
private int height;
private int closeOperation;

TextArea aTextArea = new TextArea();


PrintStream aPrintStream =
new PrintStream(
new FilteredStream(
new ByteArrayOutputStream()));

/** Creates a new RedirectFrame.


* From the moment it is created,
* all System.out messages and error messages (if requested)
* are diverted to this frame and appended to the log file
* (if requested)
*
* for example:
* RedirectedFrame outputFrame =
* new RedirectedFrame
(false, false, null, 700, 600, JFrame.DO_NOTHING_ON_CLOSE);
* this will create a new RedirectedFrame that doesn't catch errors,
* nor logs to the file, with the dimentions 700x600 and it doesn't
* close this frame can be toggled to visible, hidden by a controlling
* class by(using the example) outputFrame.setVisible(true|false)
* @param catchErrors set this to true if you want the errors to
* also be caught
* @param logFile set this to true if you want the output logged
* @param fileName the name of the file it is to be logged to
* @param width the width of the frame
* @param height the height of the frame
* @param closeOperation the default close operation
* (this must be one of the WindowConstants)
*/
public RedirectedFrame
(boolean catchErrors, boolean logFile, String fileName, int width,
int height, int closeOperation) {

this.catchErrors = catchErrors;
this.logFile = logFile;
this.fileName = fileName;
this.width = width;
this.height = height;
this.closeOperation = closeOperation;

Container c = getContentPane();

setTitle("Output Frame");
setSize(width,height);
c.setLayout(new BorderLayout());
c.add("Center" , aTextArea);
displayLog();

this.logFile = logFile;

System.setOut(aPrintStream); // catches System.out messages

14.13 Capture System.out into a JFrame


if (catchErrors)
System.setErr(aPrintStream); // catches error messages

// set the default closing operation to the one given


setDefaultCloseOperation(closeOperation);

Toolkit tk = Toolkit.getDefaultToolkit();
Image im = tk.getImage("myicon.gif");
setIconImage(im);
}

class FilteredStream extends FilterOutputStream {


public FilteredStream(OutputStream aStream) {
super(aStream);
}

public void write(byte b[]) throws IOException {


String aString = new String(b);
aTextArea.append(aString);
}

public void write(byte b[], int off, int len) throws IOException {
String aString = new String(b , off , len);
aTextArea.append(aString);
if (logFile) {
FileWriter aWriter = new FileWriter(fileName, true);
aWriter.write(aString);
aWriter.close();
}
}
}

private void displayLog() {


Dimension dim = getToolkit().getScreenSize();
Rectangle abounds = getBounds();
Dimension dd = getSize();
setLocation((dim.width − abounds.width) / 2,
(dim.height − abounds.height) / 2);
setVisible(true);
requestFocus();
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.14 Remove the titlebar of JInternalFrame


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0333.html

((javax.swing.plaf.basic.BasicInternalFrameUI)
myInternalFrame.getUI()).setNorthPane(null);

14.14 Remove the titlebar of JInternalFrame


14.15 Have borders on a JWindow/JFrame
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0204.html

You can't have a border directly on a JWindow or JFrame. You need to put a JPanel with the
desired border using the default JWindow/JFrame LayouManager (a BorderLayout). Then the
JPanel is extended giving the impression that its borders are the JWindow one.

import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
import java.awt.*;

public class MyWindow{


public static void main(String s[]) {
JWindow win = new JWindow();

JPanel pan = new JPanel();


pan.setBorder(new LineBorder(Color.blue));
win.getContentPane().add(pan,"Center");

pan.setLayout(new FlowLayout());
pan.add(new JButton("Hello"));
pan.add(new JButton("World"));

win.setSize(200,200);
win.setVisible(true);
}
}

14.16 Display HTML in a JScrollPane


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0205.html

The JTextPane can display simple HTML page.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class TestShowPage {


public static void main(String args[]) {
JTextPane tp = new JTextPane();
JScrollPane js = new JScrollPane();
js.getViewport().add(tp);
JFrame jf = new JFrame();
jf.getContentPane().add(js);
jf.pack();
jf.setSize(400,500);
jf.setVisible(true);

try {
URL url = new URL("http://www.tactika.com/realhome/contents.html");
tp.setPage(url);

14.15 Have borders on a JWindow/JFrame


}
catch (Exception e) {
e.printStackTrace();
}
}
}

If the HTML is a located into a jar,

...
URL url = getClass().getResource("contents.html");
tp.setPage(url);
...

to set an anchor, you get the URL then add the "#anchor".

...
URL url = getClass().getResource("contents.html");
tp.setPage(new URL(url.toExternalForm() + "#section42"));
...

14.17 Use a JOptionPane


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0376.html

import java.awt.*;

import javax.swing.*;
import java.awt.event.*;

public class MessageBox {

/*
These are a list of STATIC MODAL dialogs

int return codes of button pressed:

−1 − WINDOW CLOSED − the X PRESSED


0 − YES and OK
1 − NO
2 − CANCEL

(thanks to flipside for the idea)


*/

public static int yesno(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.YES_NO_OPTION);
return result;
}

public static int yesnocancel(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.YES_NO_CANCEL_OPTION);
return result;
}

public static int okcancel(String theMessage){

14.17 Use a JOptionPane


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.OK_CANCEL_OPTION);
return result;
}

public static int ok(String theMessage){


int result = JOptionPane.showConfirmDialog((Component)
null, theMessage, "alert", JOptionPane.DEFAULT_OPTION);
return result;
}

public static void main(String args[]){


int i = MessageBox.yesno("Are your sure ?");
System.out.println("ret : " + i );
i = MessageBox.yesnocancel("Are your sure ?");
System.out.println("ret : " + i );
i = MessageBox.okcancel("Are your sure ?");
System.out.println("ret : " + i );
i = MessageBox.ok("Done.");
System.out.println("ret : " + i );
}
}

14.18 Localize a JOptionPane dialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0138.html

This example will show 2 radio buttons, one for english messages and buttons and the other one for
french. Press the button to display a localized JOptionPane according to the radio button selected.

Create 2 properties files, one for english , one for french.

[JOptionPane_en.properties]
Yes=Yes
No=No
Cancel=Cancel
SaveMsg=Do you want to save your data

[JOptionPane_fr.properties]
Yes=Oui
No=Non
Cancel=Annuler
SaveMsg=Voulez−vous sauvegarder vos donnees

Then

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class MessageBoxExample extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;

14.18 Localize a JOptionPane dialog


String msg ;

public MessageBoxExample() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

button = new JRadioButton("Francais");


button.setActionCommand("fr");
button.addActionListener(this);
group.add(button);
add(button);

go = new JButton("Do it");


go.addActionListener(this);
add(go);

locale = Locale.US;
}

public void setUILanguage() {


ResourceBundle rb;
rb = ResourceBundle.getBundle("JOptionPane", locale);

UIManager.put("OptionPane.yesButtonText", rb.getString("Yes"));
UIManager.put("OptionPane.noButtonText", rb.getString("No"));
UIManager.put("OptionPane.cancelButtonText", rb.getString("Cancel"));
msg = rb.getString("SaveMsg");
}

public void actionPerformed(ActionEvent e) {


int result;

if (e.getSource() instanceof JRadioButton) {


if (e.getActionCommand().equals("en"))
locale = Locale.US;
else
locale = Locale.FRANCE;
setUILanguage();
}
else {
// the button action
result = JOptionPane.showConfirmDialog(this,msg);
System.out.println(result);
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
MessageBoxExample panel = new MessageBoxExample();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);

14.18 Localize a JOptionPane dialog


}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

14.19 Customize JOptionPane buttons


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0310.html

String[] buttons = {"Yes", "Yes to all", "No", "Cancel"};

int rc = JOptionPane.showOptionDialog(null,
"Do you really want to delete this file [" + filename + "]?",
"Confirmation",
JOptionPane.WARNING_MESSAGE,
0,
null,
buttons,
buttons[2]);

if (rc==−1) {
System.out.println("Dialog closed without clicking a button.");
}
else {
System.out.println(buttons[rc] + " was clicked");
}

14.20 Localize a JFileChooser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0299.html

Modern Swing release have now built−in ready−to−use translations for the JFileChooser. The
language is choosen based on the current Locale. So you don't have to do anything to display the
JFileChooser in the right language.

The user interface elements provided by the J2SE Runtime Environment 5.0, include Swing dialogs,
messages written by the runtime environment to the standard output and standard error streams, as
well as messages produced by the tools provided with the JRE. These user interface elements are
localized into the following languages:

Sun Supported Locales

This example will show 2 radio buttons, one for english, one for french. Press the button to display a
localized JFileChooser according to the radio button selected.

Create 2 properties files, one for english , one for french (these files are incomplete but should be
enough to get you started).

14.19 Customize JOptionPane buttons


[JFileChooser_en.properties]

Title=Real's JFileChooser
lookInLabelText=Current
filesOfTypeLabelText=File type
upFolderToolTipText=go up

[JFileChooser_fr.properties]

Title=JFileChooser de R\u00e9al
lookInLabelText=Courant
filesOfTypeLabelText=Type de fichier
upFolderToolTipText=Remonte

Then

[LocalizeJFileChooser.java]

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class LocalizeJFileChooser extends JPanel


implements ActionListener {
JButton go;
AbstractButton button;
ButtonGroup group;
Locale locale;
String msg ;

protected JFileChooser z_chooser;


String z_choosertitle;

public LocalizeJFileChooser() {
group = new ButtonGroup();

locale = Locale.US; // default value


button = new JRadioButton("English", true);
button.setActionCommand("en");
button.addActionListener(this);
group.add(button);
add(button);

button = new JRadioButton("Francais");


button.setActionCommand("fr");
button.addActionListener(this);
group.add(button);
add(button);

go = new JButton("Do it");


go.addActionListener(this);
add(go);

locale = Locale.US;

public void setUILanguage() {


ResourceBundle rb;

14.19 Customize JOptionPane buttons


rb = ResourceBundle.getBundle("JFileChooser", locale);

z_choosertitle = rb.getString("Title");

UIManager.put
("FileChooser.lookInLabelText",
rb.getString("lookInLabelText"));
UIManager.put
("FileChooser.filesOfTypeLabelText",
rb.getString("filesOfTypeLabelText"));
UIManager.put
("FileChooser.upFolderToolTipText",
rb.getString("upFolderToolTipText"));
/*
do the same with :
FileChooser.fileNameLabelText
FileChooser.homeFolderToolTipText
FileChooser.newFolderToolTipText
FileChooser.listViewButtonToolTipTextlist
FileChooser.detailsViewButtonToolTipText
FileChooser.saveButtonText=Save
FileChooser.openButtonText=Open
FileChooser.cancelButtonText=Cancel
FileChooser.updateButtonText=Update
FileChooser.helpButtonText=Help
FileChooser.saveButtonToolTipText=Save
FileChooser.openButtonToolTipText=Open
FileChooser.cancelButtonToolTipText=Cancel
FileChooser.updateButtonToolTipText=Update
FileChooser.helpButtonToolTipText=Help

Almost all Swing widgets can be customize this way. You can
examine the Swing sources to get these values or check
http://www.gargoylesoftware.com/papers/plafdiff.html for
a list of them.

*/

public void actionPerformed(ActionEvent e) {


int result;

if (e.getSource() instanceof JRadioButton) {


if (e.getActionCommand().equals("en"))
locale = Locale.US;
else
locale = Locale.FRANCE;
setUILanguage();
}
else {
z_chooser = new JFileChooser();
z_chooser.setCurrentDirectory(new java.io.File("."));
z_chooser.setDialogTitle(z_choosertitle);
if (z_chooser.showOpenDialog(this) !=
JFileChooser.APPROVE_OPTION)
return;
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

14.19 Customize JOptionPane buttons


public static void main(String s[]) {
JFrame frame = new JFrame("");
LocalizeJFileChooser panel = new LocalizeJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

14.21 Select a directory with a JFileChooser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0370.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class DemoJFileChooser extends JPanel


implements ActionListener {
JButton go;

JFileChooser chooser;
String choosertitle;

public DemoJFileChooser() {
go = new JButton("Do it");
go.addActionListener(this);
add(go);
}

public void actionPerformed(ActionEvent e) {


int result;

chooser = new JFileChooser();


chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
//
// disable the "All files" option.
//
chooser.setAcceptAllFileFilterUsed(false);
//
if (chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): "
+ chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : "
+ chooser.getSelectedFile());
}
else {

14.21 Select a directory with a JFileChooser


System.out.println("No Selection ");
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
DemoJFileChooser panel = new DemoJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.22 Disable the JFileChooser's "New folder" button


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0569.html

No easy way to disable the "New Folder" button. You need to iterate the JFileChooser components
until the right one and disable it.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class DemoJFileChooser extends JPanel


implements ActionListener {
JButton go;

JFileChooser chooser;
String choosertitle;

public DemoJFileChooser() {
go = new JButton("Do it");
go.addActionListener(this);
add(go);
}

public void actionPerformed(ActionEvent e) {


int result;

14.22 Disable the JFileChooser's "New folder" button


chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);

disableNewFolderButton(chooser);

//
int rc = chooser.showOpenDialog(this);
if (rc == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): "
+ chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : "
+ chooser.getSelectedFile());
}
else {
System.out.println("No Selection!");
}
}

public void disableNewFolderButton( Container c ) {


int len = c.getComponentCount();
for (int i = 0; i < len; i++) {
Component comp = c.getComponent(i);
if (comp instanceof JButton) {
JButton b = (JButton)comp;
Icon icon = b.getIcon();
if (icon != null
&& icon == UIManager.getIcon("FileChooser.newFolderIcon"))
b.setEnabled(false);
}
else if (comp instanceof Container) {
disableNewFolderButton((Container)comp);
}
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");
DemoJFileChooser panel = new DemoJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

14.23 Validate a filename from a JFileChooser

14.23 Validate a filename from a JFileChooser


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0568.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class DemoJFileChooser extends JPanel


implements ActionListener {
JButton go;

JFileChooser chooser;
String choosertitle;

public DemoJFileChooser() {
go = new JButton("Do it");
go.addActionListener(this);
add(go);
}

public void actionPerformed(ActionEvent e) {


int result;

chooser = new JFileChooser();


chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle(choosertitle);
//
int rc = chooser.showOpenDialog(this);
//
// loop until a .java file is selected
//
// possible to perform complex validation
// using a regular expression with .matches(regexp)
//
while(rc == JFileChooser.APPROVE_OPTION &&
!chooser.getSelectedFile().getName().endsWith(".java")){
JOptionPane.showMessageDialog(null,
"The file " + chooser.getSelectedFile()
+ " is not java source file.", "Open Error",
JOptionPane.ERROR_MESSAGE);
rc = chooser.showOpenDialog(this);
}

if (rc == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): "
+ chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : "
+ chooser.getSelectedFile());
}
else {
System.out.println("No Selection!");
}
}

public Dimension getPreferredSize(){


return new Dimension(200, 200);
}

public static void main(String s[]) {


JFrame frame = new JFrame("");

14.23 Validate a filename from a JFileChooser


DemoJFileChooser panel = new DemoJFileChooser();
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

14.24 Make a JFrame looks like a JDialog


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0582.html

Make a JFrame unresizable and with no min/max button. The difference with JDialog is that a
JFrame is shown on the taskbar (win) while a JDialog is not.

import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JRootPane;
import javax.swing.SwingUtilities;

public class JFrameWithNoMinMax extends JFrame {

public JFrameWithNoMinMax() {
createAndShowUI();
}

private void createAndShowUI(){


setTitle("This JFRAME looks like JDialog");
setSize(new Dimension(500,100));
setUndecorated(true);
setResizable(false);
getRootPane().setWindowDecorationStyle(JRootPane.PLAIN_DIALOG);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
//addWindowListener(new WindowAdapter(){
// public void windowClosing(WindowEvent e) {
// System.out.println("Window Closing");
// System.exit(0);
// }
//});
}

public static void main(String[] args){


SwingUtilities.invokeLater(new Runnable(){
public void run(){
new JFrameWithNoMinMax().setVisible(true);

14.24 Make a JFrame looks like a JDialog


}
});
}
}

14.25 Based on JTextField content, enable or disable a JButton


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0196.html

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;

public class DemoJButtonDisabled extends JApplet {


JButton button;
JTextField textfield;
Document document;
public void init() {
getContentPane().setLayout(new FlowLayout());
textfield = new JTextField(10);
getContentPane().add(textfield);
button = new JButton("foo");
getContentPane().add(button);
button.setEnabled(false);

document = textfield.getDocument();
document.addDocumentListener
(new JButtonStateController(button));
}
}

class JButtonStateController implements DocumentListener {


private JButton button;

JButtonStateController(JButton b) {
button = b;
}

public void changedUpdate(DocumentEvent e) {


disableIfEmpty(e);
}

public void insertUpdate(DocumentEvent e){


disableIfEmpty(e);
}

public void removeUpdate(DocumentEvent e){


disableIfEmpty(e);
}

public void disableIfEmpty(DocumentEvent e) {


button.setEnabled(e.getDocument().getLength() > 0);
}
}

14.25 Based on JTextField content, enable or disable a JButton


14.26 Apply special filter to a JtextField
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0197.html

The following class will help a JTextField to filter numeric or alphanumeric characters.

import javax.swing.*;
import javax.swing.text.*;

public class JTextFieldFilter extends PlainDocument {


public static final String LOWERCASE =
"abcdefghijklmnopqrstuvwxyz";
public static final String UPPERCASE =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String ALPHA =
LOWERCASE + UPPERCASE;
public static final String NUMERIC =
"0123456789";
public static final String FLOAT =
NUMERIC + ".";
public static final String ALPHA_NUMERIC =
ALPHA + NUMERIC;

protected String acceptedChars = null;


protected boolean negativeAccepted = false;

public JTextFieldFilter() {
this(ALPHA_NUMERIC);
}
public JTextFieldFilter(String acceptedchars) {
acceptedChars = acceptedchars;
}

public void setNegativeAccepted(boolean negativeaccepted) {


if (acceptedChars.equals(NUMERIC) ||
acceptedChars.equals(FLOAT) ||
acceptedChars.equals(ALPHA_NUMERIC)){
negativeAccepted = negativeaccepted;
acceptedChars += "−";
}
}

public void insertString


(int offset, String str, AttributeSet attr)
throws BadLocationException {
if (str == null) return;

if (acceptedChars.equals(UPPERCASE))
str = str.toUpperCase();
else if (acceptedChars.equals(LOWERCASE))
str = str.toLowerCase();

for (int i=0; i <str.length(); i++) {


if (acceptedChars.indexOf(str.valueOf(str.charAt(i))) == −1)
return;
}

if (acceptedChars.equals(FLOAT) ||
(acceptedChars.equals(FLOAT + "−") &negativeAccepted)) {
if (str.indexOf(".") != −1) {

14.26 Apply special filter to a JtextField


if (getText(0, getLength()).indexOf(".") != −1) {
return;
}
}
}

if (negativeAccepted &str.indexOf("−") != −1) {


if (str.indexOf("−") != 0 || offset != 0 ) {
return;
}
}

super.insertString(offset, str, attr);


}
}

import java.awt.*;
import javax.swing.*;

public class TESTJTextFieldFilter extends JApplet{


JTextField tf1,tf1b,tf1c,tf2,tf3;
JLabel l1,l1b,l1c,l2,l3;

public void init() {


getContentPane().setLayout(new FlowLayout());
//
l1 = new JLabel("only numerics");
tf1 = new JTextField(10);
getContentPane().add(l1);
getContentPane().add(tf1);
tf1.setDocument
(new JTextFieldFilter(JTextFieldFilter.NUMERIC));

//
l1b = new JLabel("only float");
tf1b = new JTextField(10);
getContentPane().add(l1b);
getContentPane().add(tf1b);
tf1b.setDocument
(new JTextFieldFilter(JTextFieldFilter.FLOAT));

//
l1c = new JLabel("only float(can be negative)");
tf1c = new JTextField(10);
getContentPane().add(l1c);
getContentPane().add(tf1c);
JTextFieldFilter jtff = new JTextFieldFilter(JTextFieldFilter.FLOAT);
jtff.setNegativeAccepted(true);
tf1c.setDocument(jtff);

//
l2 = new JLabel("only uppercase");
tf2 = new JTextField(10);
getContentPane().add(l2);
getContentPane().add(tf2);
tf2.setDocument
(new JTextFieldFilter(JTextFieldFilter.UPPERCASE));

//
l3 = new JLabel("only 'abc123%$'");
tf3 = new JTextField(10);
getContentPane().add(l3);
getContentPane().add(tf3);

14.26 Apply special filter to a JtextField


tf3.setDocument
(new JTextFieldFilter("abc123%$"));
}
}

With JDK.14, you have the JFormattedTextField class. You can provide an input mask like (###)
###−#### for a telephone number, and it will not accept any input that doesn't follow that format.

import java.awt.Container;
import javax.swing.*;
import javax.swing.text.*;
import java.text.ParseException;

public class FormattedSample {


public static void main (String args[]) throws ParseException {
JFrame f = new JFrame("JFormattedTextField Sample");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container content = f.getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.PAGE_AXIS));
// canadian Social Security Number
MaskFormatter mf1 = new MaskFormatter("###−###−###");
mf1.setPlaceholderCharacter('_');
JFormattedTextField ftf1 = new JFormattedTextField(mf1);
content.add(ftf1);
// telephone number
MaskFormatter mf2 = new MaskFormatter("(###) ###−####");
JFormattedTextField ftf2 = new JFormattedTextField(mf2);
content.add(ftf2);
f.setSize(300, 100);
f.setVisible(true);
}
}

14.27 Limit JTextField input to a maximum length


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0198.html

import com.sun.java.swing.text.*;

public class JTextFieldLimit extends PlainDocument {


private int limit;
// optional uppercase conversion
private boolean toUppercase = false;

JTextFieldLimit(int limit) {
super();
this.limit = limit;
}

JTextFieldLimit(int limit, boolean upper) {


super();
this.limit = limit;
toUppercase = upper;
}

public void insertString


(int offset, String str, AttributeSet attr)
throws BadLocationException {

14.27 Limit JTextField input to a maximum length


if (str == null) return;

if ((getLength() + str.length()) <= limit) {


if (toUppercase) str = str.toUpperCase();
super.insertString(offset, str, attr);
}
}
}

import java.awt.*;
import javax.swing.*;

public class DemoJTextFieldWithLimit extends JApplet{


JTextField textfield1;
JLabel label1;

public void init() {


getContentPane().setLayout(new FlowLayout());
//
label1 = new JLabel("max 10 chars");
textfield1 = new JTextField(15);
getContentPane().add(label1);
getContentPane().add(textfield1);
textfield1.setDocument
(new JTextFieldLimit(10));
}
}

14.28 Validate a value on the lostFocus event


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0199.html

The problem is when the lostFocus occurs on a Component, the gainedFocus is already sent for the
next component in the SystemEventQueue. We must grab this event, and request the focus for the
previous component (if there is a validation error). We can't use
Toolkit.getDefaultToolkit().getSystemEventQueue() directly to remove the gainedFocus event
because of security restriction in Applet. This can be done with invokeLater method of the
SwingUtilities class.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class DemoLostFocus extends JApplet {


JTextField tf1, tf2;
JLabel label;

public void init() {


getContentPane().setLayout(new FlowLayout());
//
label = new JLabel("must be 'a' or 'b' ");
tf1 = new JTextField(5);
getContentPane().add(label);
getContentPane().add(tf1);
tf2 = new JTextField(5);
getContentPane().add(tf2);

14.28 Validate a value on the lostFocus event


tf1.addFocusListener(
new FocusListener() {
public void focusGained(FocusEvent e) {};

public void focusLost(FocusEvent e) {


if (!e.isTemporary() &isEnabled() ) {
String content = tf1.getText();
if (!content.equals("a") &!content.equals("b")) {
Toolkit.getDefaultToolkit().beep();
System.out.println("illegal value! " + content );
SwingUtilities.invokeLater(new FocusGrabber(tf1));
}
}}
});
}
}

class FocusGrabber implements Runnable {


private JComponent component;

public FocusGrabber(JComponent component) {


this.component = component;
}
public void run() {
component.grabFocus();
}
}

JDK1.3 provides a new class, InputVerfier, which can be used to do that.

import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;

// the first JTextField expects the string "howto" as input,


// and will allow focus to change only if the required string
// is typed.

class VerifierTest extends JFrame {


public VerifierTest () {
JTextField tf,tf2;
tf = new JTextField ("howto is required");

getContentPane().add (tf, BorderLayout.NORTH);


tf.setInputVerifier(new HowtoVerifier());

tf2 = new JTextField ("howto come here");


getContentPane().add (tf2, BorderLayout.SOUTH);

addWindowListener(new WindowCloser());
}

public static void main (String [] args) {


Frame f = new VerifierTest ();
f.pack();
f.show();
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {

14.28 Validate a value on the lostFocus event


Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class HowtoVerifier extends InputVerifier {


public boolean verify(JComponent input) {
JTextField tf = (JTextField) input;
String pass = tf.getText();
return pass.equals("howto");
}
}

It's not a bad idea to give a visual cue that the textfield is not validated. Here a bad textfield will
show a red border, a good one will be black.

import javax.swing.border.*;

...

class HowtoVerifier extends InputVerifier {


public boolean verify(final JComponent input) {
JTextField tf = (JTextField) input;
String pass = tf.getText();
if (!pass.equals("howto")) {
SwingUtilities.invokeLater(new Runnable(){
public void run(){
input.setBorder( new LineBorder(Color.RED) );
}
});
return false;
}
SwingUtilities.invokeLater(new Runnable(){
public void run(){
input.setBorder( LineBorder.createBlackLineBorder() );
}
});
return true;
}
}

...

14.29 Make sure that my jTextfield has the focus when a JFrame
is created
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0200.html

In a JFrame, use a small WindowAdapter to listen to the WindowOpened event. From there, simply
request the focus for the JTextfield. This is not needed with the Appletviewer or in Application, but
with some browsers (like Netscape), you need to do it.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

14.29 Make sure that my jTextfield has the focus when a JFrame is created
public class MyFrame extends JFrame {

JTextField field1;
JTextField field2;
JPanel panel;

public MyFrame() {
super( "This is my Frame" );
panel = new JPanel();
field1 = new JTextField( 10 );
field2 = new JTextField( 10 );
panel.add( new JLabel("Field 1:"));
panel.add( field1 );
panel.add( new JLabel("Field 2:"));
panel.add( field2 );
getContentPane().add( "Center", panel );
addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
field1.requestFocus();
}
} );
pack();
setVisible( true );
}

To try it :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MyFrameApplet extends JApplet {


public void init() {
MyFrame myFrame = new MyFrame();
}
}

14.30 Stop the beep on JFormattedTextField


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0427.html

When the user inputs an invalid value into JFormattedTextField, the default behavior is to emit a
beep. To avoid this annoying beep, simply overload the invalidEdit() method.

class MyJFormattedTextField extends JFormattedTextField {


...
protected void invalidEdit() {}
...
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.30 Stop the beep on JFormattedTextField


14.31 Right justified JTextfield content
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0493.html

import javax.swing. *;
import java.awt.*;

public class Test extends JApplet {


JTextField textfield;
public void init() {
getContentPane().setLayout(new FlowLayout());
textfield = new JTextField(10);
// Right−justify the text
textfield.setHorizontalAlignment(JTextField.RIGHT);
getContentPane().add(textfield);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.32 Set the focus on a particuliar JTextField


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0510.html

SwingUtilities.invokeLater(new Runnable() {
public void run() {
myJTextField.requestFocus();
}
});

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.33 Make JTextField unselectable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0546.html

import java.awt.*;
import java.util.*;
import java.awt.event.*;
import javax.swing.*;

class UnselectableJTextField extends JFrame {

14.31 Right justified JTextfield content


public UnselectableJTextField () {
JTextField tf1,tf2;

tf1 = new JTextField ("you can select with the mouse");


getContentPane().add (tf1, BorderLayout.NORTH);

tf2 = new JTextField ("you can't select with the mouse");


// disable mouse or keyboard selection to prevent "cut and paste"
tf2.setHighlighter(null);
//
getContentPane().add (tf2, BorderLayout.SOUTH);

addWindowListener(new WindowCloser());
}

public static void main (String [] args) {


Frame f = new UnselectableJTextField ();
f.pack();
f.setVisible(true);
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}
}

14.34 Use a JTree to navigate in a site


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0209.html

This How−to will show you how to build a Tree (like this one) using Swing.

NOTE: This Tree Applet is different since it's plain JDK1.0.2 Applet.

First, we define the class representing a node. This node contains a title (the label), a URL, 2 icons
(open and close).

import javax.swing.*;

public class RealSwingNode extends Object {


private String _title;
private String _link;
private ImageIcon _openedIcon;
private ImageIcon _closedIcon;

RealSwingNode
(String title, String link, ImageIcon closed, ImageIcon opened) {
_title = title;
_link = link;
_openedIcon = opened;
_closedIcon = closed;
}

14.34 Use a JTree to navigate in a site


String getTitle() { return _title; }
String getLink() { return _link; }
ImageIcon getOpenedIcon() { return _openedIcon; }
ImageIcon getClosedIcon() { return _closedIcon; }
public String toString() { return _title; }
}

Then we define how the node would be shown in the Tree. This is done by implementing a
Renderer class.

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;

public class RealSwingTreeIconRenderer extends Object


implements TreeCellRenderer {
JLabel _label;

RealSwingTreeIconRenderer() {
_label = new JLabel();
_label.setOpaque(true);
}

public Component getTreeCellRendererComponent


(JTree tree, Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
RealSwingNode _userObject = null;

_label.setFont(tree.getFont());

if (selected){
_label.setForeground(tree.getBackground());
_label.setBackground(tree.getForeground());
}
else {
_label.setBackground(tree.getBackground());
_label.setForeground(tree.getForeground());
}

if (value instanceof RealSwingNode) {


_userObject = (RealSwingNode) value;
}
else if(value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node;

node = (DefaultMutableTreeNode) value;

if (node.getUserObject() instanceof RealSwingNode) {


_userObject = (RealSwingNode) node.getUserObject();
}
}

if(_userObject != null) {
if (expanded)
_label.setIcon(_userObject.getOpenedIcon());
else
_label.setIcon(_userObject.getClosedIcon());
_label.setText(_userObject.getTitle());
}
else {
_label.setIcon(null);

14.34 Use a JTree to navigate in a site


_label.setText(value.toString());
}

return _label;
}
}

The next step is building the JTree in a JPanel. We use a datafile to define the Tree nodes. Since
this Tree is designed to be used in Applet, we must pass a JApplet reference to be able to read
some parameters passed via the HTML PARAM tags.

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.net.*;
import java.io.*;

public class RealSwingTree extends JPanel


implements TreeSelectionListener {
private JApplet parentApplet;
private JTree tree;
private Font f;
private ImageIcon treeIcons[];
private String targetFrame;

public RealSwingTree() {
System.out.println(System.getProperty("os.name"));
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
}
catch (Exception ex_ignored) {
ex_ignored.printStackTrace();
}
}

public void setParentApplet(JApplet j) {


parentApplet = j;
}

public void initTree() {


// build the tree from the datafile
DefaultMutableTreeNode rootNode = null;
DefaultMutableTreeNode currentNode = null;
DefaultMutableTreeNode node = null;
RealSwingNode rsn = null;
RealSwingTreeIconRenderer rstir;
TreeSelectionModel tsm;

int token, value=0, oldvalue=0, rootvalue=0, image1idx=0, image2idx=0;


String strValue, lnkValue, imageValue;
boolean rootDone=false;
boolean itemDone=true;
System.out.println("[RealSwingTree] Begin populateTree() " );
try {

initTreeIcons();
targetFrame = parentApplet.getParameter("targetframe");

14.34 Use a JTree to navigate in a site


URL urlFile =
new URL(parentApplet.getCodeBase(),
parentApplet.getParameter("datafile"));

Reader r = new BufferedReader


(new InputStreamReader(urlFile.openStream()));
StreamTokenizer st = new StreamTokenizer(r);

st.quoteChar('"');
st.eolIsSignificant(false);
st.parseNumbers();
//
// datafile structure <level> <label> <link> <image1> <image2>
//
while ((token = st.nextToken()) != StreamTokenizer.TT_EOF ) {
// get level
value = new Double(st.nval).intValue();
if (!rootDone) {
// do the root first
token = st.nextToken();
strValue = st.sval;
token = st.nextToken();
lnkValue = st.sval;
rsn = new RealSwingNode(strValue, "", null, null);
node = new DefaultMutableTreeNode(rsn, true);
rootNode = node;
rootDone = true;
}
else {
token = st.nextToken(); strValue = st.sval;
token = st.nextToken(); lnkValue = st.sval;
token = st.nextToken(); image1idx = Integer.parseInt(st.sval);
token = st.nextToken(); image2idx = Integer.parseInt(st.sval);
rsn = new RealSwingNode
(strValue, lnkValue, treeIcons[image1idx],
treeIcons[image2idx]);
node = new DefaultMutableTreeNode(rsn, true);
if (value >= oldvalue) {
if (value==oldvalue) {
// *** sibling
if (currentNode.equals(rootNode))
rootNode.add(node);
else {
DefaultMutableTreeNode dmtn =
(DefaultMutableTreeNode)currentNode.getParent();
dmtn.add(node);
}
}
else {
// *** child
currentNode.add(node);
}
}
else {
// *** new branch, must get back to the right level
while (value < oldvalue) {
currentNode =
(DefaultMutableTreeNode)currentNode.getParent();
oldvalue−−;
}
DefaultMutableTreeNode dmtn =
(DefaultMutableTreeNode)currentNode.getParent();
if (dmtn.equals(rootNode))

14.34 Use a JTree to navigate in a site


rootNode.add(node);
else
dmtn.add(node);
}
}
currentNode = node;
oldvalue = value;
}

tree = new JTree(rootNode);


Color bgcolor = new Color(
Integer.valueOf
(parentApplet.getParameter("bgcolor"), 16).intValue());
setBackground(bgcolor);
Font f = new Font
(parentApplet.getParameter("font"),
Font.PLAIN,
Integer.parseInt(parentApplet.getParameter("point")));
setFont(f);
setLayout(new BorderLayout());
tree.setRootVisible(true);
tree.setShowsRootHandles(true);

tree.addTreeSelectionListener(this);
tsm = tree.getSelectionModel();
tsm.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

rstir = new RealSwingTreeIconRenderer();


tree.setCellRenderer(rstir);
tree.setRowHeight(0);

add(new JScrollPane(tree),"Center");
}

catch (Exception e) {e.printStackTrace(); }


System.out.println("[RealSwingTree] End populatetree()");
}

public void initTreeIcons() {


String rootImage;
String pathImages;
String leaveImagesList;
Vector leaveImage = new Vector();

rootImage = parentApplet.getParameter("rootimage");
pathImages = parentApplet.getParameter("images");
leaveImagesList = parentApplet.getParameter("leaveimageslist");

System.out.println("begin initImage()");

StringTokenizer leavesList =
new StringTokenizer(leaveImagesList, ",");
while(leavesList.hasMoreTokens()){
String s=leavesList.nextToken();
leaveImage.addElement(s);
}

treeIcons = new ImageIcon[leaveImage.size()];

for(int i=0; i < leaveImage.size(); i++) {


try {
URL imageURL = new URL

14.34 Use a JTree to navigate in a site


(parentApplet.getCodeBase() + "/" + pathImages
+ "/" + (String)leaveImage.elementAt(i));
treeIcons[i] = new ImageIcon(imageURL);
System.out.println("Loading ..." + (String)leaveImage.elementAt(i));
}
catch(Exception e) { e.printStackTrace(); }
}

System.out.println("end initImage()");
}

public void valueChanged(TreeSelectionEvent tse) {


DefaultMutableTreeNode dmtn;
RealSwingNode rsn;
TreePath path = tree.getSelectionPath();

if (path != null) {
dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
rsn = (RealSwingNode)dmtn.getUserObject();
System.out.println("Click! link: " + rsn.getLink());
if (!rsn.getLink().equals("")) {
try {
URL newURL = new URL
(parentApplet.getCodeBase() + rsn.getLink());
System.out.println(" url: " + newURL.toString()
+ " target:" +targetFrame);
parentApplet.getAppletContext().showDocument
(newURL,targetFrame);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

public Dimension getPreferredSize() {


return new Dimension(250, 400);
}
}

Let's make a simple Applet to try it out.

import javax.swing.*;
import java.awt.*;

public class RealSwingTreeApplet extends JApplet {


RealSwingTree rst;

public void init() {


rst = new RealSwingTree();
rst.setParentApplet(this);
rst.initTree();
getContentPane().add(rst);
}
}

Here a sample datafile. The structure is "[level] [label] [link] [image1] [image2]". The image number
is the index of the image passed via the PARAM leaveimageslist.

14.34 Use a JTree to navigate in a site


[treedata.txt]

0 "Welcome | Bienvenue" "welcome.html"


0 "Java How−to" "" "0" "1"
1 "What's new" "java−new.html" "2" "2"
1 "General" "" "0" "1"
2 "part 1" "java−g1.html" "2" "2"

Here the HTML used to test the Tree. Since there is almost no error checking, all PARAM tags are
required.

<HTML><BODY>
<APPLET CODE="RealSwingTreeApplet.class"
NAME="RealTree"
HEIGHT=2000 WIDTH=196>
<PARAM NAME="datafile" VALUE="treedata.txt">
<PARAM NAME="bgcolor" VALUE="FFFFFF">
<PARAM NAME="font" VALUE="Courier">
<PARAM NAME="point" VALUE="11">
<PARAM NAME="images" VALUE="./images">
<PARAM NAME="targetframe" VALUE="_top">
<PARAM NAME="rootimage" VALUE="root.gif">
<PARAM NAME="leaveimageslist"
VALUE="fclose.jpg,fopen.jpg,page.jpg">
</APPLET></BODY></HTML>

The <APPLET> tag and Swing applet are ok with Appletviewer, but in most browser, you need to
execute the Applet under the Java plugin. Therefore, you need to use the <EMBED> tag with
Netscape or <OBJECT> tag with IE. So for example, with Netscape, the HTML will be like this :

<HTML><BODY>
<EMBED type="application/x−java−applet;version=1.2.2" width="200"
height="2000" code="RealSwingTreeApplet.class"
datafile="treedata.txt"
bgcolor="FFFFFF"
... other params here ...

pluginspage="http://java.sun.com/products/plugin/1.2/plugin−install.html">
<NOEMBED>
No JDK 1.2 support for APPLET!!
</NOEMBED>
</EMBED>
</BODY></HTML>

Finally, you may want to grab these images used in this How−to .

root.gif fclose.jpg fopen.jpg fpage.jpg

14.35 Expand or collapse a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0210.html

import javax.swing.*;

14.35 Expand or collapse a JTree


import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class SimpleTree extends JPanel {


JTree tree;
DefaultMutableTreeNode root, node1, node2, node3, node4;
public SimpleTree() {
root = new DefaultMutableTreeNode("root", true);
node1 = new DefaultMutableTreeNode("node 1", true);
node2 = new DefaultMutableTreeNode("node 2" , true);
node3 = new DefaultMutableTreeNode("node 3" , true);
node4 = new DefaultMutableTreeNode("node 4" , true);
root.add(node1);
node1.add(node2);
root.add(node3);
node3.add(node4);
setLayout(new BorderLayout());
tree = new JTree(root);
add(new JScrollPane((JTree)tree),"Center");
}

public Dimension getPreferredSize(){


return new Dimension(200, 120);
}

public static void main(String s[]){


MyJFrame frame = new MyJFrame("Tree Collapse Expand");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJFrame extends JFrame implements ActionListener {


JButton b1, b2, b3;
SimpleTree panel;
MyJFrame(String s) {
super(s);
setForeground(Color.black);
setBackground(Color.lightGray);
panel = new SimpleTree();
expandAll(panel.tree);
getContentPane().add(panel,"Center");

b1 = new JButton("Expand");
b3 = new JButton("Expand to last");
b2 = new JButton("Collapse");

b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
getContentPane().add(b1,"West");
getContentPane().add(b3,"North");
getContentPane().add(b2,"East");
setSize(300,300);
setVisible(true);

14.35 Expand or collapse a JTree


setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) expandAll(panel.tree);
if (ae.getSource() == b3) expandToLast(panel.tree);
if (ae.getSource() == b2) collapseAll(panel.tree);
}

public void expandAll(JTree tree) {


int row = 0;
while (row <tree.getRowCount()) {
tree.expandRow(row);
row++;
}
}

public void expandToLast(JTree tree) {


// expand to the last leaf from the root
DefaultMutableTreeNode root;
root = (DefaultMutableTreeNode) tree.getModel().getRoot();
tree.scrollPathToVisible(new TreePath(root.getLastLeaf().getPath()));
}

/*
// alternate version, suggested by C.Kaufhold
public void expandToLast(JTree tree) {
TreeModel data = tree.getModel();
Object node = data.getRoot();

if (node == null) return;

TreePath p = new TreePath(node);


while (true) {
int count = data.getChildCount(node);
if (count == 0) break;
node = data.getChild(node, count − 1);
p = p.pathByAddingChild(node);
}
tree.scrollPathToVisible(p);
}
*/

public void collapseAll(JTree tree) {


int row = tree.getRowCount() − 1;
while (row >= 0) {
tree.collapseRow(row);
row−−;
}
}
}

14.36 Have a popup attached to a JTree

14.36 Have a popup attached to a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0211.html

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class TreeWithPopup extends JPanel {


DefaultMutableTreeNode root, node1, node2, node3;
public TreeWithPopup() {
MyJTree tree;
root = new DefaultMutableTreeNode("root", true);
node1 = new DefaultMutableTreeNode("node 1", true);
node2 = new DefaultMutableTreeNode("node 2" , true);
node3 = new DefaultMutableTreeNode("node 3", true);
root.add(node1);
node1.add(node2);
root.add(node3);
setLayout(new BorderLayout());
tree = new MyJTree(root);
add(new JScrollPane((JTree)tree),"Center");
}

public Dimension getPreferredSize(){


return new Dimension(300, 300);
}

public static void main(String s[]){


JFrame frame = new JFrame("Tree With Popup");
TreeWithPopup panel = new TreeWithPopup();

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setForeground(Color.black);
frame.setBackground(Color.lightGray);
frame.getContentPane().add(panel,"Center");

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
frame.addWindowListener(new WindowCloser());
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJTree extends JTree implements ActionListener{


JPopupMenu popup;
JMenuItem mi;

MyJTree (DefaultMutableTreeNode dmtn) {


super(dmtn);
// define the popup
popup = new JPopupMenu();
mi = new JMenuItem("Insert a children");
mi.addActionListener(this);
mi.setActionCommand("insert");

14.36 Have a popup attached to a JTree


popup.add(mi);
mi = new JMenuItem("Remove this node");
mi.addActionListener(this);
mi.setActionCommand("remove");
popup.add(mi);
popup.setOpaque(true);
popup.setLightWeightPopupEnabled(true);

addMouseListener (
new MouseAdapter () {
public void mouseReleased( MouseEvent e ) {
if ( e.isPopupTrigger()) {
popup.show( (JComponent)e.getSource(),
e.getX(), e.getY() );
}
}
}
);

}
public void actionPerformed(ActionEvent ae) {
DefaultMutableTreeNode dmtn, node;

TreePath path = this.getSelectionPath();


dmtn = (DefaultMutableTreeNode) path.getLastPathComponent();
if (ae.getActionCommand().equals("insert")) {
node = new DefaultMutableTreeNode("children");
dmtn.add(node);
// thanks to Yong Zhang for the tip for refreshing the tree struct
((DefaultTreeModel )this.getModel())
.nodeStructureChanged((TreeNode)dmtn);
}
if (ae.getActionCommand().equals("remove")) {
node = (DefaultMutableTreeNode)dmtn.getParent();
node.removeAllChildren();
((DefaultTreeModel )this.getModel())
.nodeStructureChanged((TreeNode)dmtn);
}
}
}

14.37 Traverse a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0313.html

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;

public class TraverseSimpleTree extends JPanel {


JTree tree;
DefaultMutableTreeNode root, n1, n2, n3,n4,n5;
public TraverseSimpleTree() {
root = new DefaultMutableTreeNode("root", true);
n1 = new DefaultMutableTreeNode("node 1", true);
n2 = new DefaultMutableTreeNode("node 2" , true);
n3 = new DefaultMutableTreeNode("node 3" , true);
n4 = new DefaultMutableTreeNode("node 4" , true);

14.37 Traverse a JTree


n5 = new DefaultMutableTreeNode("node 5" , true);
root.add(n1);
n1.add(n2);
root.add(n3);
n3.add(n4);
n4.add(n5);
setLayout(new BorderLayout());
tree = new JTree(root);
add(new JScrollPane((JTree)tree),"Center");
}

public Dimension getPreferredSize(){


return new Dimension(200, 120);
}

public static void main(String s[]){


MyJFrame frame = new MyJFrame("Traverse Tree");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJFrame extends JFrame implements ActionListener {


JButton b1, b2, b3;
TraverseSimpleTree panel;
MyJFrame(String s) {
super(s);
setForeground(Color.black);
setBackground(Color.lightGray);
panel = new TraverseSimpleTree();
getContentPane().add(panel,"Center");

b1 = new JButton("Traverse (check the console)");

b1.addActionListener(this);
getContentPane().add(b1,"West");
setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) traverse(panel.tree);
}

public void traverse(JTree tree) {


TreeModel model = tree.getModel();
if (model != null) {
Object root = model.getRoot();
System.out.println(root.toString());
walk(model,root);
}
else
System.out.println("Tree is empty.");
}

14.37 Traverse a JTree


protected void walk(TreeModel model, Object o){
int cc;
cc = model.getChildCount(o);
for( int i=0; i < cc; i++) {
Object child = model.getChild(o, i );
if (model.isLeaf(child))
System.out.println(child.toString());
else {
System.out.print(child.toString()+"−−");
walk(model,child );
}
}
}
}

14.38 Show dotted lines in a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0325.html

In your code

...
tree.putClientProperty("JTree.lineStyle", "Angled");
...

Or from the command line

java −DJTree.lineStyle=Angled MyApp

Other possible values :

None
No lines are drawn anywhere on the tree.
Angled
Vertical lines between nodes at the same level,
horizontal line to child node.
Horizontal
A single horizontal line between nodes immediately
attached to the root node. This is the default setting.

See also List of undocumented properties to change the behavior of Swing in Suns JVM.

14.39 Explore directories with a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0324.html

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.io.*;

14.38 Show dotted lines in a JTree


public class SimpleTree extends JPanel {
JTree tree;
DefaultMutableTreeNode root;
public SimpleTree() {
root = new DefaultMutableTreeNode("root", true);
getList(root, new File("c:/temp"));
setLayout(new BorderLayout());
tree = new JTree(root);
tree.setRootVisible(false);
add(new JScrollPane((JTree)tree),"Center");
}

public Dimension getPreferredSize(){


return new Dimension(200, 120);
}

public void getList(DefaultMutableTreeNode node, File f) {


if(!f.isDirectory()) {
// We keep only JAVA source file for display in this HowTo
if (f.getName().endsWith("java")) {
System.out.println("FILE − " + f.getName());
DefaultMutableTreeNode child = new DefaultMutableTreeNode(f);
node.add(child);
}
}
else {
System.out.println("DIRECTORY − " + f.getName());
DefaultMutableTreeNode child = new DefaultMutableTreeNode(f);
node.add(child);
File fList[] = f.listFiles();
for(int i = 0; i <fList.length; i++)
getList(child, fList[i]);
}
}

public static void main(String s[]){


MyJFrame frame = new MyJFrame("Directory explorer");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJFrame extends JFrame {


JButton b1, b2, b3;
SimpleTree panel;
MyJFrame(String s) {
super(s);
panel = new SimpleTree();
getContentPane().add(panel,"Center");
setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}

14.38 Show dotted lines in a JTree


14.40 Prevent JTree collapsing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0339.html

myJTree.addTreeWillExpandListener
(new TreeWillExpandListener() {
public void treeWillExpand(TreeExpansionEvent e) { }
public void treeWillCollapse(TreeExpansionEvent e)
throws ExpandVetoException {
throw new ExpandVetoException(e, "you can't collapse this JTree");
}
});

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.41 Single selection in a JTree


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0395.html

myJTree.getSelectionModel().
setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

Also you may want to disable the CTRL−A key which select the entire tree.

[JDK1.2]
KeyStroke ks = KeyStroke.getKeyStroke("ctrl A");
tree.unregisterKeyboardAction(ks);

[JDK1.3+]
KeyStroke ks = KeyStroke.getKeyStroke("ctrl A");
tree.getInputMap().put(ks, "none");

14.42 Reduce JTree children indentation


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0398.html

BasicTreeUI basicTreeUI = (BasicTreeUI) myJTree.getUI();


basicTreeUI.setRightChildIndent(10);

14.40 Prevent JTree collapsing


14.43 Use + or − for JTree Icons
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0517.html

The default look and feel for a JTree.

If you want to use the more regular − and + sign to collapse or expand a tree node.

you need to call

UIManager.put("Tree.expandedIcon", new ImageIcon("treeMinus.gif"));


UIManager.put("Tree.collapsedIcon", new ImageIcon("treePlus.gif"));

to replace default images.

Example

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class SimpleTree extends JPanel {


JTree tree;
DefaultMutableTreeNode root, node1, node2, node3, node4;
public SimpleTree() {
root = new DefaultMutableTreeNode("root", true);
node1 = new DefaultMutableTreeNode("node 1", true);
node2 = new DefaultMutableTreeNode("node 2" , true);
node3 = new DefaultMutableTreeNode("node 3" , true);
node4 = new DefaultMutableTreeNode("node 4" , true);
root.add(node1);
node1.add(node2);
root.add(node3);
node3.add(node4);
setLayout(new BorderLayout());
UIManager.put("Tree.expandedIcon",
new ImageIcon("treeMinus.gif"));
UIManager.put("Tree.collapsedIcon",

14.43 Use + or − for JTree Icons


new ImageIcon("treePlus.gif"));
tree = new JTree(root);
add(new JScrollPane((JTree)tree),"Center");
}

public Dimension getPreferredSize(){


return new Dimension(200, 120);
}

public static void main(String s[]){


MyJFrame frame = new MyJFrame("SimpleTree");
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

class MyJFrame extends JFrame {


SimpleTree panel;
MyJFrame(String s) {
super(s);
setForeground(Color.black);
setBackground(Color.lightGray);
panel = new SimpleTree();
getContentPane().add(panel,"Center");

setSize(300,300);
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowCloser());
}
}

The required small GIFs :

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.44 Change the JTable header color


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0334.html

JTableHeader anHeader = aTable.getTableHeader();


anHeader.setForeground(new Color(0).yellow);
anHeader.setBackground(new Color(0).black);

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.44 Change the JTable header color


14.45 Double click on a JTable
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0336.html

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;

import java.awt.event.*;
import java.awt.event.*;
import java.awt.*;

public class SimpleTable


implements ListSelectionListener {
JTable aTable;
public SimpleTable() {
JFrame frame = new JFrame("Table");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}});

final String[] names = {"First Name", "Last Name", "Id" };


final Object[][] data = {
{"Mark", "Andrews", new Integer(1)},
{"Tom", "Ball", new Integer(2)},
{"Alan", "Chung", new Integer(3)},
};

TableModel dataModel = new AbstractTableModel() {


public int getColumnCount() { return names.length; }
public int getRowCount() { return data.length;}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public String getColumnName(int column) {return names[column];}
public Class getColumnClass(int col) {
return getValueAt(0,col).getClass();
}
public void setValueAt(Object aValue, int row, int column) {
data[row][column] = aValue;
}
};

aTable = new JTable(dataModel);

ListSelectionModel listMod = aTable.getSelectionModel();


listMod.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
listMod.addListSelectionListener(this);

JScrollPane scrollpane = new JScrollPane(aTable);


scrollpane.setPreferredSize(new Dimension(300, 300));
frame.getContentPane().add(scrollpane);
frame.pack();
frame.setVisible(true);

aTable.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if (e.getClickCount() == 2){
System.out.println(" double click" );

14.45 Double click on a JTable


}
}
} );
}

public void valueChanged(ListSelectionEvent e) {


int maxRows;
int[] selRows;
Object value;

if (!e.getValueIsAdjusting()) {
selRows = aTable.getSelectedRows();

if (selRows.length > 0) {
for (int i= 0; i <3 ; i++) {
// get Table data
TableModel tm = aTable.getModel();
value = tm.getValueAt(selRows[0],i);
System.out.println("Selection : " + value );
}
System.out.println();
}
}
}

public static void main(String[] args) {


new SimpleTable();
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.46 Read a data file into a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0213.html

The first line of the data file contains the column names. Fields are separated by the "|" character.

[customers.dat]

Id|Name|City|Phone
102|Beth Reiser|New York|(212)5558725
111|Dylan Ricci|Syracuse|(315)5554486
116|Brian Gugliuzza|Mamaroneck|(914)5553817
120|Gertrude Stein|Elmsford|(914)5553476
131|Daljit Sinnot|Bohemia|(516)5559811

First we need a TableModel to define the data structure to used by the JTable.

[DataFileTableModel.java]

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;

14.46 Read a data file into a JTable


import java.io.*;
import java.util.*;

public class DataFileTableModel extends AbstractTableModel {


protected Vector data;
protected Vector columnNames ;
protected String datafile;

public DataFileTableModel(String f){


datafile = f;
initVectors();
}

public void initVectors() {


String aLine ;
data = new Vector();
columnNames = new Vector();
try {
FileInputStream fin = new FileInputStream(datafile);
BufferedReader br = new BufferedReader(new InputStreamReader(fin));
// extract column names
StringTokenizer st1 =
new StringTokenizer(br.readLine(), "|");
while(st1.hasMoreTokens())
columnNames.addElement(st1.nextToken());
// extract data
while ((aLine = br.readLine()) != null) {
StringTokenizer st2 =
new StringTokenizer(aLine, "|");
while(st2.hasMoreTokens())
data.addElement(st2.nextToken());
}
br.close();
}
catch (Exception e) {
e.printStackTrace();
}
}

public int getRowCount() {


return data.size() / getColumnCount();
}

public int getColumnCount(){


return columnNames.size();
}

public String getColumnName(int columnIndex) {


String colName = "";

if (columnIndex <= getColumnCount())


colName = (String)columnNames.elementAt(columnIndex);

return colName;
}

public Class getColumnClass(int columnIndex){


return String.class;
}

public boolean isCellEditable(int rowIndex, int columnIndex) {


return false;
}

14.46 Read a data file into a JTable


public Object getValueAt(int rowIndex, int columnIndex) {
return (String)data.elementAt
( (rowIndex * getColumnCount()) + columnIndex);
}

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {


return;
}
}

[DataFileTable.java]

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.util.*;

public class DataFileTable extends JPanel {


public DataFileTable(String dataFilePath) {
JTable table;
DataFileTableModel model;
Font f;

f = new Font("SanSerif",Font.PLAIN,24);
setFont(f);
setLayout(new BorderLayout());

model = new DataFileTableModel(dataFilePath);

table = new JTable();


table.setModel(model);
table.createDefaultColumnsFromModel();

JScrollPane scrollpane = new JScrollPane(table);


add(scrollpane);
}

public Dimension getPreferredSize(){


return new Dimension(400, 300);
}

public static void main(String s[]) {


JFrame frame = new JFrame("Data File Table");
DataFileTable panel;

panel = new DataFileTable("customers.dat");

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setForeground(Color.black);
frame.setBackground(Color.lightGray);
frame.getContentPane().add(panel,"Center");

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
frame.addWindowListener(new WindowCloser());
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();

14.46 Read a data file into a JTable


win.setVisible(false);
System.exit(0);
}
}

14.47 Disable row selection in a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0338.html

aTable.setRowSelectionAllowed(false);
aTable.setColumnSelectionAllowed(false);
aTable.setCellSelectionEnabled(false);

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.48 Read a data file into a JTable and reload if data file have
changed
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0214.html

We use the Observer/Observable mechanism to detect if the data file have been modifed since the
last time.

We use the same data file and DataFileTableModel as the previous How−to. Some minor
modifications are needed for the DataFileTable class. This class now implements the Observer
interface (see the update() method which will be called when the Observable object send a
notification).

[DataFileTable.java]

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.util.*;

public class DataFileTable extends JPanel


implements Observer {
protected JTable table;
protected DataFileTableModel model;

public DataFileTable(String dataFilePath) {


DataFileWatchdog wd;
Font f;

f = new Font("SanSerif",Font.PLAIN,24);
setFont(f);
setLayout(new BorderLayout());

14.47 Disable row selection in a JTable


model = new DataFileTableModel(dataFilePath);

table = new JTable();


table.setModel(model);
table.createDefaultColumnsFromModel();

JScrollPane scrollpane = new JScrollPane(table);


add(scrollpane);

// this watchdog (an Observable object)


// is monitoring any file change
wd = new DataFileWatchdog(dataFilePath);
wd.addObserver(this);
}

public void update(Observable o, Object arg) {


// reload data because data file have changed
model.initVectors();
table.repaint();
}

public Dimension getPreferredSize(){


return new Dimension(400, 300);
}

public static void main(String s[]) {


JFrame frame = new JFrame("Data File Table");
DataFileTable panel;

panel = new DataFileTable("customers.dat");


frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setForeground(Color.black);
frame.setBackground(Color.lightGray);
frame.getContentPane().add(panel,"Center");

frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
frame.addWindowListener(new WindowCloser());
}
}

class WindowCloser extends WindowAdapter {


public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
}

The DataFileWatchdog, an Observable object, is simple. We use a Swing Timer to check every
second if a given file have changed. If the timestamp is different then the last one, then all
registered Observers are notified about it.

[DataFileWatchdog.java]

import javax.swing.Timer;
import java.awt.event.*;
import java.io.*;
import java.util.*;

public class DataFileWatchdog extends Observable


implements ActionListener {

14.47 Disable row selection in a JTable


Timer t = new Timer(1000,this); // check every second
long lastModified;
String file;

DataFileWatchdog (String s) {
file = s;
File f = new File(file);
lastModified = f.lastModified(); // original timestamp
t.start();
}

public void actionPerformed(ActionEvent e) {


File f = new File(file);
long actualLastModified = f.lastModified() ;
if (lastModified != actualLastModified) {
// the file have changed
lastModified = actualLastModified;
setChanged();
notifyObservers();
}
}
}

See also this related howto.

14.49 Hide a column in JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0216.html

To hide one column (or more) in a JTable, don't give a column name. To get back the hidden data,
you must use the TableModel.

[TableHideColumn.java]

import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;

import java.awt.event.*;
import java.awt.event.*;
import java.awt.*;

public class TableHideColumn


implements ListSelectionListener {
JTable tableView;
public TableHideColumn() {
JFrame frame = new JFrame("Table");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}});

// We specify only 2 column names, the last one is hidden


final String[] names = {"First Name", "Last Name" };
final Object[][] data = {
{"Mark", "Andrews", new Integer(1)},
{"Tom", "Ball", new Integer(2)},
{"Alan", "Chung", new Integer(3)},
};

14.49 Hide a column in JTable


TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() { return names.length; }
public int getRowCount() { return data.length;}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public String getColumnName(int column) {return names[column];}
public Class getColumnClass(int col) {
return getValueAt(0,col).getClass();
}
public void setValueAt(Object aValue, int row, int column) {
data[row][column] = aValue;
}
};

tableView = new JTable(dataModel);

ListSelectionModel listMod = tableView.getSelectionModel();


listMod.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
listMod.addListSelectionListener(this);

JScrollPane scrollpane = new JScrollPane(tableView);


scrollpane.setPreferredSize(new Dimension(300, 300));
frame.getContentPane().add(scrollpane);
frame.pack();
frame.setVisible(true);
}

public void valueChanged(ListSelectionEvent e) {


int maxRows;
int[] selRows;
Object value;

if (!e.getValueIsAdjusting()) {
selRows = tableView.getSelectedRows();

if (selRows.length > 0) {
for (int i= 0; i < 3 ; i++) {
// get Table data
TableModel tm = tableView.getModel();
value = tm.getValueAt(selRows[0],i);
System.out.print(value + " " );
}
System.out.println();
}
}
}

public static void main(String[] args) {


new TableHideColumn();
}
}

This technique is not the best one since a exception is generated when Swing tries to display an
"hidden column".

For a better way check out these links :

http://www.codeguru.com/java/articles/660.shtml
http://www.experts−exchange.com/Programming/Programming_Languages/Java/Q_20394392.html

14.49 Hide a column in JTable


14.50 Scroll a JTable to the last row
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0291.html

// in the your JTable


// jump to last row
rowCount = table.getRowCount () − 1;
showCell(rowcount, 0);

// jump to first row


showCell(0, 0);

public void showCell(int row, int column) {


Rectangle rect =
getCellRect(row, column, true);
scrollRectToVisible(rect);
clearSelection();
setRowSelectionInterval(row, row);
getModel().fireTableDataChanged(); // notify the model
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.51 Transfer a ResultSet to a JTable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0309.html

// TableModel definition
String[] tableColumnsName = {"col 1","col 2","col 3"};
DefaultTableModel aModel = (DefaultTableModel) aTable.getModel();
aModel.setColumnIdentifiers(tableColumnsName);

// the query
ResultSet rs =
statement.executeQuery("select col1,col2,col3 from mytable");

// Loop through the ResultSet and transfer in the Model


java.sql.ResultSetMetaData rsmd = rs.getMetaData();
int colNo = rsmd.getColumnCount();
while(rs.next()){
Object[] objects = new Object[colNo];
// tanks to umit ozkan for the bug fix!
for(int i=0;i<colNo;i++){
objects[i]=rs.getObject(i+1);
}
aModel.addRow(objects);
}
aTable.setModel(aModel);

14.50 Scroll a JTable to the last row


14.52 Have on a JScrollPane/JTable an horizontal JScrollbar
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0397.html

JScrollPane myScrollPane;
JTable myTable;

myTable = new Jtable(x,y);


myTable.setAutoResizeMode (JTable.AUTO_RESIZE_OFF);
myScrollPane = new JScrollPane(myTable);
myScrollPane.setHorizontalScrollBar(new JScrollBar());
myTable.setAutoResizeMode (JTable.AUTO_RESIZE_OFF);

14.53 Make a JList select an item on doubleclick or the ENTER


key
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0201.html

import javax.swing.*;
import java.awt.event.*;

public class ActionJList extends JList {


/*
** sends ACTION_PERFORMED event for double−click
** and ENTER key
*/
ActionListener al;

public ActionJList(String[] it){


super(it);

addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (me.getClickCount() == 2) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,
ob[0].toString()));
me.consume();
}
}
});

addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
if (al == null) return;
Object ob[] = getSelectedValues();
if (ob.length > 1) return;
if (ke.getKeyCode() == KeyEvent.VK_ENTER) {
System.out.println("Sending ACTION_PERFORMED to ActionListener");
al.actionPerformed(new ActionEvent(this,
ActionEvent.ACTION_PERFORMED,

14.52 Have on a JScrollPane/JTable an horizontal JScrollbar


ob[0].toString()));
ke.consume();
}
}
});
this.setSelectedIndex(0);
}

public void addActionListener(ActionListener al){


this.al = al;
}
}

To try it:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class TestActionJList {


public static void main(String args[]) {
JFrame jf = new JFrame();
jf.getContentPane().add(new PanelWithActionJList());
jf.pack();
jf.setVisible(true);
}

class PanelWithActionJList extends JPanel {


public PanelWithActionJList() {
setLayout(new GridLayout(1,1));

String[] items =
{ "item 0", "item 1", "item 2", "item 3" , "item 4",
"item 5", "item 6", "item 7", "item 8" , "item 9" };

final ActionJList ajl = new ActionJList(items);

ajl.setVisibleRowCount(5);
ajl.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
System.out.println("action in Panel " + ajl.getSelectedValue());
}
});

JScrollPane jsp = new JScrollPane();


jsp.getViewport().add(ajl);
add(jsp);
}
}

14.54 Make a JList like a scrolling text display


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0202.html

import javax.swing.*;

14.54 Make a JList like a scrolling text display


import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class JListExample extends JPanel {


static MyJList mj;
public static void main(String s[]) {
JListExample ex = new JListExample();
JFrame frame = new JFrame("JList Scrolling Display");
JButton button = new JButton("Insert");
ex.mj = new MyJList();
ex.mj.list.setModel (new DefaultListModel());

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(ex.mj);
frame.getContentPane().add(button);
button.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
DefaultListModel dlm =
(DefaultListModel)JListExample.mj.list.getModel();
dlm.addElement
((Object) new Long(System.currentTimeMillis()));
JListExample.mj.list.ensureIndexIsVisible
(JListExample.mj.list.getModel().getSize() − 1);
}
});

frame.setSize(300, 300);
frame.setVisible(true);
}
}

class MyJList extends JPanel {


JList list;

public MyJList() {
setLayout(new BorderLayout());
list = new JList();
add(new JScrollPane(list));
}

public Dimension getPreferredSize() {


return new Dimension(150, 250);
}
}

14.55 Have images in a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0203.html

This snippet uses these 2 images

import javax.swing.*;
import java.awt.*;
import java.util.*;

14.55 Have images in a JList


public class JListWithImages extends JList {

public JListWithImages() {
setCellRenderer(new CustomCellRenderer());
}

public static void main(String[] args) {


JFrame frame = new JFrame();
JPanel panel = new JPanel();
Vector vector = new Vector();
panel.setForeground(Color.black);
panel.setBackground(Color.white);

// first line
JPanel jp1 = new JPanel();
jp1.add(new JLabel(new ImageIcon("gumby.gif")));
jp1.add(new JLabel("A line for Gumby"));
jp1.add(new JLabel(new ImageIcon("gumby2.gif")));

// second line
JPanel jp2 = new JPanel();
jp2.add(new JLabel(new ImageIcon("gumby.gif")));
jp2.add(new JLabel("Another line for Gumby"));
jp2.add(new JLabel(new ImageIcon("gumby2.gif")));

vector.addElement(jp1);
vector.addElement(jp2);

JListWithImages jlwi = new JListWithImages();


jlwi.setListData(vector);

panel.add(jlwi);
frame.getContentPane().add(panel);
frame.setSize(300,300);
frame.setVisible(true);
}

class CustomCellRenderer implements ListCellRenderer {


public Component getListCellRendererComponent
(JList list, Object value, int index,
boolean isSelected,boolean cellHasFocus) {
Component component = (Component)value;
component.setBackground
(isSelected ? Color.black : Color.white);
component.setForeground
(isSelected ? Color.white : Color.black);
return component;
}
}
}

The above How−to use the default layout, so each line line in the JList are centered. The version
below is showing each line left justified instead.

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.util.*;

public class JListWithImages extends JList {

public JListWithImages() {

14.55 Have images in a JList


setCellRenderer(new CustomCellRenderer());
}

public static void main(String[] args) {


JFrame frame = new JFrame();
JPanel panel = new JPanel();
Vector vector = new Vector();
panel.setForeground(Color.black);
panel.setBackground(Color.white);

// first line
JPanel jp1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); // NEW
jp1.add(new JLabel(new ImageIcon("gumby.gif")));
jp1.add(new JLabel("A line for Gumby"));
jp1.add(new JLabel(new ImageIcon("gumby2.gif")));

// second line
JPanel jp2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); // NEW
jp2.add(new JLabel(new ImageIcon("gumby.gif")));
jp2.add(new JLabel("Another line for Gumby"));
jp2.add(new JLabel(new ImageIcon("gumby2.gif")));

vector.addElement(jp1);
vector.addElement(jp2);

JListWithImages jlwi = new JListWithImages();


jlwi.setListData(vector);
jlwi.setBorder(new LineBorder(Color.black));

panel.add(jlwi);
frame.getContentPane().add(panel);
frame.setSize(300,300);
frame.setVisible(true);
}

class CustomCellRenderer implements ListCellRenderer {


public Component getListCellRendererComponent
(JList list, Object value, int index,
boolean isSelected,boolean cellHasFocus) {
Component component = (Component)value;
component.setBackground
(isSelected ? Color.black : Color.white);
component.setForeground
(isSelected ? Color.white : Color.black);
return component;
}
}
}

14.56 Add a row and clear a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0217.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class ClearJList extends JPanel

14.56 Add a row and clear a JList


implements ActionListener{
JButton jb1, jb2;
JList list;
int i = 1;

public ClearJList(){
Vector data;
setLayout(new BorderLayout());
list = new JList();
list.setModel(new DefaultListModel());
add(new JScrollPane(list),"Center");
add(jb1 = new JButton("Add"), "East");
add(jb2 = new JButton("Clear"), "West");
jb1.addActionListener(this);
jb2.addActionListener(this);
}

public Dimension getPreferredSize(){


return new Dimension(50, 50);
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == jb1) {
// add
DefaultListModel dlm =
(DefaultListModel) list.getModel();
dlm.addElement
((Object) Integer.toString(i++));
}
else {
// clear
list.setModel(new DefaultListModel());
}
}
public static void main(String s[]) {
JFrame frame = new JFrame("Clear JList");
ClearJList panel = new ClearJList();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");

frame.setSize(200,200);
frame.setVisible(true);
}
}

14.57 Sort a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0218.html

import javax.swing.*;

import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.text.Collator;
// import java.util.Locale;

public class SortJList extends JPanel


implements ActionListener{

14.57 Sort a JList


JButton jb1, jb2;
JTextField tf;
JList list;
int i = 1;

public SortJList(){
Vector data;
setLayout(new BorderLayout());
list = new JList();
list.setModel(new DefaultListModel());
add(new JScrollPane(list),"Center");
add(jb1 = new JButton("Add"), "West");
add(jb2 = new JButton("Sort"), "East");
add(tf = new JTextField(), "North");
jb1.addActionListener(this);
jb2.addActionListener(this);
}

public Dimension getPreferredSize(){


return new Dimension(50, 50);
}

public void actionPerformed(ActionEvent ae) {


DefaultListModel dlm;
if (ae.getSource() == jb1) {
// add
dlm = (DefaultListModel)list.getModel();
dlm.addElement
((Object) tf.getText());
}
else {
// sort
dlm = (DefaultListModel) list.getModel();
int numItems = dlm.getSize();
String[] a = new String[numItems];
for (int i=0;i<numItems;i++){
a[i] = (String)dlm.getElementAt(i);
}
sortArray(Collator.getInstance(),a);
// Locale loc = Locale.FRENCH;
// sortArray(Collator.getInstance(loc), (String[])a);
for (int i=0;i<numItems;i++) {
dlm.setElementAt(a[i], i);
}
}
}

public static void sortArray(Collator collator, String[] strArray) {


String tmp;
if (strArray.length == 1) return;
for (int i = 0; i < strArray.length; i++) {
for (int j = i + 1; j < strArray.length; j++) {
if( collator.compare(strArray[i], strArray[j] ) > 0 ) {
tmp = strArray[i];
strArray[i] = strArray[j];
strArray[j] = tmp;
}
}
}
}

public static void main(String s[]) {


JFrame frame = new JFrame("Sort JList");

14.57 Sort a JList


SortJList panel = new SortJList();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");

frame.setSize(200,200);
frame.setVisible(true);
}
}

14.58 Double click on a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0219.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class DClickJList extends JPanel {


public DClickJList() {
JList list = new JList();;
Vector data = new Vector();;
data.addElement("line 1");
data.addElement("line 2");
data.addElement("line 3");
list.setListData(data);
list.setSelectedIndex(0);
list.addMouseListener(new ActionJList(list));
add(new JScrollPane(list));
}

public Dimension getPreferredSize() {


return new Dimension(100, 100);
}

public static void main(String s[]){


JFrame frame = new JFrame("DClickJList");
DClickJList panel = new DClickJList();

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

class ActionJList extends MouseAdapter{


protected JList list;

public ActionJList(JList l){


list = l;
}

public void mouseClicked(MouseEvent e){


if(e.getClickCount() == 2){
int index = list.locationToIndex(e.getPoint());
ListModel dlm = list.getModel();
Object item = dlm.getElementAt(index);;
list.ensureIndexIsVisible(index);

14.58 Double click on a JList


System.out.println("Double clicked on " + item);
}
}
}

14.59 Have a PopUp on a JList


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0393.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class PopUpJList extends JPanel


implements ActionListener{
JButton jb1, jb2;
JPopupMenu popupMenu;
JMenuItem jmi1, jmi2;
JList list;
int i = 1;

public PopUpJList(){
Vector data;
setLayout(new BorderLayout());
list = new JList();
list.setModel(new DefaultListModel());
add(new JScrollPane(list),"Center");
add(jb1 = new JButton("Add"), "East");
add(jb2 = new JButton("Clear"), "West");
jb1.addActionListener(this);
jb2.addActionListener(this);

popupMenu = new JPopupMenu();


popupMenu.add(jmi1= new JMenuItem("Add"));
popupMenu.add(new JPopupMenu.Separator());
popupMenu.add(jmi2 = new JMenuItem("Clear"));

list.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
// if right mouse button clicked (or me.isPopupTrigger())
if (SwingUtilities.isRightMouseButton(me)
&!list.isSelectionEmpty()
&list.locationToIndex(me.getPoint())
== list.getSelectedIndex()) {
popupMenu.show(list, me.getX(), me.getY());
}
}
}
);

jmi1.addActionListener(this);
jmi2.addActionListener(this);

public Dimension getPreferredSize(){


return new Dimension(50, 50);

14.59 Have a PopUp on a JList


}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == jb1 || ae.getSource() == jmi1) {
// add
DefaultListModel dlm =
(DefaultListModel) list.getModel();
dlm.addElement
((Object) Integer.toString(i++));
}
else {
// clear
list.setModel(new DefaultListModel());
}
}
public static void main(String s[]) {
JFrame frame = new JFrame("PopUp JList");
PopUpJList panel = new PopUpJList();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");

frame.setSize(200,200);
frame.setVisible(true);
}
}

14.60 Set the cursor position in a JTextArea


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0332.html

To the top

myJTextArea.setCaretPosition(0);

To the end

myJTextArea.setCaretPosition(myJTextArea.getDocument().getLength());

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.61 Make a JLabel selectable with the mouse


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0296.html

Simulate the "look and feel" of a JLabel with a JTextfield.

import javax.swing.*;
import java.awt.*;

public class SelectableJLabel extends JPanel {

14.60 Set the cursor position in a JTextArea


public SelectableJLabel() {
// a regular JLabel
add(new JLabel("You can't select me"));

// a look−alike JLabel
JTextField f = new JTextField("You can select me");
f.setEditable(false);
f.setBorder(null);
f.setForeground(UIManager.getColor("Label.foreground"));
f.setFont(UIManager.getFont("Label.font"));
add(f);
}

public Dimension getPreferredSize() {


return new Dimension(100, 100);
}

public static void main(String s[]){


JFrame frame = new JFrame("SelectableJLabel");
SelectableJLabel panel = new SelectableJLabel();

frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

14.62 Change JLabel background color


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0304.html

The JLabel background is transparent by default, so changing the background color doesn't seem to
do anything. Do something like this :

aJLabel.setOpaque(true);
aJLabel.setBackround(myColor)

14.63 Bold / Unbold a JLabel


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0349.html

Font f = label.getFont();

// bold
label.setFont(f.deriveFont(f.getStyle() ^ Font.BOLD));
// unbold
label.setFont(f.deriveFont(f.getStyle() | Font.BOLD));

14.62 Change JLabel background color


14.64 Multi−line JLabel
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0315.html

Swing 1.1.1 (or better) offers the possibility to use HTML tag to format the JLabel's text. But don't be
to fancy since the HTML support is minimal.

JLabel longLabel = new JLabel();


longLabel.setText("<html><body>This is a <p><b>" +
"<font size=\"+2\">a label on</font>" +
"</b><p>three lines.</body></html>");

14.65 Underline a string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0326.html

Since Swing (JDK1.2) implements simple HTML rendering for its components, it's possible to
display underlined string (on JLabel or JButton for example).

HTML tags must be in lowercase and simple.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class UnderlineInSwing extends JFrame {


public UnderlineInSwing() {

super("Underline In Swing");
setSize(400, 300);

getContentPane().setLayout(new FlowLayout());

String htmlText =
"<html><p><font color=\"#800080\" "+
"size=\"4\" face=\"Verdana\">HTML in JLabel</font></p>"+
"<font size=\"2\"><u>"+
"underline is possible</u><br><b> and bold too</b></font>"+
"";
JLabel lbl = new JLabel(htmlText);
getContentPane().add(lbl);

WindowListener wndCloser = new WindowAdapter(){


public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}

public static void main(String args[]){


new UnderlineInSwing();
}
}

14.64 Multi−line JLabel


14.66 Update a JLabel
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0392.html

myLabel.setText("Real's HowTo");
SwingUtilities.updateComponentTreeUI(myLabel);

14.67 Have Multi−line string in a JToolTip


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0337.html

We saw that since Swing (JDK1.2) implements simple HTML rendering for its components, it's
possible to display underlined string (on JLabel or JButton for example). The same feature is true
for JToolTip.

myComponent.setToolTipText
("<html><p>This ToolTip is</p><p>two lines</p></html>");

14.68 Change Tooltip color


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0365.html

UIManager.put("Tooltip.background", new ColorUIResource(...));

The default value is

javax.swing.plaf.ColorUIResource[R=204,G=204,B=255]

NOTE:Most Swing resources can be customize this way. Here a list of the resource names and their default values.

14.69 Change a JTooltip font


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0529.html

import javax.swing.*;
import javax.swing.plaf.*;
import java.awt.event.*;
import java.awt.*;

public class TooltipInSwing extends JFrame {


public TooltipInSwing() {
super("TooltipInSwing");
setSize(400, 300);
getContentPane().setLayout(new FlowLayout());

14.66 Update a JLabel


// globally
UIManager.put("ToolTip.font",
new FontUIResource("SansSerif", Font.BOLD, 18));
JButton b1 = new JButton("tooltip 1");
b1.setToolTipText("tool tip sansserif bold");

getContentPane().add(b1);

// only one
String html =
"<html><p><font color=\"#800080\" " +
"size=\"4\" face=\"Verdana\">tool tip verdana" +
"</font></p></html>";
JButton b2 = new JButton("tooltip 2");
b2.setToolTipText(html);

getContentPane().add(b2);

WindowListener wndCloser = new WindowAdapter(){


public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}

public static void main(String args[]){


new TooltipInSwing();
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

14.70 Keep a JTooltip visible


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0528.html

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class TooltipInSwing extends JFrame {


public TooltipInSwing() {
super("TooltipInSwing");
setSize(400, 300);
getContentPane().setLayout(new FlowLayout());

JButton b1 = new JButton("Simple tooltip 1");


b1.setToolTipText("simple tool tip without a dismiss delay");

// set a new dismiss delay to a really big value, default is 4 sec.


ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE);

getContentPane().add(b1);

14.70 Keep a JTooltip visible


WindowListener wndCloser = new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}

public static void main(String args[]){


new TooltipInSwing();
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

14.71 Display icon associated with an executable


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0439.html

First technique

import java.io.*;
import javax.swing.*;

public class IconExtract1 {


public static void main(String[] args) throws Exception {
String s = "c:/windows/regedit.exe";
File file = new File(s);

// Get metadata and create an icon


sun.awt.shell.ShellFolder sf =
sun.awt.shell.ShellFolder.getShellFolder(file);
Icon icon = new ImageIcon(sf.getIcon(true));
System.out.println("type = " + sf.getFolderType());

// show the icon


JLabel ficon = new JLabel(s, icon, SwingConstants.LEFT);
JFrame frame = new JFrame();
frame.getContentPane().add(ficon);
frame.pack();
frame.setVisible(true);
}
}

output :

Second technique

import java.io.*;

14.71 Display icon associated with an executable


import javax.swing.*;
import java.awt.*;
import javax.swing.filechooser.FileSystemView;

public class IconExtract2 {


public static void main(String[] args) throws Exception {
String s = "c:/windows/regedit.exe";
File file = new File(s);

// Get metadata and create an icon


Icon icon = FileSystemView.getFileSystemView().getSystemIcon(file);

// show the icon


JLabel ficon = new JLabel(s, icon, SwingConstants.LEFT);

JFrame frame = new JFrame();


frame.getContentPane().add(ficon);
frame.pack();
frame.setVisible(true);
}
}

output:

If you need more generic image, you use a JFileChooser and extract the image for a file or
directory.

import java.io.*;
import javax.swing.*;
import java.awt.*;
import javax.swing.filechooser.*;

public class IconExtract3 {


public static void main(String[] args) throws Exception {

String s = "c:/windows/regedit.exe";
JFileChooser chooser = new JFileChooser();

File file = new File(s);


Icon icon = chooser.getIcon(file);

// show the icon


JLabel ficon = new JLabel(s, icon, SwingConstants.LEFT);

JFrame frame = new JFrame();


frame.getContentPane().add(ficon);
frame.pack();
frame.setVisible(true);
}
}

output for a directory :

output for a file :

14.71 Display icon associated with an executable


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

14.72 Have items in JMenubar at rightmost position


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0486.html

javax.swing.Box.createGlue() will create a "greedy" component: when it is added to a container it


takes all remaining horizontal and vertical space. Adding such a glue component to the menubar will
cause remaining menus/components to 'flow' to the right.

import javax.swing.*;
import java.awt.event.*;

class RightJMenuBar {
public static void main(String args[]) {
new RightJMenuBar().doit();
}

public void doit() {


JFrame frame = new JFrame("Real's HowTo");
JMenuBar menuBar = new JMenuBar();

// Create a menu
JMenu menu = new JMenu("Menu Label");
JMenuItem item = new JMenuItem("item");
menu.add(item);

menuBar.add(menu);

// shift to the right


menuBar.add(Box.createGlue());

// this button will be shifted right on the menubar


Action actionQuit = new AbstractAction("Quit") {
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
};
menuBar.add(new JButton(actionQuit));

frame.setJMenuBar(menuBar);
frame.setSize(300,300);
frame.setVisible(true);

}
}

14.72 Have items in JMenubar at rightmost position


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

14.73 Have an JButton with an Image


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0548.html

import java.awt.*;
import java.net.*;
import javax.swing.*;

public class TestJButton extends JApplet


{
JButton b1, b2, b3;

public void init() {


setLayout(new FlowLayout());
try {
b1 = new JButton("Regular",
new ImageIcon
(new URL("http://www.rgagnon.com/images/gumby.gif")));
add(b1);
// text on the center
b2 = new JButton("Special",
new ImageIcon
(new URL("http://www.rgagnon.com/images/gumby.gif")));
b2.setHorizontalTextPosition(SwingConstants.CENTER);
add(b2);
// text on the top
b3 = new JButton("Special",
new ImageIcon
(new URL("http://www.rgagnon.com/images/gumby.gif")));
b3.setVerticalTextPosition(SwingConstants.TOP);
b3.setHorizontalTextPosition(SwingConstants.CENTER);
add(b3);

}
catch (Exception e) {
e.printStackTrace();
}
}
}

How it looks :

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

14.73 Have an JButton with an Image


14.73 Have an JButton with an Image
15 Thread
15.1 java−thread

15.2 Pipe the output of a thread to the input of another one


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0140.html

We use the PipedOutputStream/PipedInputStream duo. When these streams are connected


together what is written in the PipedOutputStream can be read in PipedInputStream. That
connection acts like a queue (FIFO).

Pipeline Thread

+−−−−−−−−−−+ +−−−−−−−−−−+
| thread A | −−− > | thread B |
+−−−−−−−−−−+ +−−−−−−−−−−+
(PRODUCE) (CONSUME)

[ProduceData.java]

import java.io.*;

public abstract class ProduceData implements Runnable {


OutputStream os;

public ProduceData(OutputStream os) {


this.os = os;
Thread t = new Thread(this);
t.start();
}

public abstract boolean dataProduction();

public void run() {


while(dataProduction()) ;
}
}

[ConsumeData.java]

import java.io.*;

public abstract class ConsumeData implements Runnable {


InputStream is;

public ConsumeData(InputStream is) {


this.is = is;
Thread t = new Thread(this);
t.start();
}

public abstract boolean dataConsumption();

15 Thread
public void run(){
while(dataConsumption());
}
}

Next we implement the methods to prepare/send the data.

[SendProduction.java]

import java.io.*;

public class SendProduction extends ProduceData {


OutputStream output;

SendProduction(OutputStream os) {
super(os);
this.output = os;
}

public boolean dataProduction() {


byte[] j = new byte[1];
boolean done = false;
java.util.Random r = new java.util.Random();
while(!done) {
try {
j[0] = (byte)(Math.abs(r.nextInt()) % 255);
System.out.print(".");
output.write(j);
}
catch (Exception e) {
e.printStackTrace();
return true;
}
}
return done;
}
}

We implement the method to receive and process the data.

[ReceiveProduction.java]

import java.io.*;

public class ReceiveProduction extends ConsumeData {


InputStream input;

ReceiveProduction(InputStream is) {
super(is);
this.input = is;
}

public boolean dataConsumption() {


int i = 0;
try {
for (;;) {
i = input.read();
System.out.println(" " + i);
}
}

15 Thread
catch (Exception e) {
e.printStackTrace();
}
return true;
}
}

[TestThread.java]

import java.io.*;

public class TestThread {


public static void main(String a[]){
try {
PipedOutputStream os = new PipedOutputStream();
PipedInputStream is = new PipedInputStream();
os.connect(is);
new SendProduction(os);
new ReceiveProduction(is);
}
catch (Exception e) {}
}
}

15.3 Pipe the output of a thread to the input of other threads


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0141.html

The idea is to make the READ operation ATOMIC. Once the READING is started for one thread, it
cannot be interrupted by another one.

Pipeline Thread

+−−−−−−−−−−+ +−−−−−−−−−−+
| thread A | −−−− > | thread B |
+−−−−−−−−−−+ | +−−−−−−−−−−+
(produce) | (consume)
|
|
| +−−−−−−−−−−+
+− > | thread C |
+−−−−−−−−−−+
(CONSUME)

The ProduceData.class and ConsumeData.class are the same as the previous JAVA How−to.

[AtomicInputStream.java]

import java.io.*;

public class AtomicInputStream extends PipedInputStream {


int atom = 0;

AtomicInputStream(int atom) {
super();
this.atom = atom;
}

15.3 Pipe the output of a thread to the input of other threads


public synchronized int atomicRead(byte[] x) {
try {
read(x, 0, atom);
}
catch (Exception e) {
e.printStackTrace();
return −1;
}
return atom;
}
}

[SendProduction.java]

import java.io.*;

public class SendProduction extends ProduceData {


OutputStream os;

SendProduction(OutputStream os) {
super(os);
this.os = os;
}

public boolean dataProduction() {


byte[] j = new byte[3];
boolean done = false;
j[0] = 0 ; j[1] = 1; j[2] = 2;

while(!done) {
try {
os.write(j, 0, 3);
}
catch (Exception e) {
e.printStackTrace();
return true;
}
}
return done;
}
}

[ReceiveProduction.java]

import java.io.*;

public class ReceiveProduction extends ConsumeData {


AtomicInputStream as;

ReceiveProduction(AtomicInputStream as) {
super(as);
this.as = as;
}

public boolean dataConsumption() {


byte [] i = new byte[3];
try {
for (;;) {
as.read(i);
System.out.println
(Thread.currentThread().getName()+": " +
i[0] + " " + i[1] + " " + i[2]);

15.3 Pipe the output of a thread to the input of other threads


}
}
catch (Exception e) {
e.printStackTrace();
}
return true;
}
}

[TestThread.java]

import java.io.*;

public class TestThread {


public static void main(String a[]){
try {
PipedOutputStream os = new PipedOutputStream();
AtomicInputStream as = new AtomicInputStream(3);
os.connect(as);
new SendProduction(os);
new ReceiveProduction(as);
new ReceiveProduction(as);
new ReceiveProduction(as);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

That's OK for the situation One Producer and Many consumers.


To support many producers, simply create a AtomicOutputStream class with a synchronized
atomicWrite method in it.

Using a PipedOutputStream is complicated, a simpler solution is to use Queue (especially with Java
5). A producer sends data to the Queue and the the consumers extract the data. See this HowTo.

15.4 Wait the for the completion of a thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0142.html

public class testThread implements Runnable {


int i;
testThread(int i) {
super();
this.i = i;
}

public void run() {


for (int j=0; j < i; j++) {
System.out.println
(Thread.currentThread().getName() + " " + j);
}
System.out.println
(Thread.currentThread().getName() + " FINISHED");
}

15.4 Wait the for the completion of a thread


public static void main(String a[]) {
try {
testThread tt1 = new testThread(50);
testThread tt2 = new testThread(75);
Thread t1 = new Thread(tt1,"Test thread 1");
Thread t2 = new Thread(tt2,"Test thread 2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Main FINISHED");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

15.5 Control a thread from outside


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0143.html

public class TT extends Thread {


static final int RUN = 0;
static final int SUSPEND = 1;
static final int STOP = 2;
private int state = RUN;

public synchronized void setState(int s) {


state = s;
if (s == RUN) notify();
}

private boolean boolean checkState() {


while (state == SUSPEND) {
try {
wait();
}
catch (Exception e) {}
}
if (state == STOP)
return false;
return true;
}

public void run() {


while true {
doSomething();
if (!checkState())
break;
}
}

15.5 Control a thread from outside


15.6 Create a Timer object
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0144.html

JDK 1.3 (or better) provides new classes called java.util.Timer and java.util.TimerTask.

import java.util.Timer;
import java.util.TimerTask;

public class ToDo {


Timer timer;

public ToDo ( int seconds ) {


timer = new Timer ( ) ;
timer.schedule ( new ToDoTask ( ) , seconds*1000 ) ;
}

class ToDoTask extends TimerTask {


public void run ( ) {
System.out.println ( "OK, It's time to do something!" ) ;
timer.cancel ( ) ; //Terminate the thread
}
}

public static void main ( String args [ ] ) {


System.out.println ( "Schedule something to do in 5 seconds." ) ;
new ToDo ( 5 ) ;
System.out.println ( "Waiting." ) ;
}
}

Swing also provide a Timer class. A Timer object will send an ActionEvent to the registered
ActionListener.

import javax.swing.Timer;
import java.awt.event.*;
import java.util.*;

public class TimerDemo implements ActionListener {


Timer t = new Timer(1000,this);

TimerDemo() {
t.start();
}

public static void main(String args[]) {


TimerDemo td = new TimerDemo();
// create a dummy frame to keep the JVM running
// (for demonstation purpose)
java.awt.Frame dummy = new java.awt.Frame();
dummy.setVisible(true);
}

public void actionPerformed(ActionEvent e) {


if (e.getSource() == t) {
System.out.println
("\007Being ticked " + Calendar.getInstance().getTime());

15.6 Create a Timer object


}
}
}

15.7 Pause the execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0145.html

public class Wait {


public static void oneSec() {
try {
Thread.currentThread().sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void manySec(long s) {
try {
Thread.currentThread().sleep(s * 1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public class TestWait {


public static void main(String args[]) {
System.out.println("Wait one second");
Wait.oneSec();
System.out.println("Done\nWait five seconds");
Wait.manySec(5);
System.out.println("Done");
}
}

15.8 Execute a method at a specified time interval


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0146.html

In the following example, we are using a special class, DelayedMethod, which extends the Thread
class. This Thread will receive a pointer to the "parent class" in its constructor. This pointer will be
used to call a know method at a specified interval.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;

public class AnnoyingPopUps extends Applet implements


ActionListener {
Button b1, b2;
DelayedMethod dm;

15.7 Pause the execution


int x = 0;

public void init() {


b1 = new Button("Start Annoying Popops");
b2 = new Button("Stop Annoying Popops");
add(b1); add(b2);
b1.addActionListener(this);b2.addActionListener(this);
dm = new DelayedMethod(this, 1000); // 1 second
dm.start();
}

public void actionPerformed(ActionEvent ae) {


if (ae.getSource() == b1) {
dm.oktorun = true;
}
else if(ae.getSource() == b2) {
dm.oktorun = false;
}s
}

public void displayPopup() {


SimplePopUp d = new SimplePopUp();
d.show();
d.setLocation(x , x);
x = x + 5;
}

class SimplePopUp extends Dialog {


SimplePopUp() {
super(new Frame(), "annoying popup");
this.addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
}
}
);
}
}

class DelayedMethod extends Thread {


AnnoyingPopUps myObj = null; // customize for your need
boolean oktorun = false;
int delay;

DelayedMethod(AnnoyingPopUps myObj) {
this.myObj = myObj;
this.delay = 2000;
}

DelayedMethod(AnnoyingPopUps myObj, int delay) {


this.myObj = myObj;
this.delay = delay;
}

public void run() {


while (true) {
try {
sleep(delay);
if (oktorun)
myObj.displayPopup(); // customize this too!
}
catch (InterruptedException ignored) {}

15.7 Pause the execution


}
}
}
}

Want to Try it?

NOTE: Check this How−to to achieve to same goal by using the Timer object.

15.9 Execute a process at regular interval


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0595.html

JDK1.3 introduces a way to execute a process at regular interval (java.util.Timer and


java.util.TimerTask).

JDK1.5 provides a mechanism to create a pool a scheduled task


(java.util.concurrent.ScheduledThreadPoolExecutor (javadoc)).

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class DemoScheduledTask {

public static void main(String args[]) {

// pool size == 5
ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(5);
SimpleTask01 st01 = new SimpleTask01();
// start right now and after every 5 sec.
stpe.scheduleAtFixedRate(st01, 0, 5, TimeUnit.SECONDS);

SimpleTask02 st02 = new SimpleTask02();


// start in 1 sec and after every 2 sec.
stpe.scheduleAtFixedRate(st02, 1, 2, TimeUnit.SECONDS);
}
}

class SimpleTask01 implements Runnable {


public void run() {
System.out.println("Real's HowTo");
}
}

class SimpleTask02 implements Runnable {


int current = 10;
public void run() {
if (current > 0) {
System.out.println(current−−);
if (current == 0) {
System.out.println("end.");
}
}
}
}

15.9 Execute a process at regular interval


15.10 Handle concurrent read/write
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0373.html

Take the following program

import java.util.*;

public class RW {
private static Vector data = new Vector();

public static void main(String[] args) throws Exception {


new Producer().start();
new Consumer().start();
}

static class Consumer extends Thread {


Consumer(){
super("Consumer");
}
public void run(){
for(;;){
try {
Thread.sleep(1);
}
catch (Exception e){
e.printStackTrace();
}
Iterator it = data.iterator();
while (it.hasNext()) it.next();
}
}
}

static class Producer extends Thread {


Producer(){
super("Producer");
}
public void run(){
for(;;){
try {
Thread.sleep(1);
}
catch (Exception e){
e.printStackTrace();
}
data.addElement(new Object());
if (data.size() > 1000) data.removeAllElements();
}
}
}
}

The following Exception is generated very quickly because the Producer is trying to modify the data
(a Vector) while the Consumer is using it.

java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)

15.10 Handle concurrent read/write


at RW$Consumer.run(RW.java:26)

The solution is to use the keyword synchronized to put a lock on the data while we are using it.

import java.util.*;

public class RW {
private static Vector data = new Vector();

public static void main(String[] args) throws Exception {


new Producer().start();
new Consumer().start();
}

static class Consumer extends Thread {


Consumer(){
super("Consumer");
}
public void run(){
for(;;){
try {
Thread.sleep(1);
}
catch (Exception e){
e.printStackTrace();
}
synchronized(data){
Iterator it = data.iterator();
while (it.hasNext()) it.next();
}
}
}
}

static class Producer extends Thread {


Producer(){
super("Producer");
}
public void run(){
for(;;){
try {
Thread.sleep(1);
}
catch (Exception e){
e.printStackTrace();
}
data.addElement(new Object());
if (data.size() > 1000) data.removeAllElements();
}
}
}
}

15.11 Communicate between threads using a Queue


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0555.html

15.11 Communicate between threads using a Queue


Using BlockingQueue class
A new class in Java 5 can be used to communicate data to many Consumer classes from a
Producer class.

The java.util.concurrent.BlockingQueue is designed to work in a multi−threaded world.

A Producer opens a file and puts the data into BlockingQueue.

mport java.io.*;
import java.util.concurrent.*;

public class PrepareProduction implements Runnable{


private final BlockingQueue<String> queue;

PrepareProduction(BlockingQueue<String> q) { queue = q; }

public void run() {


String thisLine;
System.out.println("Start PrepareProduction");
try {
FileInputStream fin = new FileInputStream("d:/input_data.dat");
BufferedReader input = new BufferedReader
(new InputStreamReader(fin));
while ((thisLine = input.readLine()) != null) {
queue.put(thisLine);
}
fin.close();
input.close();
// special marker for the consumer threads
// to mark the EOF
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
queue.put("*");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

A Consumer extract a value from the Queue and execute an operation. If there is no data in the
Queue, the BlockingQueue will wait. The end−of−data is marked by the presence of a special
marker (the "*" in this example).

import java.util.concurrent.BlockingQueue;

public class DoProduction implements Runnable {


private final BlockingQueue<String> queue;

DoProduction(BlockingQueue<String> q) { queue = q; }

public void run() {


try {
System.out.println
("Start " + Thread.currentThread().getName());

15.11 Communicate between threads using a Queue


String value = queue.take();
while (!value.equals("*")) {
//System.out.println
// (Thread.currentThread().getName()+": " + value );
/*
do something with value
*/
value = queue.take();
}
}
catch (Exception e) {
System.out.println
(Thread.currentThread().getName() + " " + e.getMessage());
}
}
}

A test class

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class Test {


public static void main(String[] args) throws Exception {

BlockingQueue<String> q =
new LinkedBlockingQueue<String>();

Thread p1 = new Thread(new PrepareProduction(q));


Thread c1 = new Thread(new DoProduction(q));
Thread c2 = new Thread(new DoProduction(q));
Thread c3 = new Thread(new DoProduction(q));
Thread c4 = new Thread(new DoProduction(q));
Thread c5 = new Thread(new DoProduction(q));
Thread c6 = new Thread(new DoProduction(q));
Thread c7 = new Thread(new DoProduction(q));
Thread c8 = new Thread(new DoProduction(q));
Thread c9 = new Thread(new DoProduction(q));

p1.start();
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
c6.start();
c7.start();
c8.start();
c9.start();

p1.join();
c1.join();
c2.join();
c3.join();
c4.join();
c5.join();
c6.join();
c7.join();
c8.join();
c9.join();

System.out.println("Done.");

15.11 Communicate between threads using a Queue


}
}

Using a LinkedList
If you need don't need all the benefits of BlockingQueue then a simple LinkedList can be more
appropriate, especially if you need to process large amount of data in a batch process. Since you
are in a multi−threaded world, it's safer to use the synchronized version of the LinkedList
implementation. Keep in mind that theses examples are minimal and need more error checking!

First the Producer

import java.io.*;
import java.util.*;

public class PrepareProduction implements Runnable{


private final List<String> queue;

PrepareProduction(List<String> q) { queue = q; }

public void run() {


String thisLine;
System.out.println("Start PrepareProduction");
try {
FileInputStream fin = new FileInputStream("d:/input_data.dat");
BufferedReader input = new BufferedReader
(new InputStreamReader(fin));
while ((thisLine = input.readLine()) != null) {
queue.add(thisLine);
}
fin.close();
input.close();
// special marker for EOF
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
queue.add("*");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

The Consumer

import java.util.*;
public class DoProduction implements Runnable {
private final List<String> queue;

DoProduction(List<String> q) { queue = q; }

public void run() {


try {
System.out.println("Start "
+ Thread.currentThread().getName());

15.11 Communicate between threads using a Queue


// you may need to wait for the first data available
// with a BlockingQueue it's done for you.
String value = queue.remove(0);
while (!value.equals("*")) {
System.out.println(Thread.currentThread().getName()
+": " + value );
/*
do something with value
*/
value = queue.remove(0);
}
}
catch (Exception e) {
System.out.println(Thread.currentThread().getName()
+ " " + e.getMessage());
}
}
}

The test

import java.util.*;

public class Test {


public static void main(String[] args) throws Exception {

List q = Collections.synchronizedList
(new LinkedList<String>());

Thread p1 = new Thread(new PrepareProduction(q));


Thread c1 = new Thread(new DoProduction(q));
Thread c2 = new Thread(new DoProduction(q));
Thread c3 = new Thread(new DoProduction(q));
Thread c4 = new Thread(new DoProduction(q));
Thread c5 = new Thread(new DoProduction(q));
Thread c6 = new Thread(new DoProduction(q));
Thread c7 = new Thread(new DoProduction(q));
Thread c8 = new Thread(new DoProduction(q));
Thread c9 = new Thread(new DoProduction(q));

p1.start();
c1.start();
c2.start();
c3.start();
c4.start();
c5.start();
c6.start();
c7.start();
c8.start();
c9.start();

p1.join();
c1.join();
c2.join();
c3.join();
c4.join();
c5.join();
c6.join();
c7.join();
c8.join();
c9.join();
System.out.println("Done.");
}

15.11 Communicate between threads using a Queue


}

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

15.11 Communicate between threads using a Queue


16 Varia
16.1 java−varia

16.2 Create a Taglet to document database access (Javadoc)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0473.html

Since JDK1.4, it is possible to create a taglet to be used with javadoc to customized the generated
documentation.

This example implements a new javadoc tag to document which tables a class is dealing with. If a
method interact with 2 tables, employee and address, then the javadoc tag

/**
*@table employee:firstname,lastname;address:city,country
* @return value
*/
public String newMethod() {
return "yo";
}

will be documented as

16.2.1 newMethod
public java.lang.String newMethod()

Returns:
value
Table(s):
firstname city
lastname country

The "table" taglet source

/*
* Table.java
*/

package com.rgagnon.taglet;
import com.sun.tools.doclets.Taglet;
import com.sun.javadoc.*;
import java.util.Map;
/**
* This is a taglet to document tables and fields used by a classes
* example : @table employee:lastname,firstname;address:city,country
*
* @author Réal Gagnon

16 Varia
*/
public class Table implements Taglet{

private static final String NAME = "table";


private static final String HEADER = "Table(s):";

/**
* Return the name of this custom tag.
*/
public String getName() {
return NAME;
}

/**
* Will return true since <code>@todo</code>
* can be used in field documentation.
* @return true since <code>@todo</code>
* can be used in field documentation and false
* otherwise.
*/
public boolean inField() {
return false;
}

/**
* Will return true since <code>@todo</code>
* can be used in constructor documentation.
* @return true since <code>@todo</code>
* can be used in constructor documentation and false
* otherwise.
*/
public boolean inConstructor() {
return true;
}

/**
* Will return true since <code>@todo</code>
* can be used in method documentation.
* @return true since <code>@todo</code>
* can be used in method documentation and false
* otherwise.
*/
public boolean inMethod() {
return true;
}

/**
* Will return true since <code>@todo</code>
* can be used in method documentation.
* @return true since <code>@todo</code>
* can be used in overview documentation and false
* otherwise.
*/
public boolean inOverview() {
return true;
}

/**
* Will return true since <code>@todo</code>
* can be used in package documentation.
* @return true since <code>@todo</code>
* can be used in package documentation and false
* otherwise.

16 Varia
*/
public boolean inPackage() {
return true;
}

/**
* Will return true since <code>@todo</code>
* can be used in type documentation (classes or interfaces).
* @return true since <code>@todo</code>
* can be used in type documentation and false
* otherwise.
*/
public boolean inType() {
return true;
}

/**
* Will return false since <code>@todo</code>
* is not an inline tag.
* @return false since <code>@todo</code>
* is not an inline tag.
*/

public boolean isInlineTag() {


return false;
}

/**
* Register this Taglet.
* @param tagletMap the map to register this tag to.
*/
public static void register(Map tagletMap) {
Table tag = new Table();
Taglet t = (Taglet) tagletMap.get(tag.getName());
if (t != null) {
tagletMap.remove(tag.getName());
}
tagletMap.put(tag.getName(), tag);
}

/**
* Given the <code>Tag</code> representation of this custom
* tag, return its string representation.
* @param tag the <code>Tag</code> representation of this custom tag.
*/
public String toString(Tag tag) {
String output = "";
String tables [] = tag.text().split(";");
int j = tables.length;
if (j > 0) {
output = "<DT><B>" + HEADER
+ "</B><DD><TABLE><TR>";
for (int i=0; i < j ; i++){
// deals with the current table and its fields
String current[] = tables[i].split(":");
output +=
"<TD><TABLE style=\"border−style:solid;"
+ " border−width:thin\">";
output +=
"<TH ALIGN=\"center\" STYLE=\"border−style:solid;"
+ " border−width:thin\">"
+ current[0] + "</TH>";
if (current.length > 1) {

16 Varia
String fields[] = current[1].split(",");
int k = fields.length;
for (int n=0; n < k ; n++) {
output += "<TR><TD ALIGN=\"center\">"
+ fields[n] + "</TD></TR>";
}
}
output += "</TABLE>";
}
output += "</TR></TABLE>";
}
return output;
}

/**
* Given an array of Tags representing this custom
* tag, return its string representation.
* @param tags the array of Tags representing of this custom tag.
*/
public String toString(Tag[] tags) {
if (tags.length == 0) {
return null;
}
String result = "";
for (int i = 0; i < tags.length; i++) {
result += toString(tags[i]);
}
return result ;
}
}

Compile your taglet. Use javac compiler version 1.4.0 (or later) in the Java 2 SDK. The required
class files are in the lib\tools.jar file in the SDK. Assuming the SDK is installed at C:\Program
Files\j2sdk1.4.1 :

javac −classpath "C:\Program Files\j2sdk1.4.1\lib\tools.jar"


com\rgagnon\taglet\Table.java

Run the javadoc tool using the −taglet and −tagletpath options. For example, if your taglet class file
is defined to be in package com.rgagnon.taglet and is stored in
C:\taglets\com\rgagnon\taglet\Table.class, then you should set tagletpath to C:\taglets. This
example calls javadoc on package com.package1, including Table taglet tags:

C:\dev\Work\java\taglet>javadoc −taglet com.rgagnon.taglet.Table


−tagletpath c:\dev\work\java\taglet com.package1

Download this taglet here.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.3 Generate the Javadoc "en français"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0437.html

16.3 Generate the Javadoc "en français"


The javadoc utility uses the regular Java mechanism to internationalize its output. The tools.jar in
the lib directory contains the resource bundle standard.properties used by Javadoc to generated the
labels. To add a new language, you need to create the appropriate resource bundle, in our case for
french, we need a file called standard_fr.properties.

The new file must be in the package com.sun.tools.doclets.standard.resources.

Extract from tools.jar, the standard.properties files (keep the directory structure). Copy it under the
name standard_fr.properties. Translate it (or you can download my "incomplete" version here).

[standard.properties (extract)]

doclet.Window_Split_Index={0}\: {1}−Index
doclet.Packages=Packages
doclet.SerialData=Serial Data\:
doclet.Since=Since\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Subinterfaces of {0} in {1}
doclet.Frame_Version=Frame version
doclet.Generated_Docs_Untitled=Generated Documentation (Untitled)

[standard_fr.properties (extract)]

doclet.Window_Split_Index={0}\: {1}−Index
doclet.Packages=Paquetages
doclet.SerialData=Donn\u00E9e s\u00E9rialis\u00E9e\:
doclet.Since=Depuis\:
doclet.Warn_inline_taglet=Inline tag {0} should only be used with a {1}.
doclet.ClassUse_Subinterface=Sous−interfaces de {0} dans {1}
doclet.Frame_Version=Version avec cadres
doclet.Generated_Docs_Untitled=Documentation g\u00E9n\u00E9r\u00E9e

Once everything translated, put your standard_fr.properties into the tools.jar making sure that the
file is located in the right package (along standard.properties in
com.sun.tools.doclets.standard.resources).

To generate in french, use the −locale switch on the command line

javadoc −locale fr ....

NOTE : Make sure the −locale switch is the first one.

Using Ant,

<javadoc
locale="fr"
sourcefiles="c:/client/Client.java"
destdir="javadoc/Client"
author="true"
version="true"
use="true"
private="true"
windowtitle="Client">
<doctitle><![CDATA[<h1>Client</h1>]]></doctitle>
<bottom><![CDATA[<i>Copyright &#169; 2003 Real's Howto.</i>]]></bottom>
</javadoc>

16.3 Generate the Javadoc "en français"


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.4 Document a package using Javadoc


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0502.html

Suppose I have a package called com.rgagnon with one HelloWorld class.

com
rgagnon
HelloWorld.java

In the directory containing HelloWorld.java, add a file called package.html.

This must be a complete HTML file (with HEAD and BODY). the first line of the body will be used a
the package description by javadoc.

<html><head></head><body>
this is <i>com.rgagnon</i> package description,
see <a href="http://www.rgagnon.com" target="_top">web site</a>
</body></html>

Now execute the javadoc utility located in [JDK]\bin directory from the root of the com.rgagnon
package.

\progra~1\Java\jdk1.5.0\bin\javadoc −d javadoc0 −linksource com.rgagnon

where −d javadoc0 is used to specify the output directory and


−linksource to create HTML version of the source file.

See the result.

Since JDK 1.5, to create a package comment file, you have a choice of two files to place your
comments:

• package−info.java − Can contain a package declaration, package annotations, package


comments and Javadoc tags. This file is new in JDK 5.0, and is preferred over
package.html.
• package.html − Can contain only package comments and Javadoc tags, no package
annotations.

See http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#packagecomment

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.4 Document a package using Javadoc


16.5 Use a Log file
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0501.html

Since 1.4, a logging functionnality is included with the JDK. It's the java.util.logging package.

import java.util.logging.*;
import java.io.*;

public class TestLog {

public static Logger logger;

static {
try {
boolean append = true;
FileHandler fh = new FileHandler("TestLog.log", append);
//fh.setFormatter(new XMLFormatter());
fh.setFormatter(new SimpleFormatter());
logger = Logger.getLogger("TestLog");
logger.addHandler(fh);
}
catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String args[]) {


logger.severe("my severe message");
logger.warning("my warning message");
logger.info("my info message");
}
}

and the result is

2005−02−28 21:19:28 TestLog main


GRAVE: my severe message
2005−02−28 21:19:28 TestLog main
ATTENTION: my warning message
2005−02−28 21:19:28 TestLog main
INFO: my info message

if the XMLFormatter is in use then the output is

<?xml version="1.0" encoding="windows−1252" standalone="no"?>


<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2005−02−28T21:21:09</date>
<millis>1109643669250</millis>
<sequence>0</sequence>
<logger>TestLog</logger>
<level>SEVERE</level>
<class>TestLog</class>
<method>main</method>
<thread>10</thread>
<message>my severe message</message>
</record>

16.5 Use a Log file


<record>
<date>2005−02−28T21:21:09</date>
<millis>1109643669328</millis>
<sequence>1</sequence>
<logger>TestLog</logger>
<level>WARNING</level>
<class>TestLog</class>
<method>main</method>
<thread>10</thread>
<message>my warning message</message>
</record>
<record>
<date>2005−02−28T21:21:09</date>
<millis>1109643669328</millis>
<sequence>2</sequence>
<logger>TestLog</logger>
<level>INFO</level>
<class>TestLog</class>
<method>main</method>
<thread>10</thread>
<message>my info message</message>
</record>
</log>

to customize the output, you can provide you own formatter

import java.util.logging.*;
import java.io.*;

public class TestLog {

public static Logger logger;

static {
try {
boolean append = true;
FileHandler fh = new FileHandler("TestLog.log", append);
fh.setFormatter(new Formatter() {
public String format(LogRecord rec) {
StringBuffer buf = new StringBuffer(1000);
buf.append(new java.util.Date());
buf.append(' ');
buf.append(rec.getLevel());
buf.append(' ');
buf.append(formatMessage(rec));
buf.append('\n');
return buf.toString();
}
});
logger = Logger.getLogger("TestLog");
logger.addHandler(fh);
}
catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String args[]) {


logger.severe("my severe message");
logger.warning("my warning message");
logger.info("my info message");
}
}

16.5 Use a Log file


then the output is

Mon Feb 28 21:30:54 EST 2005 SEVERE my severe message


Mon Feb 28 21:30:54 EST 2005 WARNING my warning message
Mon Feb 28 21:30:54 EST 2005 INFO my info message

To limit the log file size and set a rolling pattern

int limit = 1000000; // 1 Mb


int numLogFiles = 3;
FileHandler fh = new FileHandler("TestLog%g.log", limit, numLogFiles);

will give TestLog0.log, TestLog1.log and so on.

Default values are defined in JRE_HOME/lib/logging.properties. To use a different properties file,


you specify a filename with the java.util.logging.config.file system property.

java −Djava.util.logging.config.file=mylogging.props TestLog

To suppress the logging output to the console


Logger rootLogger = Logger.getLogger("");
Handler[] handlers = rootLogger.getHandlers();
if (handlers[0] instanceof ConsoleHandler) {
rootLogger.removeHandler(handlers[0]);
}

or modify the logging.properties file located in JRE_HOME/lib (default).

Look for the property handlers and remove the value java.util.logging.ConsoleHandler

You may want to take a look at another popular logging mechanism : Log4J.

See also this HowTo and this one

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.6 Trace the execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0301.html

This class generate a stackTrace and then parse it according to the parameters received.

[StackTrace.java]

public class StackTrace {


public static void displayStack() {
displayStack("", 0);
}
public static void displayStack(int deep) {
displayStack("", deep);

16.6 Trace the execution


}
public static void displayStack(String msg) {
displayStack(msg, 0);
}

public static void displayStack(String msg, int deep) {


//
// msg a message to appear in the Trace
// deep = 0 complete stack
// n from "n" levels
//
String output = "" ;
StringWriter sw = new StringWriter();
new Throwable("").printStackTrace(new PrintWriter(sw));
String stackTrace = sw.toString();

// to clean up the stacktrace


StringTokenizer st =
new StringTokenizer(stackTrace, "\n");

// get ride of the first line


String s=st.nextToken();

// get ride of line(s) for the Trace class


if (!msg.equals("")) output = msg + "\n" ;
s=st.nextToken();
s=st.nextToken();
if ( s.indexOf("StackTrace.displayStack") < 0 )
output += s + "\n";

// process the stack


if (deep == 0) {
while (st.hasMoreTokens()) {
output += st.nextToken() + "\n";
}
}
else {
while (deep > 1) {
if (st.hasMoreTokens()){
output += st.nextToken() + "\n";
deep−−;
System.out.println("**" + deep);
}
else
deep = 0;
}
}

System.out.println("Trace: " + output);


}
}

[SimpleTrace.java]

import java.io.*;
import java.util.*;

public class SimpleTrace {


public static void main(String args[]){
SimpleTrace s = new SimpleTrace();
s.doit();
}

16.6 Trace the execution


public void doit() {
MyClass s = new MyClass();
s.aMethod();
}
}

class MyClass {
MyClass() { }

public void aMethod() {


StackTrace.displayStack("Howto Trace only 1 level", 1);
StackTrace.displayStack("Howto Trace all levels");
}
}

And the output should be

Trace: Howto Trace only 1 level


at MyClass.aMethod(SimpleTrace.java:20)

Trace: Howto Trace all levels


at MyClass.aMethod(SimpleTrace.java:21)
at SimpleTrace.doit(SimpleTrace.java:12)
at SimpleTrace.main(SimpleTrace.java:7)

NOTES:
The stackTrace() formatting may be different with the JVM used, in this example, it's the Sun's JDK 1.2.1.

See also this HowTo.

You may want to look at this How−to to disable the Trace mechanism in the "release" version of
your classes to achieve the best performance.

Remember that line numbers are not available when a JIT is in function. To disable it, check this
How−to

16.7 Time the execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0132.html

public class ExecutionTimer {


private long start;
private long end;

public ExecutionTimer() {
reset();
}

public void start() {


start = System.currentTimeMillis();
}

public void end() {


end = System.currentTimeMillis();
}

public long duration(){

16.7 Time the execution


return (end−start);
}

public void reset() {


start = 0;
end = 0;
}

public static void main(String s[]) {


// simple example
ExecutionTimer t = new ExecutionTimer();
t.start();
for (int i=0; i < 80; i++){ System.out.print(".");}
t.end();
System.out.println("\n" + t.duration() + " ms");
}
}

See this HowTo to format a duration in ms into a string as "Days , Hours , minutes and seconds".

16.8 Log information efficiently (with Log4J)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0527.html

In production code, a good practice is to only log what is necessary in the context.

With Log4J, you can have different levels of message written into your log.

public class MyClass {

/**
* Logger log4j
*/
static Logger logger = Logger.getLogger(MyClass.class.getName());

...
logger.debug("I'm here");
logger.info(e.getMessage());
logger.warning("something wrong " + e.getMessage());
logger.error("omg " + e.getMessage());
...

While you can set the level in your code with something like

logger.setLevel(Level.WARN);

it's more flexible to do it from the Log4J properties file

; can be OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL


log4j.threshold=WARN

You put the properties file in the classpath and then from your code

URL url = ClassLoader.getSystemResource("log4j.props");


PropertyConfigurator.configure(url);

16.8 Log information efficiently (with Log4J)


Logging activities have a cost. Even if you set the level at DEBUG level, the logger.debug(...) is
interpreted. Consider this line :

logger.setLevel(Level.DEBUG);
logger.debug("something wrong with the value of " + myValue.toString());

the toString() method will be called and the result concatened to a String even if the DEBUG level is
disabled.

The best practice is to check if the level is enabled or not.

logger.setLevel(Level.DEBUG);
if (logger.isDebugEnabled()) {
logger.debug("something wrong with the value of " + myValue.toString());
}

This way you will not incur the cost of parameter construction if debugging is disabled for logger.

You can even remove the unwanted logging operation from the bytecode! See this HowTo.

Finally it's a good idea to design a robust toString() method for your class like this one :

public String toString(){


StringBuffer sb = new StringBuffer();
sb.append(getClass().getName())
sb.append(" myValue=[").append(this.myValue).append("]");
sb.append(" anotherValue=[").append(this.anotherProperty).append("]");
return sb.toString();
}

even if myValue is null, this toString() method will display "null" as the value and not throw a
NullPointerExeception.

See also this HowTo and this one

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

16.9 Call Windows API (Open source solution)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0497.html

NativeCall
NativeCall is a Java toolkit that lets you call operating system methods from whithin Java without
JNI code.

// copying a file to a new one using the Windows API


import com.eaio.nativecall.*;

NativeCall.init();
IntCall ic = new IntCall("CopyFileA");
ic.executeCall(new Object[] { "test.txt", "test_copy.txt", Boolean.FALSE });

16.9 Call Windows API (Open source solution)


ic.destroy();

See http://johannburkard.de/software/nativecall/

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.10 Call COM object (Open source solution)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0498.html

com4j
A Java library that allows Java applications to seemlessly interoperate with Microsoft Component
Object Model.

First generate Java type definitions from a COM type library. Here we are doing for the type library
for the Windows Scripting Host.

> java −jar tlbimp.jar −o wsh −p test.wsh %WINDIR%\system32\wshom.ocx

Then we are able to call WSH objects/methods.

public class Main {


public static void main(String[] args) {
IFileSystem3 fs = ClassFactory.createFileSystemObject();
for( String file : args )
System.out.println(fs.getFileVersion(file));
}
}

See https://com4j.dev.java.net/

See also this HowTo for an alternative package to access a COM package from Java.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.11 Run JAVA as a Windows service


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0151.html

A solution adapted to Java, is the Java Service Wrapper (


http://wrapper.tanukisoftware.org/doc/english/introduction.html ) (opensource). The setup is very
simple with one configuration file and your Java service can be notified when the service is stopped.

16.10 Call COM object (Open source solution)


If you log in and log out from a machine and a java service is running then the service may be
stopped. The fix is to use Java 1.3.1 or higher and start the process with the JVM switch −Xrs
(Reduce Signals Xtended−switch) to stop the Windows signal from killing the JVM.

For BEA JRockit, it's the −Xnohup

Also, it's possible to the utility SRVANY.EXE, included with the NT resource Kit.

http://www.techeez.com/windows_tips/service_under_nt.htm

SVRANY is used to run any EXE as a windows service. In our situation, SVRANY will run the
specified JAVA.EXE with our class a parameter. But this solution presents many problems. For
exemple, if you kill the SVRANY.EXE process (stop the service) then the JAVA.EXE is not killed,
you need to do it manually.

16.12 Create entity−relation diagram


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0584.html

Linguine Maps is an open−source Java library that conducts programmatic visualization of various
text files, generating from them easy−to−understand entity−relation diagrams.

http://www.softwaresecretweapons.com/jspwiki/linguinemaps

One interesting use is the Linguine Maps for Apache Ant. This utility produces easy to read
diagrams from Ant build files. The diagram shows all the task dependencies and colors default,
normal, and optional task in different colors. Tis a great way to document your Ant build file.

16.13 Java Remote desktop tool


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0583.html

Java Remote Desktop Protocol (RDP) Client is an Open Source Java RDP client for Windows
Terminal Server.

It runs on Java 1.1 and up, and works on Linux, Windows, Mac and other Java enabled systems.
http://www.elusiva.com/opensource/

Simply pass the machine name to connect to on the command line.

javaw −jar JavaRDP13−1.1.jar some.machine.local

For more option, from a command shell

javaw −jar JavaRDP14−1.1.jar

16.12 Create entity−relation diagram


There is a port for OpenVMS called JavaRDP for OpenVMS at
http://vmsfree.free.fr/freen/index.php?id=38

16.14 Create entity−relation diagram


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0584.html

Linguine Maps is an open−source Java library that conducts programmatic visualization of various
text files, generating from them easy−to−understand entity−relation diagrams.

http://www.softwaresecretweapons.com/jspwiki/linguinemaps

One interesting use is the Linguine Maps for Apache Ant. This utility produces easy to read
diagrams from Ant build files. The diagram shows all the task dependencies and colors default,
normal, and optional task in different colors. Tis a great way to document your Ant build file.

16.15 Launch a java program as a Windows EXE file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0588.html

WinRun4j is a java launcher for Windows. It provides an alternative to javaw.exe and provides the
following benefits:

• Use of INI file for specifying classpath, main class, vm args, program args.
• Custom executable name that appears in task manager.
• Built−in icon replacer for custom icon.

http://winrun4j.sourceforge.net/

16.16 Handle CSV file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0591.html

16.17 com.Ostermiller.util CSV Utils


CSVPrinter/CSVParser/ExcelCSVPrinter/ExcelCSVParser
http://ostermiller.org/utils/CSV.html

16.18 opencsv
A simple csv parser library for Java
http://opencsv.sourceforge.net/

16.14 Create entity−relation diagram


16.19 ServingXML
Framework for flat/XML data transformations. Supported transformations : flat−XML, XML−flat,
flat−flat, and XML−XML
http://servingxml.sourceforge.net/

16.20 Super CSV


This CSV reader/writer makes it easy to read/write objects/maps/string lists with automatic type
conversion and constraint checking.
http://supercsv.sourceforge.net/

16.21 csvreader
Library for reading and writing CSV and plain delimited text files. All kinds of CSV files can be
handled, text qualified, Excel formatted, etc.
http://www.csvreader.com/java_csv.php

16.22 CSVFile
A simple set of Java classes used to handle CSV
http://sourceforge.net/projects/csvfile

16.23 FlatPack
Flat file parser that handles CSV, fixed length and custom delimiters. Export a DataSet to a fixed
length or delimited format. FlatPack provides a sorting mechanism for your flat files.
http://flatpack.sourceforge.net/

16.24 Handle Excel files


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0516.html

There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about
OpenSource (and free) solutions.

16.25 JDBC−ODBC Excel driver


This solution lets you access your Excel worksheet with SQL SELECT statement. The required
ODBC driver is included in a regular Windows installation and the JDBC−ODBC bridge is used to
access the Excel DSN.

See this HowTo for an example.

16.19 ServingXML
16.26 JExcel
Java Excel API is a java API enabling developers to read, write, and modify Excel spreadsheets
dynamically. Any operating system which can run a Java virtual machine can both process and
deliver Excel spreadsheets. One nice thing about JExcelApi is that it has no dependencies on any
third party libraries.

Example : output an Excel file from a Servlet

import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

public class Sample extends HttpServlet {


public void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStream out = null;
try {
response.setContentType("application/vnd.ms−excel");
response.setHeader
("Content−Disposition", "attachment; filename=sampleName.xls");
WritableWorkbook w =
Workbook.createWorkbook(response.getOutputStream());
WritableSheet s = w.createSheet("Demo", 0);
s.addCell(new Label(0, 0, "Hello World"));
w.write();
w.close();
}
catch (Exception e){
throw new ServletException("Exception in Excel Sample Servlet", e);
}
finally{
if (out != null)
out.close();
}
}
}

See http://jexcelapi.sourceforge.net/

16.27 POI
The POI project consists of APIs for manipulating various file formats based upon Microsoft's OLE 2
Compound Document format using pure Java. POI is your Java Excel solution as well as your Java
Word solution.

HSSF is the POI Project's pure Java implementation of the Excel '97(−2002) file format and it
provides a way to read spreadsheets create, modify, read and write XLS spreadsheets.

16.26 JExcel
Since it's Jakarta project, POI has a dependencies with other JARs (commons,log4j,etc...).

Example : create an Excel file

HSSFWorkbook wb = new HSSFWorkbook();


HSSFSheet sheet = wb.createSheet("new sheet");

HSSFRow row = sheet.createRow((short)0);


row.createCell((short)0).setCellValue("HelloWorld");

FileOutputStream fileOut = new FileOutputStream("workbook.xls");


wb.write(fileOut);
fileOut.close();

The name was originally an acronym for "Poor Obfuscation Implementation" (ref: Wikipedia).

See http://jakarta.apache.org/poi/

16.28 JXLS
jXLS is a project that allows creation of extremely complex Excel reports just in several lines of
code. It is based on Jakarta POI.

With jXLS, all you need is to create XLS template file with all required formatting, formulas etc using
specific notation to indicate placement of data and then write a couple lines of code to invoke jXLS
engine passing XLS template and the exported data as parameters.

Example :
The XLS Template

Employees
Name Age Payment Bonus
${employee.name} ${employee.age} ${employee.payment} ${employee.bonus}
$[SUM(@employee.payment@)]

with the code

Collection staff = new HashSet();


staff.add(new Employee("Derek", 35, 3000, 0.30));
staff.add(new Employee("Elsa", 28, 1500, 0.15));
Map beans = new HashMap();
beans.put("employee", staff);
XLSTransformer transformer = new XLSTransformer();
transformer.transformXLS(templateFileName, beans, destFileName);

gives the result

Employees
Name Age Payment Bonus
Derek 35 3000 30,00%
Else 28 1500 15,00%
4500

See http://jxls.sourceforge.net/

16.28 JXLS
16.29 xlSQL
xlSQL is a JDBC Driver for Excel and CSV data sources. Documents can be read and written with
SQL as if they were tables in a database.

You can export XLS to XML or SQL INSERT statements. xlSQL includes its own "zero−admin"
mySQL database. The documentation is minimal at this time.

See http://xlsql.sourceforge.net/

16.30 JCOM
JCOM is a Java to COM bridge library. With JCOM you can call a COM object from Java as if it
were a Java object without having to deal with the internals of JNI. The documentation is minimal (in
Japanese!).

Example :

import jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
import jp.ne.so_net.ga2.no_ji.jcom.*;
import java.io.File;
import java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();
try {
System.out.println("EXCEL startup...");
// if already started, open new window
ExcelApplication excel = new ExcelApplication(rm);
excel.Visible(true);
// display any information
System.out.println("Version="+excel.Version());
System.out.println("UserName="+excel.UserName());
System.out.println("Caption="+excel.Caption());
System.out.println("Value="+excel.Value());

ExcelWorkbooks xlBooks = excel.Workbooks();


ExcelWorkbook xlBook = xlBooks.Add(); // create new book

// enumurate all files


System.out.println
("set infomation of files in current directory to cell ...");
ExcelWorksheets xlSheets = xlBook.Worksheets();
ExcelWorksheet xlSheet = xlSheets.Item(1);
ExcelRange xlRange = xlSheet.Cells();

xlRange.Item(1,1).Value("filename" );
xlRange.Item(2,1).Value("size" );
xlRange.Item(3,1).Value("last modified time");
xlRange.Item(4,1).Value("is directory");
xlRange.Item(5,1).Value("is file");
xlRange.Item(6,1).Value("can read");
xlRange.Item(7,1).Value("can write");

File path = new File("./");


String[] filenames = path.list();
for(int i=0; i<filenames.length; i++) {

16.29 xlSQL
File file = new File(filenames[i]);
System.out.println(file);
xlRange.Item(1,i+2).Value( file.getName() );
xlRange.Item(2,i+2).Value( (int)file.length() );
xlRange.Item(3,i+2).Value( new Date(file.lastModified()) );
xlRange.Item(4,i+2).Value( file.isDirectory()?"Yes":"No" );
xlRange.Item(5,i+2).Value( file.isFile()?"Yes":"No" );
xlRange.Item(6,i+2).Value( file.canRead()?"Yes":"No" );
xlRange.Item(7,i+2).Value( file.canWrite()?"Yes":"No" );
}
String expression = "=Sum(B2:B"+(filenames.length+1)+")";
System.out.println
("embed equation, calculate sum of filesize: "+expression);
xlRange.Item(1,filenames.length+2).Value("sum");
xlRange.Item(2,filenames.length+2).Formula(expression);
xlRange.Columns().AutoFit(); // fit columns

// comment out, if print out.


// output default printer.
// System.out.println("print out...");
// xlSheet.PrintOut();

// comment out, if book save to file.


// if no path, save to(My Documents)
// System.out.println
// ("save to file... (My Documents)\\testExcel.xls");
// xlBook.SaveAs("testExcel.xls");

xlBook.Close(false,null,false);
excel.Quit();

System.out.println("thank you .");


}
catch(Exception e) { e.printStackTrace(); }
finally { rm.release(); }
}
}

See http://sourceforge.net/projects/jcom

See also this HowTo for an alternative package to access a COM package from Java.

16.31 OpenXLS Java Spreadsheet SDK


OpenXLS claims that it has the best compatibility with complex Excel files and able to handle any
kind of Excel file out there without corrupting it. This open source effort is the result of over 6 years
of development into it.

See http://www.extentech.com/estore/product_detail.jsp?product_group_id=228

Example (extract 3 images from a workbook, create a new workbook with them) :

doit("testImages.xls","Sheet1");

...

void doit(String finpath, String sheetname){


System.out.println("Begin parsing: " + workingdir + finpath);
WorkBookHandle tbo = new WorkBookHandle(workingdir + finpath);

16.31 OpenXLS Java Spreadsheet SDK


try{
sheet = tbo.getWorkSheet(sheetname);
// read images from sheet 1 −− .gif, .png, .jpg
ImageHandle[] extracted = sheet.getImages();
// extract and output images
for(int t=0;t<extracted.length;t++) {
System.out.println("Successfully extracted: "
+ workingdir + "testImageOut_"
+ extracted[t].getName()+"."
+extracted[t].getType());
FileOutputStream outimg = new FileOutputStream
(workingdir + extracted[t].getName()+"."
+extracted[t].getType());
extracted[t].write(outimg);
outimg.flush();
outimg.close();
}

tbo = new WorkBookHandle();


sheet = tbo.getWorkSheet("Sheet1");
CellHandle a1 = sheet.add
("New workbook with 3 images: a gif, a jpg, and a png", "A1");

// get gif image input stream


FileInputStream fin = new FileInputStream
(workingdir + "testImages.gif");

// add to sheet
ImageHandle giffy = new ImageHandle(fin, sheet);

// set picture size and location in sheet


giffy.setBounds(100, 100, 400, 200);
giffy.setName("giffy");
sheet.insertImage(giffy);

// add to sheet
for(int x=0;x<100;x++) {
fin = new FileInputStream(workingdir + "testImages.png");
ImageHandle jpgy = new ImageHandle(fin, sheet);
jpgy.setName("heart" + x);
// set the random x/y coords of picture
int ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setX(100 + ix);
ix = Math.round((float)((x * (Math.random()*10))));
jpgy.setY(100 + ix);
sheet.insertImage(jpgy);
}
// get png image input stream
fin = new FileInputStream(workingdir + "testImages.jpg");
// add to sheet
ImageHandle pngy = new ImageHandle(fin, sheet);
// set just the x/y coords of picture
pngy.setX(10);
pngy.setY(200);
sheet.insertImage(pngy);
}
catch(Exception e){
System.err.println("testImages failed: " + e.toString());
}
testWrite(tbo, workingdir + "testImagesOut.xls");
WorkBookHandle newbook = new WorkBookHandle
(workingdir + "testImagesOut.xls",0);
System.out.println("Successfully read: " + newbook);

16.31 OpenXLS Java Spreadsheet SDK


}

public void testWrite(WorkBookHandle b, String fout){


try{
java.io.File f = new java.io.File(fout);
FileOutputStream fos = new FileOutputStream(f);
BufferedOutputStream bbout = new BufferedOutputStream(fos);
bbout.write(b.getBytes());
bbout.flush();
fos.close();
}
catch (java.io.IOException e){
System.err.println("IOException in Tester. "+e);
}
}

See also this HowTo for a way to create a simple XLS without any additional library.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

16.32 Use System time to generate unique ID


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0385.html

Since the granulaty of a PC can be as high as 55ms (down to 10ms), you can't use the System time
to generate a unique ID because of the risk of getting duplicated IDs. This can be solved by using
the following technique to make sure that the number returned is unique (in a single JVM).

public class UniqueID {


static long current= System.currentTimeMillis();
static public synchronized long get(){
return current++;
}
}

See also this HowTo

16.33 Get a unique identifier


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0518.html

java.rmi.dgc.VMID can generate an identifier. Each new VMID is unique for all Java virtual
machines under the following conditions:

• The conditions for uniqueness for objects of the class java.rmi.server.UID are satisfied
♦ An independently generated UID instance is unique over time with respect to the
host it is generated on as long as the host requires more than one millisecond to
reboot and its system clock is never set backward. A globally unique identifier can be

16.32 Use System time to generate unique ID


constructed by pairing a UID instance with a unique host identifier, such as an IP
address.
• An address can be obtained for this host that is unique and constant for the lifetime of this
object.

The format is :

[2 chars for each byte in 4 byte ip address]:


[8 char unique string]:
[16 char from time in hex]:
[8 char from count]

Code :

public class TestVMID {


public static void main(String arg[]) {
System.out.println(new java.rmi.dgc.VMID().toString());
System.out.println(new java.rmi.dgc.VMID().toString());
System.out.println(new java.rmi.dgc.VMID().toString());
}
}

Output :

d578271282b42fce:−2955b56e:107df3fbc96:−8000
d578271282b42fce:−2955b56e:107df3fbc96:−7fff
d578271282b42fce:−2955b56e:107df3fbc96:−7ffe

See also this HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.34 Get the hard disk serial number or Motherboard serial


number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0580.html

When you need to know hardware details, Java is not the best tool unless you call a JNI routine or
an external utility. The JNI solution is always the best because it is designed to interact closely with
Java but it may be more complex to develop. If your need is simple (no interaction) and the need to
be cross plateform is not present then calling an external utility is maybe "a good enough" choice.

In these 2 examples, we create the appropriate VBS script file on−the−fly and capture its output.
They are very Windows oriented since they rely on the "Windows Script Host" to execute the
generated scripts.

The vbscript queries a WMI class to get a specific hardware information. Here we are using the
Win32_BaseBoard but they are many others, see
http://msdn2.microsoft.com/en−us/library/aa389273.aspx for complete list.

16.34 Get the hard disk serial number or Motherboard serial number
16.35 Motherboard serial number
import java.io.File;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class MiscUtils {


private MiscUtils() { }

public static String getMotherboardSN() {


String result = "";
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs =
"Set objWMIService = GetObject(\"winmgmts:\\\\.\\root\\cimv2\")\n"
+ "Set colItems = objWMIService.ExecQuery _ \n"
+ " (\"Select * from Win32_BaseBoard\") \n"
+ "For Each objItem in colItems \n"
+ " Wscript.Echo objItem.SerialNumber \n"
+ " exit for ' do the first cpu only! \n"
+ "Next \n";

fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

public static void main(String[] args){


String cpuId = MiscUtils.getMotherboardSN();
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, cpuId, "Motherboard serial number",
javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

16.36 Hard disk serial number


import java.io.File;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class DiskUtils {


private DiskUtils() { }

16.35 Motherboard serial number


public static String getSerialNumber(String drive) {
String result = "";
try {
File file = File.createTempFile("realhowto",".vbs");
file.deleteOnExit();
FileWriter fw = new java.io.FileWriter(file);

String vbs = "Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\n"


+"Set colDrives = objFSO.Drives\n"
+"Set objDrive = colDrives.item(\"" + drive + "\")\n"
+"Wscript.Echo objDrive.SerialNumber"; // see note
fw.write(vbs);
fw.close();
Process p = Runtime.getRuntime().exec("cscript //NoLogo " + file.getPath());
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
result += line;
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result.trim();
}

public static void main(String[] args){


String sn = DiskUtils.getSerialNumber("C");
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, sn, "Serial Number of C:",
javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

NOTE : Other available properties : objDrive.AvailableSpace/DriveType/FileSystem/IsReady

16.37 Sort an array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0008.html

[ArraySorter.java] JDK1.1

public class ArraySorter {


/*
** Sort in the same array
*/
public static void sort(Object[] a, Comparer comparer) {
sort(a, null, 0, a.length − 1, true, comparer);
}

/*
** Sort a and b, using a as the reference
*/
public static void sort(Object[] a, Object[] b,

16.37 Sort an array


int from, int to, boolean ascending, Comparer comparer) {
// No sort
if (a == null || a.length < 2) return;

// sort using Quicksort


int i = from, j = to;
Object center = a[ (from + to) / 2 ];
do {
if (ascending) {
while( (i < to) &(comparer.compare( center, a[i]) > 0) )
i++;
while( (j > from) &(comparer.compare(center, a[j]) < 0) )
j−−;
}
else {
// Decending sort
while( (i < to) &(comparer.compare( center, a[i]) < 0) )
i++;
while( (j > from) &(comparer.compare(center, a[j]) > 0) )
j−−;
}
if (i < j) {
// Swap elements
Object temp = a[i]; a[i] = a[j]; a[j] = temp;
// Swap in b array if needed
if (b != null) {
temp = b[i]; b[i] = b[j]; b[j] = temp;
}
}
if (i <= j) { i++; j−−; }
} while(i <= j);
// Sort the rest
if (from < j) sort(a, b, from, j, ascending, comparer);
if (i < to) sort(a, b, i, to, ascending, comparer);
}

public static interface Comparer {


/**
* The interface implementation should compare the two
* objects and return an int using these rules:
* if (a > b) return > 0;
* if (a == b) return 0;
* if (a < b) return < 0;
*/
public int compare(Object a, Object b);
}
}

[testArraySorter.java]

public class testArraySorter {


public static final ASCIIComparer asciiComparer = new ASCIIComparer();
public static void main(String args[]) {
if (args.length == 0)
System.out.println("give me some args to sort");
else {
ArraySorter.sort(args, asciiComparer);
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}

16.37 Sort an array


public static class ASCIIComparer implements ArraySorter.Comparer {
public int compare(Object a, Object b) {
return ((String)a).compareTo((String)b);
}
}
}

JDK1.4 case−sensitive

String[] myArray = new String[] {"foo","bar","baz"};


java.util.Arrays.sort(myArray);

case−insensitive

String[] myArray = new String[] {"foo","Bar","baz"};


java.util.Arrays.sort(myArray, java.text.Collator.getInstance());

16.38 Sort a String array


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0343.html

Sort utilities are now part of latest JDK versions.

Case sensitive

java.util.Arrays.sort(myArray);

Case insensitive

java.util.Arrays.sort(myArray, String.CASE_INSENSITIVE_ORDER);

Sort with international characters.

Take the following example :

import java.util.*;
import java.io.*;

public class TestSort1 {

String [] words = { "Réal", "Real", "Raoul", "Rico" };

public static void main(String args[]) {


new TestSort1().doit();
}

public void doit() {


try {
// to be able output french character at the console
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
//
w.write("Before :\n");
for(int i=0; i < 4 ; i++) {

16.38 Sort a String array


w.write(words[i] + " ");
}

java.util.Arrays.sort(words);

w.write("\nAfter :\n");
for(int i=0; i < 4 ; i++) {
w.write(words[i] + " ");
}
w.write("\n");
w.flush();
w.close();
}
catch(Exception e){}
}
}

The output is :

Before :
Réal Real Raoul Rico
After :
Raoul Real Rico RéaAl

which is wrong since we expect to find "Réal" after "Real". To solve the problem , replace

java.util.arrays.sort(words);

by

java.util.arrays.sort(words, java.text.collator.getInstance(Locale.FRENCH));

and the output will be :

Before :
Réal Real Raoul Rico
After :
Raoul Real Réal Rico

Or you can do it the long way :

...
Locale loc = Locale.FRENCH;
sortArray(Collator.getInstance(loc), words);
...

public static void sortArray(Collator collator, String[] strArray) {


String tmp;
if (strArray.length == 1) return;
for (int i = 0; i < strArray.length; i++) {
for (int j = i + 1; j < strArray.length; j++) {
if( collator.compare(strArray[i], strArray[j] ) > 0 ) {
tmp = strArray[i];
strArray[i] = strArray[j];
strArray[j] = tmp;
}
}
}
}

16.38 Sort a String array


16.39 Do a selection sort
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0009.html

public class SelectionSort {


public static void sort(int array[]) {
sort(array, 0, array.length − 1);
}

public static void sort(int array[], int min, int max) {


if (min == max)
return;

// Find the smallest.


int index = select(array, min, max);

// Swap the smallest with the first.


int temp = array[min];
array[min] = array[index];
array[index] = temp;

// Sort the rest.


sort(array, min + 1, max);
}

private static int select(int array[], int min, int max) {


int index = min;
for (int i = min + 1; i <= max; ++i)
if (array[i] < array[index])
index = i;
return index;
}
}

16.40 Obtain from where a Class is loaded


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0300.html

public class LoadingFromWhere {


public static void main(String args[]){
LoadingFromWhere s = new LoadingFromWhere();
s.doit();
}

public void doit() {


System.out.println(this.getClass().getName() + " is loaded from " +
getClass().getProtectionDomain().getCodeSource().getLocation());

MyClass s = new MyClass();


}
}

class MyClass {
MyClass() {
System.out.println
(this.getClass().getName() + " is loaded from " +

16.39 Do a selection sort


this.getClass().getProtectionDomain().getCodeSource().getLocation());
}
}

The output

>java LoadingFromWhere
LoadingFromWhere is loaded from file:/C:/temp/
MyClass is loaded from file:/C:/temp/

Other technique (doesn't work with jar)

public class FromWhere {


public static void main(String args[]){
Class theClass = FromWhere.class;
java.net.URL u = theClass.getResource("");
System.out.println("This class (FromWhere) is located at : " + u);
}
}

The output

> java FromWhere


This class (FromWhere) is located at : file:/C:/temp/

See these related HowTo's : 1 2

16.41 Get the class name with or without the package


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0389.html

public class ClassUtils {


// returns the class (without the package if any)
public static String getClassName(Class c) {
String FQClassName = c.getName();
int firstChar;
firstChar = FQClassName.lastIndexOf ('.') + 1;
if ( firstChar > 0 ) {
FQClassName = FQClassName.substring ( firstChar );
}
return FQClassName;
}

// returns package and class name


public static String getFullClassName(Class c) {
return c.getName();
}

// returns the package without the classname, empty string if


// there is no package
public static String getPackageName(Class c) {
String fullyQualifiedName = c.getName();
int lastDot = fullyQualifiedName.lastIndexOf ('.');
if (lastDot==−1){ return ""; }
return fullyQualifiedName.substring (0, lastDot);
}

16.41 Get the class name with or without the package


public static void main(String[] args) {
System.out.println(ClassUtils.getClassName(java.awt.Frame.class));
System.out.println(ClassUtils.getFullClassName(java.awt.Frame.class));
System.out.println(ClassUtils.getPackageName(java.awt.Frame.class));
System.out.println("−−−−");
System.out.println(ClassUtils.getClassName(ClassUtils.class));
System.out.println(ClassUtils.getFullClassName(ClassUtils.class));
System.out.println(ClassUtils.getPackageName(ClassUtils.class));
System.out.println("−−−−");
java.util.Calendar cal = java.util.Calendar.getInstance();
System.out.println(ClassUtils.getClassName(cal.getClass()));
System.out.println(ClassUtils.getFullClassName(cal.getClass()));
System.out.println(ClassUtils.getPackageName(cal.getClass()));
}
}

The output

Frame
java.awt.Frame
java.awt
−−−−
ClassUtils
ClassUtils

−−−−
GregorianCalendar
java.util.GregorianCalendar
java.util

Thanks to L. Janovszki for the idea

Alternate way to get only the package name (null if there is no package) :

Class cls = java.lang.String.class;


Package pkg = cls.getPackage();
String name = pkg.getName(); // java.lang

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.42 Convert a .class to .java file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0330.html

There are several java "decompilers" , check out JAD (JAva Decompiler).

A list of what is available can be found at here.

16.42 Convert a .class to .java file


16.43 See the generated bytecode
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0495.html

Use the javap included in the JDK bin directory. javap is class disassembler, the result is similar to
the assembly code but for the JVM.

Consider the following class

class Test1 {
public static void main(String args[]) {
new Integer(1);
new Integer(2);
new Integer(3);

}
}

Compile the source code and then disassemble the bytecode with

javap −c Test1
// to redirect the output to a file
javap −c Test1 >test1.out

The Result is

Compiled from "Test1.java"


class Test1 extends java.lang.Object{
Test1();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return

public static void main(java.lang.String[]);


Code:
0: new #2; //class java/lang/Integer
3: dup
4: iconst_1
5: invokespecial #3; //Method java/lang/Integer."":(I)V
8: pop
9: new #2; //class java/lang/Integer
12: dup
13: iconst_2
14: invokespecial #3; //Method java/lang/Integer."":(I)V
17: pop
18: new #2; //class java/lang/Integer
21: dup
22: iconst_3
23: invokespecial #3; //Method java/lang/Integer."":(I)V
26: pop
27: return
}

and compile the following class and dissassemble the Test2 class.

class Test2 {
public static void main(String args[]) {

16.43 See the generated bytecode


int i = 1;
new Integer(i++);
new Integer(i++);
new Integer(i++);
}
}

Compiled from "Test2.java"


class Test2 extends java.lang.Object{
Test2();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return

public static void main(java.lang.String[]);


Code:
0: iconst_1
1: istore_1
2: new #2; //class java/lang/Integer
5: dup
6: iload_1
7: iinc 1, 1
10: invokespecial #3; //Method java/lang/Integer."":(I)V
13: pop
14: new #2; //class java/lang/Integer
17: dup
18: iload_1
19: iinc 1, 1
22: invokespecial #3; //Method java/lang/Integer."":(I)V
25: pop
26: new #2; //class java/lang/Integer
29: dup
30: iload_1
31: iinc 1, 1
34: invokespecial #3; //Method java/lang/Integer."":(I)V
37: pop
38: return
}

You can see the "cost" of doing the incrementation of i.

Now with the following source and the disassembled listing

class Test3 {
public static void main(String args[]) {
int i = 1;
new Integer(i++);
new Integer(i);
i = i + 1;
new Integer(i);
}
}

Compiled from "Test3.java"


class Test3 extends java.lang.Object{
Test3();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."":()V
4: return

16.43 See the generated bytecode


public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: new #2; //class java/lang/Integer
5: dup
6: iload_1
7: iinc 1, 1
10: invokespecial #3; //Method java/lang/Integer."":(I)V
13: pop
14: new #2; //class java/lang/Integer
17: dup
18: iload_1
19: invokespecial #3; //Method java/lang/Integer."":(I)V
22: pop
23: iload_1
24: iconst_1
25: iadd
26: istore_1
27: new #2; //class java/lang/Integer
30: dup
31: iload_1
32: invokespecial #3; //Method java/lang/Integer."":(I)V
35: pop
36: return
}

"i=i+1" takes 2 op−codes more than the equivalent "i++".

Note this is very low−level optimization, the gain in performance is not very significative, the class is
little bit smaller.

Remember Premature optimization is the root of all evil

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.44 Self replicating programs


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0344.html

Self replicating programs (also known as Quine) is computer program which prints its own listing!

Try these and try to explain the output!

First example

class S{public static void main(String[]a){char c=34;String s=


"class S{public static void main(String[]a){char c=34;String s=;"+
"System.out.println(s.substring(0,62)+c+s+c+s.substring(62));}}";
System.out.println(s.substring(0,62)+c+s+c+s.substring(62));}}

Second example

16.44 Self replicating programs


class a{public static void main(String x[]){String []s=
{"class a{2}public static void main(String x[]){2}String"+
"[]s={2}{1}{0}{1};new String(new char[]{2}34}),new String"+
"(new char[]{2}123});System.out.println(java.text.MessageFormat"+
".format(s[0],s));}}",new String(new char[]{34}),
new String(new char[]{123})};
System.out.println(java.text.MessageFormat.format(s[0],s));}}

See also this HowTo

16.45 A curiosity (strange Java code)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0356.html

A collection of weird Java code!

Can you spot why the following program is compiling ok ?


public class Curiosity {
public static void main (String[]args){
System.out.println ("A curiosity");
http: //www.rgagnon.com/howto.html
System.out.println ("compile Ok!");
}
}

The URL in the middle does not generate any compiler warning because http: is considered as a
label and the //www.rgagnon... is seen as a comment.

The next one is strange. From the main(), we create a Foo instance, then we call getFoo() which
returns a null and from "null" , we can access the value of fubar!
public class Foo {
static int fubar = 42;

Foo getFoo() {
return null;
}

public static void main(String args[]) {


Foo foo = new Foo();
System.out.println(foo.getFoo().fubar);
}
}
// output : 42

(from Usenet)

> I am new to java, and I really havent had time to do much work in it.
> However, I have a small project that is due next week for my class. Can
> anyone help me by providing some code? It should do the following;
>
> The program is simple. It should allow a user to input a string of digits,
> and then output the sum of those digits.
>
> For example; the user inputs 3563
> the program would then output 17 (3+5+6+3)

16.45 A curiosity (strange Java code)


and one the answer (from E. Sosman) was

public class Homework{public static void main (String[] OoO) {for (int
oOo=0;oOo<OoO.length;++oOo) main (OoO [oOo]);} public static void main
(String oOo){String Oo0="9876543210"; long o0o=oOo.length()*Oo0.length
();for(int OoO=oOo.length();−−OoO>=0;) {int O0O=Oo0.indexOf(oOo.charAt
(OoO));o0o−=O0O<0?012:++O0O;} main(oOo,o0o);} public static void main(
String Oo0,long oOo){System.out.print("Sum of digits in ");for(int O0O
=0;O0O<Oo0.length();++O0O)System.out.print(Oo0.charAt(O0O));System.out
.print(" = ");System.out.println(oOo);}}

Signature programs are short programs that people have been using as part of their signature in
Usenet message or email. They are small programs, that are often rather cryptic because they have
to save space as much as possible.

Here collection of classic signature programs, my own signature when I was a the Universite de
Montreal it's there!

A signature program in Java is not an easy task because Java is lot more verbose than C. Here an
attempt, try it to see the output!

class Howto{public static void main(String[] args){\u0066or(int


\u0020$:"vÌÈÊ\"¤¾Àʲ¬Æ\"v¤Î¤\"²ÀÐÊÀ\"".to\u0043h\u0061rArray()
)System./*goto/*$/%\u0126//^\u002A\u002Fout.print((char)(($>>+
(~'"''/'.')/\u002Array.const(~1)\*\u002F)));}}

See also this HowTo

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

16.46 Classic bugs


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0361.html

Here some common mistakes :

1:

int x = 0;

for( x=0; x<10; x++ );{


System.out.println("Print only once, why not 10 times ?");
}

2:

int i = 0;

if (i = 0){
System.out.println("Won't print, why ?");
}

16.46 Classic bugs


3:

public class WontCompile {


public static void main(String[] args) {
getInt(09);
}

private static void getInt(int i) {


System.out.println(i);
}
}

4:

// this don't do what it is supposed to do


void setIsDirtyData(boolean isdirtyData) {this.isDirtyData = isDirtyData;}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.47 Number of the beast!


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0477.html

public class Gates {


static String beast = "BillGates";

public static void main(String args[]) {


char [] temp = beast.toUpperCase().toCharArray();
int j = temp.length;
int i = 0;
int k = 0;
while (i < j) {
k += temp[i++];
System.out.println(temp[i−1]);
}
// Since it's really "Bill Gates III"
System.out.println(k + 1 + 1 + 1);
// output : 666 :−)
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.48 Convert wildcard to a regex expression


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0515.html

16.47 Number of the beast!


import java.util.regex.Pattern;

public class WildcardRegex {


public WildcardRegex() { }
public static void main(String[] args) {
String test = "123ABC";
System.out.println(test);
System.out.println(Pattern.matches(wildcardToRegex("1*"), test));
System.out.println(Pattern.matches(wildcardToRegex("?2*"), test));
System.out.println(Pattern.matches(wildcardToRegex("??2*"), test));
System.out.println(Pattern.matches(wildcardToRegex("*A*"), test));
System.out.println(Pattern.matches(wildcardToRegex("*Z*"), test));
System.out.println(Pattern.matches(wildcardToRegex("123*"), test));
System.out.println(Pattern.matches(wildcardToRegex("123"), test));
System.out.println(Pattern.matches(wildcardToRegex("*ABC"), test));
System.out.println(Pattern.matches(wildcardToRegex("*abc"), test));
System.out.println(Pattern.matches(wildcardToRegex("ABC*"), test));
/*
output :
123ABC
true
true
false
true
false
true
false
true
false
false
*/

public static String wildcardToRegex(String wildcard){


StringBuffer s = new StringBuffer(wildcard.length());
s.append('^');
for (int i = 0, is = wildcard.length(); i < is; i++) {
char c = wildcard.charAt(i);
switch(c) {
case '*':
s.append(".*");
break;
case '?':
s.append(".");
break;
// escape special regexp−characters
case '(': case ')': case '[': case ']': case '$':
case '^': case '.': case '{': case '}': case '|':
case '\\':
s.append("\\");
s.append(c);
break;
default:
s.append(c);
break;
}
}
s.append('$');
return(s.toString());
}
}

16.47 Number of the beast!


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.49 Count distinct elements in a Vector


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0377.html

Submitted by T GUIRADO

/**
** This method counts distinct elements from a given position in vector
** containing series of element.
** Arguments : source = vector containing the vectors of elements
** position = which element to search, first position = 0
** count = serie length
**
** ex :
** source = A,B,C D,E,F D,F,G
** length is 3
** from position 0 in each series we have A,D,D
** this method returns 2 because there are 2 distinct elements (A and D)
** from position 2 in each series we have C,F,G
** this method returns 2 because there are 3 distinct elements (C,FandG)
**/
protected synchronized int countDistinctElements
(Vector source,int position,int count){
Vector v = null;
for (int i = 0 ; i < source.size() ; i++) {
boolean isFound = false;
if ( i % count == position ) {
if ( null != v ) {
for (int j = 0 ; j < v.size() ; j++) {
if ( source.elementAt(i).equals(v.elementAt(j) ) ) {
isFound = true;
j = v.size();
}
}
}
if ( !isFound ) {
if ( null == v ) v = new Vector(1, 1);
v.addElement( (String)source.elementAt(i) );
}
i += count − position;
}
}
try { return v.size(); } catch ( Exception e ) {return 0;}
}

Submitted by bdobby2000

protected static int countDistinctElements


( Vector source, int position, int count )
throws IllegalArgumentException , IndexOutOfBoundsException {
List list = source.subList(position, position+count);
Set set = new HashSet();
set.addAll(list);

16.49 Count distinct elements in a Vector


return set.size();
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.50 Justify a string with wordwrap


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0013.html

/*
justify a string,
here only left justification is implemented
*/
public class FormatLine {
public static String justifyLeft( int width,String st) {
StringBuffer buf = new StringBuffer(st);
int lastspace = −1;
int linestart = 0;
int i = 0;

while (i < buf.length()) {


if ( buf.charAt(i) == ' ' ) lastspace = i;
if ( buf.charAt(i) == '\n' ) {
lastspace = −1;
linestart = i+1;
}
if (i > linestart + width − 1 ) {
if (lastspace != −1) {
buf.setCharAt(lastspace,'\n');
linestart = lastspace+1;
lastspace = −1;
}
else {
buf.insert(i,'\n');
linestart = i+1;
}
}
i++;
}
return buf.toString();
}

public static void main(String arg[]){


String formatted_string;
String original_string=
"01234567890123456789 01234567890 0123 4565789 ";

formatted_string = FormatLine.justifyLeft(25,original_string);

System.out.println("−−−−−−−−−");
System.out.println(original_string);
System.out.println("−−−−−−−−−");
System.out.println(formatted_string);
/*
output :
−−−−−−−−−

16.50 Justify a string with wordwrap


01234567890123456789 01234567890 0123 4565789
−−−−−−−−−
01234567890123456789
01234567890 0123
4565789
*/
}
}

16.51 Validate a Social Security Number (canadian)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0033.html

import java.util.*;
import java.io.*;

public class SSNUtils {


/**
* Validate a SSN number nnn nnn nnn
*/
public static boolean validSSN(String ssn) {
if (isNumber(ssn)) {
try {
int checksum = 0;
int j = ssn.length();
int [] digit = new int[j];
for (int i=0; i < ssn.length(); i++)
digit[i] = Integer.valueOf("" + ssn.charAt(i)).intValue();
// Add odd digits except the last one
int total_odd = 0;
for (int i=0; i < digit.length−1; i+=2)
checksum += digit[i];
// Multiply by 2 even digits,
// if result > 9 then div and mod by 10,
// add the results to the checksum
// else
// add result to the checksum
int k = 0;
for (int i=0; i < digit.length; i+= 2) {
if (i < digit.length−1) {
k = digit[i+1] * 2;
if (k>9) k = (k−10) + 1;
// total_even += k;
checksum += k;
}
}

// perform a modulo 10 on the total_odd_even


// then add the last digit
int mod = checksum % 10;
checksum = digit[digit.length−1] + mod;

// if the checksum is divisible by 10 then it's valid


return ((checksum % 10) == 0);
}
catch (Exception e) {
e.printStackTrace();
return false;
}

16.51 Validate a Social Security Number (canadian)


}
else {
return false;
}
}

/**
* Check if number is valid
*/
public static boolean isNumber(String n) {
try {
double d = Double.valueOf(n).doubleValue();
return true;
}
catch (NumberFormatException e) {
e.printStackTrace();
return false;
}
}

/*
** For testing purpose
**
** java SSNUtils or java SSNUtils
**
*/
public static void main(String args[]) throws Exception {
String aSSN = "";

if (args.length > 0)
aSSN = args[0];
else {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("SSN number : ");
aSSN = input.readLine();
}
System.out.println
("The SSN " + aSSN + " is " +(validSSN(aSSN)?" good.":" bad."));
}
}

16.52 Validate a Credit Card Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0034.html

import java.util.*;
import java.io.*;

public class CCUtils {


public static final int INVALID = −1;
public static final int VISA = 0;
public static final int MASTERCARD = 1;
public static final int AMERICAN_EXPRESS = 2;
public static final int EN_ROUTE = 3;
public static final int DINERS_CLUB = 4;

private static final String [] cardNames =


{ "Visa" ,

16.52 Validate a Credit Card Number


"Mastercard",
"American Express",
"En Route",
"Diner's CLub/Carte Blanche",
};

/**
* Valid a Credit Card number
*/
public static boolean validCC(String number)
throws Exception {
int CardID;
if ( (CardID = getCardID(number)) != −1)
return validCCNumber(number);
return false;
}

/**
* Get the Card type
* returns the credit card type
* INVALID = −1;
* VISA = 0;
* MASTERCARD = 1;
* AMERICAN_EXPRESS = 2;
* EN_ROUTE = 3;
* DINERS_CLUB = 4;
*/
public static int getCardID(String number) {
int valid = INVALID;

String digit1 = number.substring(0,1);


String digit2 = number.substring(0,2);
String digit3 = number.substring(0,3);
String digit4 = number.substring(0,4);

if (isNumber(number)) {
/* −−−−
** VISA prefix=4
** −−−− length=13 or 16 (can be 15 too!?! maybe)
*/
if (digit1.equals("4")) {
if (number.length() == 13 || number.length() == 16)
valid = VISA;
}
/* −−−−−−−−−−
** MASTERCARD prefix= 51 ... 55
** −−−−−−−−−− length= 16
*/
else if (digit2.compareTo("51")>=0 &digit2.compareTo("55")<=0) {
if (number.length() == 16)
valid = MASTERCARD;
}
/* −−−−
** AMEX prefix=34 or 37
** −−−− length=15
*/
else if (digit2.equals("34") || digit2.equals("37")) {
if (number.length() == 15)
valid = AMERICAN_EXPRESS;
}
/* −−−−−
** ENROU prefix=2014 or 2149
** −−−−− length=15

16.52 Validate a Credit Card Number


*/
else if (digit4.equals("2014") || digit4.equals("2149")) {
if (number.length() == 15)
valid = EN_ROUTE;
}
/* −−−−−
** DCLUB prefix=300 ... 305 or 36 or 38
** −−−−− length=14
*/
else if (digit2.equals("36") || digit2.equals("38") ||
(digit3.compareTo("300")>=0 &digit3.compareTo("305")<=0)) {
if (number.length() == 14)
valid = DINERS_CLUB;
}
}
return valid;

/* −−−−
** DISCOVER card prefix = 60
** −−−−−−−− lenght = 16
** left as an exercise ...
*/

public static boolean isNumber(String n) {


try {
double d = Double.valueOf(n).doubleValue();
return true;
}
catch (NumberFormatException e) {
e.printStackTrace();
return false;
}
}

public static String getCardName(int id) {


return (id > −1 &id < cardNames.length ? cardNames[id] : "");
}

public static boolean validCCNumber(String n) {


try {
/*
** known as the LUHN Formula (mod10)
*/
int j = n.length();

String [] s1 = new String[j];


for (int i=0; i < n.length(); i++) s1[i] = "" + n.charAt(i);

int checksum = 0;

for (int i=s1.length−1; i >= 0; i−= 2) {


int k = 0;

if (i > 0) {
k = Integer.valueOf(s1[i−1]).intValue() * 2;
if (k > 9) {
String s = "" + k;
k = Integer.valueOf(s.substring(0,1)).intValue() +
Integer.valueOf(s.substring(1)).intValue();
}
checksum += Integer.valueOf(s1[i]).intValue() + k;

16.52 Validate a Credit Card Number


}
else
checksum += Integer.valueOf(s1[0]).intValue();
}
return ((checksum % 10) == 0);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}

/*
** For testing purpose
**
** java CCUtils [credit card number] or java CCUtils
**
*/
public static void main(String args[]) throws Exception {
String aCard = "";

if (args.length > 0)
aCard = args[0];
else {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("Card number : ");
aCard = input.readLine();
}
if (getCardID(aCard) > −1) {
System.out.println("This card is supported.");
System.out.println("This a " + getCardName(getCardID(aCard)));
System.out.println
("The card number " + aCard + " is "
+ (validCC(aCard)?" good.":" bad."));
}
else
System.out.println("This card is invalid or unsupported!");
}
}

16.53 Preventing multiple instances of an application


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0288.html

Because each application is running in it's own JVM, there is no obvious way to detect if a particuliar
application is already running.

The socket technique


One way to detect to prevent multiple application execution is to use a simple socket server. The
application will try a connection to that Server, if it's a success then the application is already
running (and the application is stopped), if no connection is made then the application create the
Server.

In this example, the simple server is running on the same machine as the application so the
machine name is "localhost", the port 80 is used, you may want to customize the port number for

16.53 Preventing multiple instances of an application


your machine.

[JustOneServer.java]

import java.io.*;
import java.net.*;

public class JustOneServer extends Thread {


// you may need to customize this for your machine
public static final int PORT = 80 ;

ServerSocket serverSocket = null;


Socket clientSocket = null;

public void run() {


try {
// Create the server socket
serverSocket = new ServerSocket(port, 1);
while (true) {
// Wait for a connection
clientSocket = serverSocket.accept();
// System.out.println("*** Got a connection! ");
clientSocket.close();
}
}
catch (IOException ioe) {
System.out.println("Error in JustOneServer: " + ioe);
}
}
}

[JustOne.java]

import java.io.*;
import java.net.*;

public class JustOne {


SimpleDummyServer sds = null;

public static void main(String args[]){


new JustOne().doit();
}

public void doit() {


try {
Socket clientSocket = new Socket("localhost", JustOneServer.PORT);
System.out.println("*** Already running!");
System.exit(1);
}
catch (Exception e) {
sds = new JustOneServer();
sds.start();
}

while(true) {
try { System.out.print("."); Thread.sleep(5 * 60); }
catch(Exception e) { e.printStackTrace(); }
}
}
}

16.53 Preventing multiple instances of an application


To test it out, open 2 consoles.

In console 1 , type java JustOne.

In console 2, type java JustOne and the application should response "Already running!".

The file lock technique


[JDK1.4+] You can use a flag file with a lock mechanism. The idea is to create and lock a file on
user.home folder with a provided name. A concurrent execution will try to lock the same file and will
failed. A special "shutdown hook" is provided to unlock the file when the JVM is shutting down.

[JustOneLock.java]

import java.io.*;
import java.nio.channels.*;

public class JustOneLock {


private String appName;
private File file;
private FileChannel channel;
private FileLock lock;

public JustOneLock(String appName) {


this.appName = appName;
}

public boolean isAppActive() {


try {
file = new File
(System.getProperty("user.home"), appName + ".tmp");
channel = new RandomAccessFile(file, "rw").getChannel();

try {
lock = channel.tryLock();
}
catch (OverlappingFileLockException e) {
// already locked
closeLock();
return true;
}

if (lock == null) {
closeLock();
return true;
}

Runtime.getRuntime().addShutdownHook(new Thread() {
// destroy the lock when the JVM is closing
public void run() {
closeLock();
deleteFile();
}
});
return false;
}
catch (Exception e) {
closeLock();
return true;
}
}

16.53 Preventing multiple instances of an application


private void closeLock() {
try { lock.release(); }
catch (Exception e) { }
try { channel.close(); }
catch (Exception e) { }
}

private void deleteFile() {


try { file.delete(); }
catch (Exception e) { }
}
}

[JustOneTest.java]

public class JustOneTest {


public static void main(String[] args) {
new JustOneTest().test();
}

void test() {
JustOneLock ua = new JustOneLock("JustOneId");

if (ua.isAppActive()) {
System.out.println("Already active.");
System.exit(1);
}
else {
System.out.println("NOT already active.");
try {
while(true) {
try { System.out.print("."); Thread.sleep(5 * 60); }
catch(Exception e) { e.printStackTrace(); }
}
}
catch (Exception e) { }
}
}
}

16.54 Trap JVM shutdown


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0459.html

The Java virtual machine shuts down in response to two kinds of events:

• The program exits normally, when the last non−daemon thread exits or when the exit
(equivalently, System.exit) method is invoked.
• The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a
system−wide event, such as user logoff or system shutdown.

JDK1.3

public class TrapBreak {

public static void main(String args[]) throws Exception{


new TrapBreak().doit();

16.54 Trap JVM shutdown


}

public void doit() throws Exception{


Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("*** END ***");
}
});

while(true) { Thread.sleep(100); System.out.print("."); }


}
}

To test it out on Windows, in DOS window, start the class with

C:\temp> java TrapBreak >out.log

Now close the DOS window by clicking on the upper−right X.

Now check the out.log file, you will find "*** END ***" written by our ShutdownHook.

..................*** END ***

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.55 Browse a Queue (JMS/MQ)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0472.html

Here 2 nice utilities to browse (and even create) messages. Both are free to use and one is open
source.

WMQTool is more WebSphere MQ oriented.

Hermes is a Swing application that allows you to interact with JMS.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

16.56 Wrap a Java beans in a COM object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0045.html

The previous How−to was using a Microsoft utility to enable access to Java objects from a
COM−aware development tool. Sun provides a similar tool but you must package everything in a jar

16.55 Browse a Queue (JMS/MQ)


file and use the Beans technology. The tool is called packager, written in Java, you execute it from
the sun.beans.ole package. The Java Plug−in 1.2 and the JDK1.2 must be installed on the system
(for download, see Java Sun Web site).

Let's try it with this simple class :

package JavaCom;
public class JavaBeanSays {
private String _hello = "Hello World!";

public String getHello() {


return _hello ;
}

public void setHello(String s) {


_hello = s;
}
}

NOTE: This is not really a Bean but let's keep it simple!

The next step is to build a manifest file to identify the bean in the jar. Here it is (manifest.txt):

Name: JavaCom/JavaBeanSays
Java−Bean: true

NOTE: If no manifest is present all classes in the jar are treated as beans.

The JavaBeanSays class is in the directory JavaCom, the manifest.txt is the directory under it. From
the directory under (the one containing manifest.txt), we built the jar with :

jar cfm javacom.jar manifest.txt javacom\JavaBeanSays.class

NOTE: You can download my JavaCom.jar if you to proceed more rapidly.

The next step is to run the packager. You run it from the JDK installation directory. If the JDK is
installed in c:\dev\java\jdk1.2.1\ for example , you go there. And you start the packager with

bin\java.exe −cp jre\lib\rt.jar;jre\lib\jaws.jar sun.beans.ole.Packager

A wizard is started, you follow the 5 steps to create the "JavaBeans bridge for ActiveX" for the
JavabeanSays component.

The first step is to specify where is located the JavaCom.jar file. When selected, the wizard should
list the JavaCom.JavaBeanSays bean, press Next. The "ActiveX" name under which the beans will
be seen is shown, press Next (in VbScript, the beans suffix must be added to this name).

An output directory is needed, be careful because this directory name will be hard−coded in the
generated files (REG and TLB), you need to specify a valid directory name. The packager assume
that a subdirectory bin is present with the file beans.ocx in it. You can create it and then copy
beans.ocx from the JRE\bin into it or edit the REG file to specify the original JRE\bin and update the
registry with the good location.

The Bean is now registered and ready to be used as a COM object.

NOTE: There is a command−line interface available in the packager if you want to bypass the wizard.

16.55 Browse a Queue (JMS/MQ)


To test it, try this VbScript (TestJavaBeansSays.vbs)

' VBSCRIPT connect to a Java Bean


Dim objJava
Set objJava = WScript.CreateObject("JavaBeanSays.Bean")

strFromJava = objJava.getHello
MsgBox strFromJava, _
0, _
"JAVA BEAN OUTPUT"

objJava.setHello("Bonjour le monde!")

strFromJava = objJava.getHello
MsgBox strFromJava, _
0, _
"JAVA BEAN OUTPUT"

NOTE: Check the JAVA PLUG−IN SCRIPTING documentation (jdk1.2) or (jsdk1.4). document for more infos.

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

16.55 Browse a Queue (JMS/MQ)


17 XML
17.1 java−xml

17.2 Read me
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0405.html

These HowTo's are about the way XML can be used from Java or directly through a browser (tested
with IE6).

Here some basic definitions related to this technology:

XML(Extensible Markup Language) is a flexible way to create common information formats and
share both the format and the data on the WWW, intranets, and elsewhere.

XSL (Extensible Style Language) is a language for creating a style sheet that describes how data
sent over the Web using XML is to be presented to the user.

XSL−T (XSL Transformations) is a standard way to describe how to transform ( or change) the
structure of an XML document into an XML document with a different structure.

XML−FOP (XSL Formatting Object Processor) is used to transform XML into something else (ex.
PDF).

DOM (Document Object Model) represents the XML as hierarchy to simplify the access. JDOM is
an implementation for Java.

SAX (Simple API for XML) is an event−driven interface. The programmer specifies an event that
may happen and, if it does, SAX gets control and handles the situation.

JAXP (Java API for XML Processing) provides basic functionality for reading, manipulating, and
generating XML documents through pure Java APIs.

NOTE: JAXP in JDK 1.4 now includes :

• Document Object Model (DOM) Level 2 , org.w3c.dom


• Simple API For XML Parsing (SAX) 2.0 , org.xml.sax
• XSLT 1.0 , javax.xml.transform

XQL (XML Query Language) is a way to locate and filter the elements (data fields) and text in an
XML document. It is based on the pattern syntax used in the Extensible Stylesheet Language (XSL)
and is proposed as an extension to it.

XPointer is a language for locating data within an XML document based on properties such as
location within the document, character content, and attribute values.

17 XML
XPath is a language that describes a way to locate and process items in XML documents by using
an addressing syntax based on a path through the document's logical structure or hierarchy.

Xalan is a specification for transforming XML documents into HTML or other XML document types.

Xerces is a set of parsers compatible with XML.

XHTML (Extensible Hypertext Markup Language) is a reformulation of HTML 4.0 as an application


of the XML.

Useful links:

• JAXP overview

17.3 Display XML using plain HTML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0406.html

Using something called "Data Island", available only on IE AFAIK.

<HTML>
<HEAD><TITLE>Real's java HowTo</TITLE>
</HEAD>
<XML id="HowTo">
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon/pbhowto.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>
</howto>
</XML>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000"
VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?">
<TABLE datasrc="#howto">
<THEAD><TR><TH>TOPIC</TH><TH>URL</TH>
</THEAD>
<TR>
<TD><SPAN datafld="title"></SPAN></TD>
<TD><SPAN datafld="url"></SPAN></TD>
</TR>
</TABLE>
</BODY>
</HTML>

17.3 Display XML using plain HTML


See the result here (IE only).

17.4 Transform XML into HTML using XSLT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0407.html

[howto.xml]

<?xml version="1.0"?>
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon/pbhowto.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>
</howto>

[howto.xsl]

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<html>
<head><title>Real's HowTo</title></head>
<body>
<table border="1">
<tr>
<th>Title</th>
<th>URL</th>
</tr>
<xsl:for−each select="howto/topic">
<tr>
<td><xsl:value−of select="title"/></td>
<td><xsl:value−of select="url"/></td>
</tr>
</xsl:for−each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>

[HowToXSLT.java]

// jdk1.4.1
import javax.xml.transform.*;

17.4 Transform XML into HTML using XSLT


import java.net.*;
import java.io.*;

public class HowToXSLT {


public static void main(String[] args) {
try {

TransformerFactory tFactory = TransformerFactory.newInstance();

Transformer transformer =
tFactory.newTransformer
(new javax.xml.transform.stream.StreamSource
("howto.xsl"));

transformer.transform
(new javax.xml.transform.stream.StreamSource
("howto.xml"),
new javax.xml.transform.stream.StreamResult
( new FileOutputStream("howto.html")));
}
catch (Exception e) {
e.printStackTrace( );
}
}
}

See the result here.

17.5 Parse using SAX or DOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0408.html

DOM (Document Object Model) represents the XML as hierarchy to simplify the access. Since
everything is in memory, it is more ressource intensive.

SAX − creates events and calls callback methods that the programmer write to handle them.

Both examples read this XML data file [howto.xml]

<?xml version="1.0"?>
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon/pbhowto.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>

17.5 Parse using SAX or DOM


</howto>

In both cases , the output is

Title: Java
Url: http://www.rgagnon/javahowto.htm
Title: PowerBuilder
Url: http://www.rgagnon/pbhowto.htm
Title: Javascript
Url: http://www.rgagnon/jshowto.htm
Title: VBScript
Url: http://www.rgagnon/vbshowto.htm

[HowToListerSAX.java]

// jdk1.4.1
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

// using SAX
public class HowToListerSAX {
class HowToHandler extends DefaultHandler {
boolean title = false;
boolean url = false;
public void startElement(String nsURI, String strippedName,
String tagName, Attributes attributes)
throws SAXException {
if (tagName.equalsIgnoreCase("title"))
title = true;
if (tagName.equalsIgnoreCase("url"))
url = true;
}

public void characters(char[] ch, int start, int length) {


if (title) {
System.out.println("Title: " + new String(ch, start, length));
title = false;
}
else if (url) {
System.out.println("Url: " + new String(ch, start,length));
url = false;
}
}
}

public void list( ) throws Exception {


XMLReader parser =
XMLReaderFactory.createXMLReader
("org.apache.crimson.parser.XMLReaderImpl");
parser.setContentHandler(new HowToHandler( ));
parser.parse("howto.xml");
}

public static void main(String[] args) throws Exception {


new HowToListerSAX().list( );
}
}

[HowToListerDOM.java]

17.5 Parse using SAX or DOM


// jdk1.4.1
import java.io.File;
import javax.xml.parsers.*;
import org.w3c.dom.*;

// using DOM
public class HowtoListerDOM {
public static void main(String[] args) {
File file = new File("howto.xml");
try {
DocumentBuilder builder =
DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(file);

NodeList nodes = doc.getElementsByTagName("topic");


for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);

NodeList title = element.getElementsByTagName("title");


Element line = (Element) title.item(0);

System.out.println("Title: " + getCharacterDataFromElement(line));

NodeList url = element.getElementsByTagName("url");


line = (Element) url.item(0);
System.out.println("Url: " + getCharacterDataFromElement(line));

}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static String getCharacterDataFromElement(Element e) {
Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
}

17.6 Parse an XML string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0573.html

Using DOM and a StringReader.

import javax.xml.parsers.*;
import org.xml.sax.InputSource;
import org.w3c.dom.*;
import java.io.*;

public class ParseXMLString {

public static void main(String arg[]) {


String xmlRecords =
"<data>" +

17.6 Parse an XML string


" <employee>" +
" <name>John</name>" +
" <title>Manager</title>" +
" </employee>" +
" <employee>" +
" <name>Sara</name>" +
" <title>Clerk</title>" +
" </employee>" +
"</data>";

try {
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
is.setCharacterStream(new StringReader(xmlRecords));

Document doc = db.parse(is);


NodeList nodes = doc.getElementsByTagName("employee");

// iterate the employees


for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);

NodeList name = element.getElementsByTagName("name");


Element line = (Element) name.item(0);
System.out.println("Name: " + getCharacterDataFromElement(line));

NodeList title = element.getElementsByTagName("title");


line = (Element) title.item(0);
System.out.println("Title: " + getCharacterDataFromElement(line));
}
}
catch (Exception e) {
e.printStackTrace();
}
/*
output :
Name: John
Title: Manager
Name: Sara
Title: Clerk
*/

public static String getCharacterDataFromElement(Element e) {


Node child = e.getFirstChild();
if (child instanceof CharacterData) {
CharacterData cd = (CharacterData) child;
return cd.getData();
}
return "?";
}
}

17.7 Create an XML document with DOM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0530.html

17.7 Create an XML document with DOM


import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class TestDOM {


public TestDOM() { }
public String doit()
throws javax.xml.parsers.ParserConfigurationException,
javax.xml.transform.TransformerException,
javax.xml.transform.TransformerConfigurationException{

DocumentBuilderFactory factory
= DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();

Document doc = impl.createDocument(null,null,null);


Element e1 = doc.createElement("howto");
doc.appendChild(e1);

Element e2 = doc.createElement("java");
e1.appendChild(e2);

e2.setAttribute("url","http://www.rgagnon.com/howto.html");

// transform the Document into a String


DOMSource domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
String xml = sw.toString();
return xml;
}

public static void main(String args[])


throws javax.xml.parsers.ParserConfigurationException,
javax.xml.transform.TransformerException,
javax.xml.transform.TransformerConfigurationException{
System.out.println(new TestDOM().doit());
/*
output :
<?xml version="1.0" encoding="ISO−8859−1"?>
<howto>
<java url="http://www.ragagnon.com/howto.html"/>
</howto>
/*
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

17.7 Create an XML document with DOM


Written and compiled by Réal Gagnon ©1998−2006
[ home ]

17.8 Attach a stylesheet to an XML file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0450.html

Consider the following XML file, a simple xsl is attached to nicely format the data.
Modern browsers (like N7 or IE5.5) support XML and XSL transformation.

bruce.xml

<?xml version="1.0" encoding="ISO−8859−1"?>


<?xml−stylesheet type="text/xsl" href="bruce.xsl"?>
<data>
<guynamedbruce>
<FirstName>Bruce</FirstName>
<LastName>Lee</LastName>
</guynamedbruce>
<guynamedbruce>
<FirstName>Bruce</FirstName>
<LastName>Willis</LastName>
</guynamedbruce>
<guynamedbruce>
<FirstName>Bruce</FirstName>
<LastName>Wayne</LastName>
</guynamedbruce>
</data>

bruce.xsl

<?xml version="1.0" encoding="ISO−8859−1"?>


<xsl:stylesheet version="1.0" xmlns:xsl="http://w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table>
<xsl:for−each select="data/guynamedbruce">
<tr>
<td>
<xsl:value−of select="FirstName"/>
</td>
<td>
<xsl:value−of select="LastName"/>
</td>
</tr>
</xsl:for−each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Try it here

If you find this article useful, consider making a small donation

17.8 Attach a stylesheet to an XML file


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

17.9 Create an XML file and attach an XSL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0577.html

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

public Document initXML() throws ParserConfigurationException{


// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java−xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

17.9 Create an XML file and attach an XSL


public void writeXML(Document xmldoc, StreamResult out)
throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO−8859−1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java−xml.html</URL>
</TOPIC>
</HOWTOS>

And now to attach an XSL

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

Node pi = xmldoc.createProcessingInstruction
("xml−stylesheet", "type=\"text/xsl\" href=\"howto.xsl\"");
xmldoc.insertBefore(pi, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

17.9 Create an XML file and attach an XSL


public Document initXML() throws ParserConfigurationException{
// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java−xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO−8859−1"?>


<?xml−stylesheet type="text/xsl" href="howto.xsl"?>

<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java−xml.html</URL>
</TOPIC>
</HOWTOS>

17.9 Create an XML file and attach an XSL


17.10 Nicely display WEB.XML informations
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0451.html

A web.xml file contains informations about a web application hosted by a application server. While
it's possible to consult the data using a regular text editor, it maybe easier to use a special
stylesheet to nicely format the data for easy browsing.

I found a nice generic stylesheet on the Web and adapted it a little bit for that purpose. Here the
modified xsl file, the css file, a sample web.xml.

See the sample output if your browser supports XML/XSL transformation.

Attach the xsl to the xml by adding this line to the xml file :

<?xml version="1.0" encoding="UTF−8"?>


<?xml−stylesheet type="text/xsl" href="tree−view.xsl"?>
...

or do the transformation in Java, for a hint see this How−to.

Here an ASP page (yeah I know...) which accepts as a parameter an XML filename and transforms
the passed filename using the XSL. As an added bonus, the original XML filename is displayed (you
will need this XSL).
<META http−equiv="Content−Type" content="text/html; charset=ISO8859−1">
<%@ LANGUAGE="JScript" %>
<%
Response.buffer = true;
var xmlfile;
var oXML;
var oXSL;
var oXSLTemplate;
var oXSLProcessor;
var SrcXSL;
var SrcXML;

// get the PARAM=??? (assumes you have used GET request method!)...
// assume something like http://.../docxml.asp?xmlfile=myxml.xml
xmlfile = '' + Request.QueryString('xmlfile');

// get the source file (XML and XSL) paths


SrcXML = Server.MapPath(xmlfile);
SrcXSL = Server.MapPath('xmldoc/tree−view2.xsl');

// create documents for the XML and XSL...


oXML = Server.CreateObject('Msxml2.DOMDocument');
oXSL = Server.CreateObject('Msxml2.FreeThreadedDOMDocument');

// load the XML and XSL into your documents...


// we don't want to waste time validating the file
oXSL.load(SrcXSL);
oXML.validateOnParse = false ;
oXML.async = false ;
oXML.resolveExternals = false ;

oXML.load(SrcXML);

17.10 Nicely display WEB.XML informations


// create the XSL template and processor...
oXSLTemplate = Server.CreateObject('Msxml2.XSLTemplate');
oXSLTemplate.stylesheet = oXSL;
oXSLProcessor = oXSLTemplate.createProcessor;

// place the ?xmlfile=xxx value into the XSL processor...


oXSLProcessor.addParameter('xmlfile',xmlfile,'');

// tell the XSL processor of the XML you want to have transformed...
oXSLProcessor.input = oXML;

try {
oXSLProcessor.transform ;
Response.write(oXSLProcessor.output);
}
catch (e) {
Response.write
('The file ' +e.url + ' is not valid. Reason: ' + e.reason );
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

17.11 Serialize an object using XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0470.html

Consider this simple class

public class Foo {


private String foo ;

public void setFoo(String s) {


foo = s;
}

public String getFoo() {


return foo;
}
}

The java.beans package provides useful methods to save an object state into an XML file and easily
read it back.

Here an Helper class for our Foo class.

import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.io.*;

public class FooHelper {


public static void write(Foo f, String filename) throws Exception{
XMLEncoder encoder =

17.11 Serialize an object using XML


new XMLEncoder(
new BufferedOutputStream(
new FileOutputStream(filename)));
encoder.writeObject(f);
encoder.close();
}

public static Foo read(String filename) throws Exception {


XMLDecoder decoder =
new XMLDecoder(new BufferedInputStream(
new FileInputStream(filename)));
Foo o = (Foo)decoder.readObject();
decoder.close();
return o;
}
}

Here how to use it.

public class FooTest {


public static void main (String [] args) throws Exception{
Foo f1 = new Foo();
f1.setFoo("bar");
FooHelper.write(f1, "foo.xml");

Foo f2 = FooHelper.read("foo.xml");
System.out.println("Foo" + f2.getFoo());
// the output : Foobar
}
}

Just for fun, here the resulting XML file (with my installation)

<?xml version="1.0" encoding="UTF−8"?>


<java version="1.5.0−beta" class="java.beans.XMLDecoder">
<object class="Foo">
<void property="foo">
<string>bar</string>
</void>
</object>
/JAVA

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

17.12 Convert a flat file to XML (SAX)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0482.html

Consider the following data file (data.txt):

Java|http://www.rgagnon/javahowto.htm
PowerBuilder|http://www.rgagnon/pbhowto.htm
Javascript|http://www.rgagnon/jshowto.htm
VBScript|http://www.rgagnon/vbshowto.htm

17.12 Convert a flat file to XML (SAX)


We want to convert it to an XML format (data.xml) :

<?xml version="1.0" encoding="ISO−8859−1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/javahowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>PowerBuilder</TITLE>
<URL>http://www.rgagnon/pbhowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>Javascript</TITLE>
<URL>http://www.rgagnon/jshowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>VBScript</TITLE>
<URL>http://www.rgagnon/vbshowto.htm</URL>
</TOPIC>
</HOWTOS>

We are using JAXP and SAX.

import java.io.*;

// SAX classes.
import org.xml.sax.*;
import org.xml.sax.helpers.*;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.sax.*;

public class ToXML {

BufferedReader in;
StreamResult out;

TransformerHandler th;
AttributesImpl atts;

public static void main (String args[]) {


new ToXML().doit();
}

public void doit () {


try{
in = new BufferedReader(new FileReader("data.txt"));
out = new StreamResult("data.xml");
initXML();
String str;
while ((str = in.readLine()) != null) {
process(str);
}
in.close();
closeXML();
}
catch (Exception e) { e.printStackTrace(); }
}

17.12 Convert a flat file to XML (SAX)


public void initXML() throws ParserConfigurationException,
TransformerConfigurationException, SAXException {
// JAXP + SAX
SAXTransformerFactory tf =
(SAXTransformerFactory) SAXTransformerFactory.newInstance();

th = tf.newTransformerHandler();
Transformer serializer = th.getTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// pretty XML output
serializer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
serializer.setOutputProperty(OutputKeys.INDENT,"yes");
th.setResult(out);
th.startDocument();
atts = new AttributesImpl();
th.startElement("","","HOWTOS",atts);
}

public void process (String s) throws SAXException {


String [] elements = s.split("\\|");
atts.clear();
th.startElement("","","TOPIC",atts);

th.startElement("","","TITLE",atts);
th.characters(elements[0].toCharArray(),0,elements[0].length());
th.endElement("","","TITLE");

th.startElement("","","URL",atts);
th.characters(elements[1].toCharArray(),0,elements[1].length());
th.endElement("","","URL");

th.endElement("","","TOPIC");
}

public void closeXML() throws SAXException {


th.endElement("","","HOWTOS");
th.endDocument(); }
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

17.13 Convert a flat file to XML (DOM)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0481.html

Consider the following data file (data.txt):

Java|http://www.rgagnon/javahowto.htm
PowerBuilder|http://www.rgagnon/pbhowto.htm
Javascript|http://www.rgagnon/jshowto.htm
VBScript|http://www.rgagnon/vbshowto.htm

We want to convert it to an XML format (data.xml) :

17.13 Convert a flat file to XML (DOM)


<?xml version="1.0" encoding="ISO−8859−1"?>
<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/javahowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>PowerBuilder</TITLE>
<URL>http://www.rgagnon/pbhowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>Javascript</TITLE>
<URL>http://www.rgagnon/jshowto.htm</URL>
</TOPIC>
<TOPIC>
<TITLE>VBScript</TITLE>
<URL>http://www.rgagnon/vbshowto.htm</URL>
</TOPIC>
</HOWTOS>

We are using JAXP and DOM.

NOTE: Since DOM constructs the XML tree in memory, it may be more appropriate to use SAX instead if you have to deal with big data files.

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class ToXML {

BufferedReader in;
StreamResult out;

Document xmldoc;
Element root;

public static void main (String args[]) {


new ToXML().doit();
}

public void doit () {


try{
in = new BufferedReader(new FileReader("data.txt"));
out = new StreamResult("data.xml");
initXML();
String str;
while ((str = in.readLine()) != null) {
process(str);
}
in.close();
writeXML();
}
catch (Exception e) { e.printStackTrace(); }
}

public void initXML() throws ParserConfigurationException{


// JAXP + DOM

17.13 Convert a flat file to XML (DOM)


DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();

xmldoc = impl.createDocument(null, "HOWTOS", null);


root = xmldoc.getDocumentElement();
}

public void process(String s) {


// Since the separator character "|" has special meaning
// with regular expression, we need to escape it.
String [] elements = s.split("\\|");
Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode(elements[0]);
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode(elements[1]);
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML() throws TransformerConfigurationException,


TransformerException {
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
/*
get the XML in a String
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
return sw.toString();
*/
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

17.13 Convert a flat file to XML (DOM)


17.14 Convert a ResultSet to XML
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0511.html

import java.sql.Connection;
import java.sql.Statement;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

class JDBCapp {

static Connection con;

public static void main (String args[]) {


ResultSet rs = null;
Statement stmt = null;
String sql;

try {
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element results = doc.createElement("Results");
doc.appendChild(results);

// connection to an ACCESS MDB


con = AccessCon.getConnection();

sql = "select objet from Email";


stmt = con.createStatement();
rs = stmt.executeQuery(sql);

ResultSetMetaData rsmd = rs.getMetaData();


int colCount = rsmd.getColumnCount();

while (rs.next()) {
Element row = doc.createElement("Row");
results.appendChild(row);
for (int ii = 1; ii <= colCount; ii++) {
String columnName = rsmd.getColumnName(ii);
Object value = rs.getObject(ii);
Element node = doc.createElement(columnName);
node.appendChild(doc.createTextNode(value.toString()));
row.appendChild(node);
}
}

System.out.println(getDocumentAsXml(doc));

17.14 Convert a ResultSet to XML


catch (Exception e) {
e.printStackTrace();
}
finally {
try {
if (con != null) con.close();
if (stmt != null) stmt.close();
if (rs != null) rs.close();
}
catch (Exception e) {
}
}
}

public static String getDocumentAsXml(Document doc)


throws TransformerConfigurationException, TransformerException {
DOMSource domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
//transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION,"yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
java.io.StringWriter sw = new java.io.StringWriter();
StreamResult sr = new StreamResult(sw);
transformer.transform(domSource, sr);
return sw.toString();
}
}

class AccessCon {
public static Connection getConnection() throws Exception {
Driver d = (Driver)Class.forName
("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
Connection c = DriverManager.getConnection
("jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=c:/tech97.mdb");
return c;
/*
To use an already defined ODBC Datasource :

String URL = "jdbc:odbc:myDSN";


Connection c = DriverManager.getConnection(URL, "user", "pwd");

*/
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

17.14 Convert a ResultSet to XML


17.15 Parse with XPath
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0550.html

[J2SE 1.5]

Consider the following XML data file (howto.xml)

<?xml version="1.0"?>
<howto>
<topic name="Java">
<url>http://www.rgagnon/javahowto.htm</url>
</topic>
<topic name="PowerBuilder">
<url>http://www.rgagnon/pbhowto.htm</url>
<url>http://www.rgagnon/pbhowtonew.htm</url>
</topic>
<topic name="Javascript">
<url>http://www.rgagnon/jshowto.htm</url>
</topic>
<topic name="VBScript">
<url>http://www.rgagnon/vbshowto.htm</url>
</topic>
</howto>

To list the topics :

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class SimpleXPath {


public static void main(String[] args) throws Exception {
XPath xpath = XPathFactory.newInstance().newXPath();
String xpathExpression = "/howto/topic/@name";
InputSource inputSource = new InputSource("howto.xml");

NodeList nodes = (NodeList) xpath.evaluate


(xpathExpression, inputSource, XPathConstants.NODESET);

int j = nodes.getLength();

for (int i = 0; i < j; i++) {


System.out.println(nodes.item(i).getTextContent());
}
/*
output :
Java
PowerBuilder
Javascript
VBScript
*/
}
}

17.15 Parse with XPath


Select the topic Powerbuilder then list the urls :

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;

import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class SimpleXPath2 {


public static void main(String[] args) throws Exception {
XPath xpath = XPathFactory.newInstance().newXPath();
String topicExpression = "/howto/topic[@name='PowerBuilder']";
InputSource inputSource = new InputSource("howto.xml");

// get nodes with the topic PowerBuilder


NodeList nodes = (NodeList) xpath.evaluate
(topicExpression, inputSource, XPathConstants.NODESET);

// output the text content of this node and its descendants.


// (includes empty LF because of empty comment (#text))
System.out.println(nodes.item(0).getTextContent());
/*
output :
http://www.rgagnon/pbhowto.htm
http://www.rgagnon/pbhowtonew.htm
*/
// display only the "url" nodes for PowerBuidler
NodeList urls = nodes.item(0).getChildNodes();
int j = urls.getLength();
for (int i = 0; i < j ; i++) {
if (urls.item(i).getNodeName().equals("url")) {
System.out.println("url :" + urls.item(i).getTextContent());
}
}
/*
output :
url :http://www.rgagnon/pbhowto.htm
url :http://www.rgagnon/pbhowtonew.htm
*/
}
}

17.16 Strip extra spaces in a XML string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0563.html

This can be useful to reduce the size of a file or before writting a message to a queue.

public class StripSpaces {


public static void main (String [] args) {
String test1 = "<tag>test 1</tag> <tag>test 2</tag> ";
String out1 = test1.replaceAll(">\\s+<", "><");
System.out.println(test1);
System.out.println(out1);

17.16 Strip extra spaces in a XML string


System.out.println("");

String test2 = "<tag>test 3</tag> \n<tag>test 4</tag> ";


String out2 = test2.replaceAll(">\\s+<", "><");
System.out.println(test2);
System.out.println(out2);

/*
output :

<tag>test 1</tag> <tag>test 2</tag>


<tag>test 1</tag><tag>test 2</tag>

<tag>test 3</tag>
<tag>test 4</tag>
<tag>test 3</tag><tag>test 4</tag>
*/
}
}

17.17 Create an XML file and attach an XSL


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0577.html

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

public void doit () {


try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

public Document initXML() throws ParserConfigurationException{


// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

17.17 Create an XML file and attach an XSL


public void process(Document xmldoc, Element root) {
Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java−xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

<?xml version="1.0" encoding="ISO−8859−1"?>


<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java−xml.html</URL>
</TOPIC>
</HOWTOS>

And now to attach an XSL

import java.io.*;

import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import javax.xml.transform.dom.*;

public class CreateXML {

public static void main (String args[]) {


new CreateXML().doit();
}

17.17 Create an XML file and attach an XSL


public void doit () {
try{
Document xmldoc = initXML();
Element root = xmldoc.getDocumentElement();

process(xmldoc, root);

Node pi = xmldoc.createProcessingInstruction
("xml−stylesheet", "type=\"text/xsl\" href=\"howto.xsl\"");
xmldoc.insertBefore(pi, root);

StreamResult out = new StreamResult("howto.xml");


writeXML(xmldoc, out);
}
catch (Exception e) { e.printStackTrace(); }
}

public Document initXML() throws ParserConfigurationException{


// JAXP + DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
DOMImplementation impl = builder.getDOMImplementation();
return impl.createDocument(null, "HOWTOS", null);
}

public void process(Document xmldoc, Element root) {


Element e0 = xmldoc.createElement("TOPIC");

Element e1 = xmldoc.createElement("TITLE");
Node n1 = xmldoc.createTextNode("Java");
e1.appendChild(n1);

Element e2 = xmldoc.createElement("URL");
Node n2 = xmldoc.createTextNode
("http://www.rgagnon/topics/java−xml.html");
e2.appendChild(n2);

e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}

public void writeXML(Document xmldoc, StreamResult out)


throws TransformerConfigurationException, TransformerException
{
DOMSource domSource = new DOMSource(xmldoc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty
(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO−8859−1");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indent−amount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is

17.17 Create an XML file and attach an XSL


<?xml version="1.0" encoding="ISO−8859−1"?>
<?xml−stylesheet type="text/xsl" href="howto.xsl"?>

<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/java−xml.html</URL>
</TOPIC>
</HOWTOS>

17.18 Use XML with Properties


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0578.html

import java.util.*;
import java.io.*;

class XMLProps {
public static void main(String args[]) {
new XMLProps().doit();
}

public void doit() {


try{
Properties p = new Properties();

p.put("today", new Date().toString());


p.put("user", "Bob");

FileOutputStream out = new FileOutputStream("user.props");


p.storeToXML(out,"props updated");

FileInputStream in = new FileInputStream("user.props");

p.loadFromXML(in);
p.list(System.out);
/*
output :
−− listing properties −−
today=Thu Aug 09 22:45:11 EDT 2007
user=Bob
*/
}
catch (Exception e) {
e.printStackTrace();
}
}
}

The XML looks like

<?xml version="1.0" encoding="UTF−8"?>


<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>props updated</comment>
<entry key="user">Bob</entry>
<entry key="today">Thu Aug 09 22:45:11 EDT 2007</entry>
</properties>

17.18 Use XML with Properties


17.19 Create a RSS feed
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0556.html

RSS is a method to syndicate content on the web. This is done by creating an XML document which
summarizes specific content such as news, blog posts or comments or any informations. There are
many versions but the 2 most used are RSS 2.0 and ATOM.

17.19.1 RSS 2.0

The official specification of RSS 2.0 : http://cyber.law.harvard.edu/rss/rss.html

A typical RSS XML file looks like :

<?xml version="1.0" encoding="utf−8"?>


<?xml−stylesheet title="XSL_formatting" type="text/xsl" href="feed.xsl"?>

<rss version="2.0">

<channel>
<title>Real's HowTo</title>
<description>Updates of useful code examples for Java</description>
<link>http://www.rgagnon.com/howto.html</link>
<pubDate>23 May 2007 00:00:00 GMT</pubDate>
<image>
<title>Real's HowTo</title>
<width>144</width>
<height>41</height>
<link>http://www.rgagnon.com/howto.html</link>
<url>http://www.rgagnon.com/images/realhowto−left.jpg</url>
</image>

<item>
<title>JS: Resize an IFRAME based on its content</title>
<description>Using the onLoad event, resize the IFRAME</description>
<link>http://www.rgagnon.com/jsdetails/js−0129.html</link>
<pubDate>23 May 2007 00:00:00 GMT</pubDate>
<guid>http://www.rgagnon.com/jsdetails/js−0129.html</guid>

17.19 Create a RSS feed


</item>

</channel>
</rss>

17.19.2 Atom

Atom was an answer to the incompatibilites between all the RSS versions. Adopted by the IETF, the
official specification is RFC4287, http://www.ietf.org/rfc/rfc4287.

A typical ATOM feed looks like :

<?xml version="1.0" encoding="utf−8"?>


<feed xmlns="http://www.w3.org/2005/Atom">

<title>Example Feed</title>
<subtitle>A subtitle.</subtitle>
<link href="http://example.org/"/>
<updated>2003−12−13T18:30:02Z</updated>
<author>
<name>John Doe</name>
<email>johndoe@example.com</email>
</author>
<id>urn:uuid:60a76c80−d399−11d9−b91C−0003939e0af6</id>

<entry>
<title>Atom−Powered Robots Run Amok</title>
<link href="http://example.org/2003/12/13/atom03"/>
<id>urn:uuid:1225c695−cfb8−4ebb−aaaa−80da344efa6a</id>
<updated>2003−12−13T18:30:02Z</updated>
<summary>Some text.</summary>

17.19.2 Atom
</entry>

</feed>

17.19.3 Creating a feed

While you can create the XML file using a regular text editor, it's more interesting to do it from code.
You can do it using regular XML library and make sure that all the required tags are there or use
special tools which encapsulate the complexity of generating a valid feed. We will look at two of
them.

17.19.4 Creating a feed with Apache Commons Digester

The org.apache.commons.digester is a package designed manipulating XML file. In the first release
there are a few classes to deal with RSS feed, it was the org.apache.commons.digester.rss
package. However, in the latest version, the binaries of this package is no longer distributed. It's still
possible to build it from the examples but it's no longer part of the official "Commons Digester".

Look at the javadoc and the code at


http://jsourcery.com/api/apache/jakarta/commons/digester/1.7/org/apache/commons/digester/rss/package−s

So you need the main Commons Digester plus, as usual with Apache software, you have depencies
with the BeanUtils v1.7 and Commons Logging

Download the required jars at http://jakarta.apache.org/commons/digester/

Don't forget the famous commons−digester−rss.jar, you can build it from the Commons Digester
examples jar or download it from here.

import org.apache.commons.digester.rss.Channel;
import org.apache.commons.digester.rss.Item;
import org.apache.commons.digester.rss.RSSDigester;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.text.SimpleDateFormat;

class CreateRSSFeedUsingCommons {

public static void main(String args[]) {

SimpleDateFormat formatter=
new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z");
String today = formatter.format(new Date());

Channel newChannel = new Channel();

newChannel.setCopyright("(c)Real Gagnon 2007");


newChannel.setDescription("Useful Java code examples");
newChannel.setLink("http://www.rgagnon.com/howto.html");
newChannel.setLanguage("en");

17.19.3 Creating a feed


newChannel.setPubDate(today);

Item item = new Item();


item.setTitle("Real's HowTo");
item.setLink("http://www.rgagnon.com/java−details/");
item.setDescription("Cool java snippet!");
newChannel.setPubDate(today);
newChannel.addItem(item);

try {
FileOutputStream fout = new FileOutputStream("feed.xml");
newChannel.render(fout);
fout.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}

The result is :

<?xml version="1.0"?>

<!DOCTYPE rss PUBLIC


"−//Netscape Communications//DTD RSS 0.91//EN"
"http://my.netscape.com/publish/formats/rss−0.91.dtd">

<rss version="0.91">

<channel>

<title>null</title>
<description>Useful Java code examples</description>
<link>http://www.rgagnon.com/howto.html</link>
<language>en</language>
<copyright>(c)Real Gagnon 2007</copyright>
<pubDate>29 mai 2007 23:48:42 −0400</pubDate>

<item>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/java−details/</link>
<description>Cool java snippet!</description>
</item>

</channel>

</rss>

The RSS created is at version 0.91 level. To support RSS v2 file then you need to modify the
source files yourself ... that's what OpenSource is all about!

17.19.5 Creating a feed with Rome

ROME stands for RSS and Atom Utilities.

ROME includes a set of parsers and generators for the various flavors of syndication feeds, as well
as converters to convert from one format to another. The project is hosted by java.net at
http://wiki.java.net/bin/view/Javawsxml/Rome.

17.19.5 Creating a feed with Rome


ROME requires JDOM 1.0 (http://www.jdom.org/).

import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.SyndFeedOutput;

import java.io.FileWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

public class CreateRSSFeedUsingRome {


private static final DateFormat DATE_PARSER =
new SimpleDateFormat("yyyy−MM−dd");

public static void main(String[] args) {


try {
String feedType = "rss_2.0";
String fileName = "feed.xml";

SyndFeed feed = new SyndFeedImpl();


feed.setFeedType(feedType);

feed.setTitle("Real's HowTo");
feed.setLink("http://www.rgagnon.com/howto.html");
feed.setDescription("Useful Java code examples");

List entries = new ArrayList();


SyndEntry entry;
SyndContent description;

entry = new SyndEntryImpl();


entry.setTitle("Real's HowTo");
entry.setLink("http://www.rgagnon.com/java−details/");
entry.setPublishedDate(DATE_PARSER.parse("2004−06−08"));
description = new SyndContentImpl();
description.setType("text/plain");
description.setValue("Cool java snippet!");
entry.setDescription(description);
entries.add(entry);

feed.setEntries(entries);

Writer writer = new FileWriter(fileName);


SyndFeedOutput output = new SyndFeedOutput();
output.output(feed,writer);
writer.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

And the result is :

<?xml version="1.0" encoding="UTF−8"?>


<rss xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
xmlns:rdf="http://www.w3.org/1999/02/22−rdf−syntax−ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">

17.19.5 Creating a feed with Rome


<channel>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/howto.html</link>
<description>Useful Java code examples</description>
<item>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/java−details/</link>
<description>Cool java snippet!</description>
<pubDate>Tue, 08 Jun 2004 04:00:00 GMT</pubDate>
<guid>http://www.rgagnon.com/java−details/</guid>
<dc:date>2004−06−08T04:00:00Z</dc:date>
</item>
</channel>
</rss>

17.20 Parse a RSS XML file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0557.html

In a previous HowTo, we saw how to create a RSS feed using commons.digester or ROME
packages. In this HowTo, we are parsing a given feed using the packages.

17.20.1 Parsing a feed with Apache Commons Digester


NOTE: See this HowTo for the required jars.

import org.apache.commons.digester.rss.Channel;
import org.apache.commons.digester.rss.Item;
import org.apache.commons.digester.rss.RSSDigester;

import java.net.HttpURLConnection;
import java.net.URL;

public class ParseRSSFeedUsingCommons {


public static void main(String args[]) throws Exception {
RSSDigester digester=new RSSDigester();
String feed = "http://www.rgagnon.com/feed.xml";
URL url=new URL(feed);
HttpURLConnection httpSource=
(HttpURLConnection)url.openConnection();
Channel channel=
(Channel)digester.parse(httpSource.getInputStream());
if (channel==null) {
throw new Exception("can't communicate with " + url);
}

Item rssItems[]=channel.findItems();
for (int i=0;i<rssItems.length;i++) {
System.out.println(rssItems[i].getTitle());
System.out.println(rssItems[i].getLink());
System.out.println(rssItems[i].getDescription());
System.out.println();
}
/*
to parse from a file instead of a URL

import java.io.FileInputStream;
...

17.20 Parse a RSS XML file


String feed = "feed.xml"
FileInputStream fis = new FileInputStream(feed);
Channel channel=(Channel)digester.parse(fis);
...
*/
}
}

the output

JS: Resize an IFRAME based on its content


http://www.rgagnon.com/jsdetails/js−0129.html
Using the onLoad event, resize the IFRAME according to its content

Java: Communicate between threads using a Queue


http://www.rgagnon.com/javadetails/java−0555.html
BlockingQueue (Java 5) is designed to work in a multi−threaded world

JDBC: Escape special character in a LIKE clause


http://www.rgagnon.com/javadetails/java−0554.html
How to use LIKE clause wildcards as literals
...

17.20.2 Parsing a feed with ROME


NOTE: See this HowTo for the required jars.

import com.sun.syndication.feed.synd.*;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

import java.net.URL;
import java.util.List;
import java.util.Iterator;

public class ParseRSSFeedUsingRome {


public static void main(String args[]) throws Exception {
String feed = "http://www.rgagnon.com/feed.xml";

URL feedUrl = new URL(feed);

SyndFeedInput input = new SyndFeedInput();


SyndFeed sf = input.build(new XmlReader(feedUrl));

List entries = sf.getEntries();


Iterator it = entries.iterator();
while (it.hasNext()) {
SyndEntry entry = (SyndEntry)it.next();
System.out.println(entry.getTitle());
System.out.println(entry.getLink());
SyndContent description = entry.getDescription();
System.out.println(description.getValue());
System.out.println();
}
/*
to parse from a file instead of a URL

import java.io.FileInputStream;
...
String feed = "feed.xml"
FileInputStream fis = new FileInputStream(feed);

17.20.2 Parsing a feed with ROME


SyndFeedInput input = new SyndFeedInput();
SyndFeed sf = input.build(new XmlReader(fis));
*/
}
}

17.20.3 RSS−UTIL.TLD

A Sun article about a JSP Tag Library to parse a RSS feed.


http://java.sun.com/developer/technicalArticles/javaserverpages/rss_utilities/

17.21 Add a Live bookmark


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0558.html

Live Bookmark is used to subscribe easily to the RSS feed from a particular web site. A Live
bookmark is possible if you see an orange icon in the address bar. Simply click on the icon and then
a live bookmark is created.

Most modern browsers have something like that like FF or IE7.

To make the icon appear, add this directive your page(s).

<LINK rel="alternate" type="application/rss+xml"


title="Real's HowTo" href="http://www.rgagnon.com/feed.xml">

17.22 Validate a RSS feed


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0559.html

To make sure your generated RSS feed is ok, use this very handy site : http://feedvalidator.org/.

It works with RSS 0.90, 0.91, 0.92, 0.93, 0.94, 1.0, 1.1, and 2.0. It also validates Atom feeds.

To use it, simply enter the address of your feed and click Validate. If the validator finds any
problems in your feed, it will give you messages for each type of problem and highlight where the
problem first occurs in your feed. If you're unsure what a message means, click the "help" link next
to the message for a fuller explanation.

17.23 Attach a CSS to RSS feed


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0560.html

17.20.3 RSS−UTIL.TLD
You add a directive to the XML file.

<?xml version="1.0" encoding="utf−8"?>


<?xml−stylesheet title="XSL_formatting" type="text/xsl" href="feed.xsl"?>

<rss version="2.0">
...

then, in the XSL

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="channel">
<html>
<head>
<link title="mystyle" href="howto.css"
type="text/css" rel="stylesheet"/>
<link rel='alternate' type='application/rss+xml'
title="Real's HowTo" href='http://www.rgagnon.com/feed.xml'/>
<title>What's new − Real's HowTo</title>
<script type="text/javascript" src="scripts/rss.js" />
<style>
.box {
border−width: 1px 1px 1px 1px;
border−spacing: 2px;
border−style: solid solid solid solid;
border−color: blue blue blue blue;
border−collapse: separate;
background−color: white;
}
</style>

</head>
<body onload="setURLS();">
<a href='http://www.rgagnon.com/howto.html'
title='Useful code snippets for Java, JS or PB developers!'>
<img src='images/realhowto−left.jpg' border='0' />
</a>
<h2>What's new, the last 10 updates</h2>
<div class="box" align="center">
Copy the URL in the box below into your preferred RSS reader.
New content will be delivered as it's published.

<br/>
<input type="text" size="50" id="rss−url"/>
</div>
<br/>
<xsl:for−each select="item">
<h4><xsl:value−of select="title"/></h4>
<i><xsl:value−of select="pubDate"/></i><br/>
<xsl:value−of select="description"/><br/>
<a HREF="{link}"><xsl:value−of select="link"/></a>
<p/>
</xsl:for−each>
<p/>
<hr/>
<div align="center">
Written and compiled by Real Gagnon ©1998−2007<br/>
[<A HREF="http://www.rgagnon.com/" TARGET="_top"> home </A>]
</div>
</body></html>

17.20.3 RSS−UTIL.TLD
</xsl:template>
</xsl:stylesheet>

See the result.

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

17.20.3 RSS−UTIL.TLD
18 DEPRECATED
18.1 java−deprecated

18.2 * Read me *
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0186.html

These examples works only in a Microsoft JVM and are very Windows−oriented so portabilty here is
not issue.

Microsoft SDK is no longer available. Try to search for the file SDKjava40.exe (20,243,128 bytes) in
Google to find a copy on the Net.

See this related Howto.

18.3 Keep the console open after execution


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0187.html

Call the static method PressAnykey to keep to "DOS" window open.

import java.io.*;
public class IO {
public static void PressAnyKey() {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
System.out.print("Press any key...");
try { input.readLine();}
catch (Exception e) { e.printStackTrace();}
}
}

For example

public class HelloWorld {


public static void main(String[] args) {
System.out.println("Hello world.");
IO.PressAnyKey();
}
}

18.4 Read the Registry


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0188.html

18 DEPRECATED
public class RegistryRead {
public static void main(String[] args) {
RegistryRead demo = new RegistryRead();
demo.doit();
// IO.PressAnyKey();
}

public void doit() {


displayUserName();
displayODBCDSN();
}

public void displayUserName(){


com.ms.wfc.app.RegistryKey regKey;
String userName;
regKey =
com.ms.wfc.app.Registry.LOCAL_MACHINE.getSubKey
("Network\\Logon");
if (regKey == null) {
userName = "Unable to get username from Registry!";
}
else {
userName = (String) regKey.getValue("username");
}
System.out.println("Username : " + userName);
}

public void displayODBCDSN() {


com.ms.wfc.app.RegistryKey regKey;
regKey =
com.ms.wfc.app.Registry.CURRENT_USER.getSubKey
("Software\\ODBC\\ODBC.INI\\ODBC Data Sources");
if (regKey == null) {
System.out.println("Unable to get ODBC DSN Registry!");
}
else {
String dsn [] = regKey.getValueNames();
System.out.println("ODBC DSN defined : ");
for(int i = 0; i < dsn.length; i++) {
System.out.println(dsn[i]);
}
}
}
}

See also this How−to for a solution using the Sun's JVM and the REG utility.

18.5 Call a Win API


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0189.html

Use the @dll.import directive. This is allowed only in Application. In the following example, we are
calling the API to detect the currect user name.

public class TestWinAPI {


public static void main (String[] args) {
// Give us some room,
// let's say 128 characters (MAX 127 + '\0').

18.5 Call a Win API


long[] buffer = { 128 } ;
StringBuffer username= new StringBuffer((int)buffer[0]);
GetUserNameA(username, buffer);
System.out.println("UserName: " + username);
MessageBox(0, "UserName : " + username, "Box issued from Java", 0);
// IO.PressAnyKey();
}

/** @dll.import("ADVAPI32") */
static native void GetUserNameA
(StringBuffer userName, long buffer[]);
// string by ref are passed with a StringBuffer
// basic scalar type by ref are passed via an array

/** @dll.import("USER32") */
private static native int MessageBox
(int hwndOwner, String text,String title, int fuStyle);
}

If an error is returned by the Win32 API called, you can't get the actual error code by calling the
standard getLastError() Win32 API. You must use the special keyword setLastError in the
@dll.import directive to instruct the JVM to keep the error code. Then you retrieve the error code by
calling the getLastWin32Error() method from the DllLib class.

import com.ms.dll.DllLib;

public class TestChangeDirectory {


public static void main (String[] args) {
boolean rc;
// for demonstration
// we specify a non−existent directory, to get an error code...
StringBuffer newdir = new StringBuffer("Unknown directory");
rc = SetCurrentDirectoryA(newdir);
if (!rc) {
int err = DllLib.getLastWin32Error();
// should be rc : 2 "ERROR_FILE_NOT_FOUND"
System.out.println("rc : " + err);
// you may want to throw an exception here...
}
else {
System.out.println("Done.");
}
// keep the console open...
try {System.in.read();}catch(Exception e){}
}

/** @dll.import("KERNEL32",setLastError) */
static native boolean SetCurrentDirectoryA(StringBuffer newdir);
}

NOTE: The example above call the Win32 API to change the current direcotry but you should note that you don't really need to do that. Simply
call the static method setCurrentDirectory() from the File class instead...

To be able to do the same in Applet, you need to sign the Applet then make the following call before
making API calls:

import com.ms.security.*;
...
PolicyEngine.assertPermission(PermissionID.SYSTEM);

Thanks to H. Parvillers for the tip.

18.5 Call a Win API


18.6 Display a BMP image
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0190.html

The standard Java Image object doesn't support the BMP format (only JPG or GIF). While it's
possible to use pure Java classes to let an Image use a BMP−encoded image (see this How−to), in
a Microsoft−oriented environment, it's easier to use the WFC control PictureBox which can display
BMP/, GIF or JPEG images.

In VJ++, create a Windows application. In the Java form, drag the WFC picturebox control and a
button. In the button click event, put the following to call the Win FileOpen dialog to let you select
the image to be displayed.

OpenFileDialog ofd = new OpenFileDialog();


ofd.setDefaultExt("bmp");
ofd.setFilter("BMP images(*.bmp)|*.bmp|JPG images (*.jpg)|*.jpg");
ofd.setFilterIndex(1);
ofd.setInitialDir("c:\\");
int dlgResult = ofd.showDialog();
if (dlgResult == DialogResult.OK) {
pictureBox1.setImage(new Bitmap(ofd.getFileName()));
}

18.7 Play a WAV audio file


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0191.html

import com.ms.win32.Winmm;
import com.ms.win32.wins;

public class WavAudio {


private String wavFile=null;
public WavAudio(String file) {
wavFile=file;
}
public void stop() {
Winmm.PlaySound(null,0,
wins.SND_ASYNC|wins.SND_FILENAME|wins.SND_NOWAIT);
}
public void playAsync() {
stop();
Winmm.PlaySound(wavFile,0,
wins.SND_ASYNC|wins.SND_FILENAME|wins.SND_NOWAIT);
}
public void playSync() {
stop();
Winmm.PlaySound(wavFile,0,
wins.SND_SYNC|wins.SND_FILENAME|wins.SND_NOWAIT);
}

public void loop() {


// stop();

18.6 Display a BMP image


Winmm.PlaySound(wavFile,0,
wins.SND_ASYNC|wins.SND_LOOP|wins.SND_FILENAME|wins.SND_NOWAIT);
}

public static void main(String args[]) {


// for demonstration ...
WavAudio ac =
new WavAudio("c:/windows/media/Chord.wav");
System.out.print("Playing ...");
ac.playSync();
System.out.println("Done...");
}
}

18.8 Detect if the MS JVM is used


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0192.html

While the Microsoft Java Virtual Machine can run "almost" any 100% pure Java classes, the other
way is not true, non−MS JVM are not able to run classes that used Microsoft−specific classes
(com.ms.*). Check this How−to for some techniques to detect Virtual machine in use.

18.9 Get the latest MS JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0386.html

The Microsoft Java Virtual Machine is no longer available from Microsoft directly due to legal
wrangling with Sun, however it still can be downloaded... Check this list of URL's.

See this related Howto.

18.10 Uninstalling the MS JVM


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0509.html

• Execute RunDll32 advpack.dll,LaunchINFSection java.inf,UnInstall


• Reboot
• Delete the java folder within \%systemroot% (such as WINNT or WINDOWS).
• Delete configuration file java.pnf from folder \%systemroot%\inf
• Delete jview.exe and wjview.exe from folder \%systemroot%\system32
• Run Regedit to find and delete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Java VM
registry subkey
• Run Regedit to find and delete HKEY_LOCAL_MACHINE\SOFTWARE \Microsoft\Internet
Explorer\AdvancedOptions\JAVA_VM registry subkey

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

18.8 Detect if the MS JVM is used


Written and compiled by Réal Gagnon ©1998−2005
[ home ]

18.11 Wrap a Java class in a COM object


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0044.html

Use the Microsoft javareg utility to register a java class as a COM server. Once registered, the Java
class will be visible from all languages that can deal with COM objects. I am giving here some
examples in VbScript, JScript, ASP and Powerbuilder.

NOTE: The class can compiled with any JDK but the actual execution will use the Microsoft JVM installed on the system.

The javareg utility is part of the Microsoft Java SDK which can be freely downloaded from the
Microsoft Web site.

First a simple Java class.

[JavaSays.java]

package JavaCom;
public class JavaSays {
public String Hello() {
return "Hello world" ;
}
public String Say(String what) {
return what ;
}
}

Then this BAT file is executed to register our class.

javareg /register /class:JavaCom.JavaSays /progid:JavaCom.JavaSays


md c:\Windows\Java\TrustLib\JavaCom
copy JavaSays.class c:\windows\java\trustlib\javacom

That's it. The system now has a COM object called JavaCom.JavaSays installed.

VbScript and JScript are useful scripting tools. They are now part of a regular Windows installation
(or IE). If your Windows installation is too old, you can download the Windows Scripting Host from
the Microsoft Web site.

[VbScript TestJavaCom.vbs]

' VBSCRIPT connect to a Java COM object


Dim objJava
Set objJava = WScript.CreateObject("JavaCom.JavaSays")

strFromJava = objJava.Hello
MsgBox strFromJava, _
0, _
"JAVA COM OUTPUT"

strFromJava = objJava.Say("Displayed by VbScript via a Java object")


MsgBox strFromJava, _

18.11 Wrap a Java class in a COM object


0, _
"JAVA COM OUTPUT"

[JScript TestJavaCom.js]

// JSCRIPT connect to a Java COM object


var objJava = WScript.CreateObject("JavaCom.JavaSays")
var WSHShell = WScript.CreateObject("WScript.Shell");

strFromJava = objJava.Hello()
WSHShell.Popup(strFromJava,
0,
"JAVA COM OUTPUT",
0 );

strFromJava = objJava.Say("Displayed by JScript via a Java object")


WSHShell.Popup(strFromJava, 0, "JAVA COM OUTPUT", 0 );

[ASP TestJavaCom.asp]

<%
Set objJava = Server.CreateObject("JavaCom.JavaSays")
%>
<BR>
test 1 : <% =objJava.Hello() %><BR>
test 2 : <% =objJava.Say("From ASP via a Java Object") %>

[PowerBuilder]

OLEObject objJava
string strFromjava

objJava = CREATE OLEObject


objJava.ConnectToNewObject("JavaCom.JavaSays")

strFromJava = objJava.Hello()
MessageBox("From PB via JavaCom", strFromJava)

strFromJava = objJava.Say("Displayed by PB via a Java object")


MessageBox("From PB via JavaCom", strFromJava)

DESTROY objjava

18.12 Sign an applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0122.html

This howto is deprecated (old stuff)


You need to obtain a certificate from a trusted source.

A Certificate for developer can be purchased for about $200 (with $100/year to renew it), see
Thawte certification for example. For non US citizen, it can be difficult to obtain a certificate from US
based trusted source, because of the exportation limitation imposed on encryption technique.
Certificates used to sign email are not secured enough to sign applets, they are CLASS 1
certificate, you need something like CLASS 3 to be able to sign an applet.

18.12 Sign an applet


Signing an Applet means signing the JAR containing the Applet. To sign a JAR, you need tools
provided by Netscape. Zigbert is a command−line utility. Also a GUI JAR packager can be used to
sign JARS. You may look at this JAVA How−to for infos about JAR file.

Sun's JAVAKEY utility can't be used to produce/sign certificate/JAR compatible for the Netscape
security manager. Read the Netscape's security FAQ or Netscape OBJECT SIGNING
RESOURCES for more informations.

Once the Applet signed, we must use the netscape.security (also called Capabilities) package to
grant/remove privileges. This package is included with Netscape v4 or can be downloaded from the
Netscape Web site.

When compiling a JAVA source containing references to the Capabilities class, we must adjust to
CLASSPATH to include the JAR java40.jar (with v4).

set CLASSPATH=
.;c:\windev\jdk1.1.3\lib\classes.zip;
c:\program files\netscape\communicator\program\java\classes\java40.jar;

18.13 Bypass the need for a certificate


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0123.html

Netscape provides a way to accept a codebase as trusted (then a certificate is not needed). This
can be useful during development or in a private Intranet. In the Netscape Users directory, there is a
file called prefs.js. Adding the line

user_pref("signed.applets.codebase_principal_support", true);

WILL ENABLEJAR file without a certificate to request privileges on your machine. If you agree, it
will be possible for an Applet to lauch a program, write a file on your hard disk or print on the printer.
You will still have to ask for privileges in your program using the Netscape capabilites classes.

Another way is to lower general security setting to more allow more freedom when running applets
locally. Add or modify the following entries in the prefs.js:

user_pref("unsigned.applets.low_security_for_local_classes", true);
user_pref("signed.applets.local_classes_have_30_powers", true);
user_pref("signed.applets.low_security_for_local_classes", true);
user_pref("signed.applets.verbose_security_exception", true);

Then you don't need to asked for privileges for local classes.

NOTE: When adding or modifying the file prefs.js, Netscape must not be running because your modification will be overwritten. So shut down
Netscape, edit the prefs.js and then restart Netscape.

With IE, you can achieve the same thing through the Internet option menu.

Internet Options
Security Tab
Internet Custom level
Java permissions
Custom radio buttons

18.13 Bypass the need for a certificate


Java Custom settings
select the permissions given to unsigned content.

Be careful with this because this can be a huge security breach.

18.14 Start an executable on the client


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0124.html

(with Netscape capabilities classes)

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import netscape.security.*;

public class LauchNotepad extends Applet


implements ActionListener {
Button lauchButton;
TextField filename;
String browserName;
boolean securitySupported = false;

public void init() {


setLayout(new FlowLayout());
Label label =
new Label("Lauch notepad with the specified file");
add(label);
lauchButton = new Button("call NOTEPAD");
add(lauchButton);
lauchButton.addActionListener(this);
filename = new TextField(20);
add(filename);
browserName = System.getProperty("java.vendor");
if (browserName.indexOf("Netscape") > −1)
securitySupported = true;
setSize(200, 200);
}

public void actionPerformed(ActionEvent evt) {


if (evt.getSource() == lauchButton) {
if (securitySupported) {
PrivilegeManager.enablePrivilege("UniversalExecAccess");
try {
Runtime.getRuntime().exec("notepad.exe " + filename.getText());
}
catch(Exception e) {
e.printStackTrace();
}
}
else {
getAppletContext().showStatus("security not installed");
}
}
}
}

18.14 Start an executable on the client


18.15 Get rid of the message "Warning − unsigned applet
window"
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0125.html

Before opening the new Frame or Window, use (with Netscape capabilities classes)

PrivilegeManager.enablePrivilege("UniversalTopLevelWindow");

18.16 Read/write a local file from an Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0126.html

(with Netscape capabilities classes)

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import netscape.security.*;

public class FileAccess extends Applet


implements ActionListener {
Button loadButton, saveButton;
TextField filename;
TextArea content;
String browserName;
boolean securitySupported = false;

public void init() {


setLayout(new FlowLayout());
Label label =
new Label("Simple file editor");
add(label);
loadButton = new Button("Load");
saveButton = new Button("Save");
add(loadButton);
add(saveButton);
loadButton.addActionListener(this);
saveButton.addActionListener(this);
filename = new TextField(20);
add(filename);
content = new TextArea(5,20);
add(content);
browserName = System.getProperty("java.vendor");
if (browserName.indexOf("Netscape") > −1)
securitySupported = true;
setSize(200, 200);
}

public void actionPerformed(ActionEvent evt) {


if (securitySupported) {
if (evt.getSource() == saveButton) {
PrivilegeManager.enablePrivilege("UniversalFileAccess");
try {

18.15 Get rid of the message "Warning − unsigned applet window"


FileWriter aWriter = new FileWriter(filename.getText(), false);
aWriter.write(content.getText());
aWriter.flush();
aWriter.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
else if (evt.getSource() == loadButton) {
PrivilegeManager.enablePrivilege("UniversalFileAccess");
try {
BufferedReader aReader =
new BufferedReader
(new FileReader(filename.getText()));
content.setText(aReader.readLine());
aReader.close();
}
catch(Exception e) {
e.printStackTrace();
}
}

else {
getAppletContext().showStatus("security not installed");
}
}
}
}

18.17 Write "other−browser−friendly" code when using the


Netscape Capabilities package
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0127.html

Use a combination of try/catch when enabling a privilege.

try {
try {
netscape.security.PrivilegeManager.enablePrivilege
("UniversalTopLevelWindow");
}
catch(netscape.security.ForbiddenTargetException e) {
}
}
catch(NoSuchMethodError e) {
/*
** add here code required by IE or
** any other supported browser
*/
}

18.17 Write "other−browser−friendly" code when using the Netscape Capabilities package
18.18 Disable the JIT compiler in Netscape or IE
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0155.html

When a JIT is active, Exception don't output the line number where the exception occurs. To
retrieve line numbers, simply disable the JIT compiler. With Microsoft IE, simply check the option in
the Preferences Dialog. With Netscape v4, rename the DLL jit3240.dll in the directory
program/java/bin.

In application, with the Sun JVM, you have the following options:

java −Djava.compiler=NONE myapp


or
SET JAVA_COMPILER=NONE (Set the environment variable JAVA_COMPILER)
java myapp
or
JAVA −NOJIT MYAPP

With the MS JVM, you set the environment variable MSJAVA_ENABLE_JIT to 0 to disable the
Microsoft JIT, or use the Registry key

HKEY_CURRENT_USER\Software\Microsoft\Java VM\EnableJIT

a value of 0 (dword) will disable the JIT.

With the latest JVM this is not necessarily true. To retrieve the line numbers, make sure that the
classes are compiled with the debugging infos.

−g Generate all debugging info


−g:none Generate no debugging info
−g:{lines,vars,source} Generate only some debugging info

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

18.19 Start automatically JAVA when opening Netscape


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0156.html

Go into the properties Tab panel of the Netscape icon and specify that you want to start Netscape
with the option −start_java.

For example:

"C:\PROGRAM FILES\NETSCAPE\COMMUNICATOR\PROGRAM\NETSCAPE.EXE" −START_JAVA

18.18 Disable the JIT compiler in Netscape or IE


18.20 Use Netscape Java Console hidden commands
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0152.html

Netscape Java Console Commands:

?: help
b: break into the debugger (Windows only)
c: clear console window
d: dump applet context state to console
f: finalize objects on finalization queue
g: garbage collect
h: print this help message
l: capture all classes loaded by an applet to a directory
m: print current memory use to console
q: hide console
s: dump memory summary to "memory.out"
t: dump thread info to "memory.out"
x: dump memory to "memory.out"
X: dump memory (detailed) to "memory.out"
0−9: set applet debug level to <n>

18.21 Avoid the Netscape "Couldn't connect to '' with origin


from 'local−classpath−classes'" message.
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0162.html

In Windows, open a DOS window, go to the directory where the HTML file is located. Type

SET CLASSPATH=

and then

START MYPAGE.HTML

18.22 Post a message on a newsserver using NNTP protocol


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0087.html

This snippet uses an undocumented Sun package [JDK1.1]

import sun.net.nntp.*;
import java.io.*;

public class NntpPost {


public static void main(String[] args) throws IOException {
/*
** pass your news server as parameter
** eg. java NttpPost news.server.com
*/

18.20 Use Netscape Java Console hidden commands


NntpClient c = new NntpClient(args[0]);
NewsgroupInfo ni = c.getGroup("alt.test");
PrintStream p = c.startPost();
System.out.println("Starting post at " + args[0] + "...");
p.println("From: epresley@jailhouse.rock (Elvis Presley)");
p.println("Newsgroups: alt.test");
p.println("Subject: I'm alive");
p.println("");
p.println("Hi");
p.println("Don't be cruel, please help me");
p.println(" ");
p.println("Thanks in advance");
if (c.finishPost())
System.out.println("Ending post... success");
else
System.out.println("Ending post... failed");
c.closeServer();
}
}

Here some java code to illustrate NTTP protocol without using the undocumented classes,
Communicating with an NNTP server.

Sun's JavaMail APi can be used to interact with a NTTP server, check out the Knife Plugin.

18.23 Read messages from a newsserver


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0088.html

This snippet uses an undocumented Sun package [JDK1.1]

import sun.net.nntp.*;
import java.io.*;

public class NntpGetGroup {


public static void main(String[] args)
throws IOException {
/*
** pass your news server, newsgroup as parameter
** eg. java NttpPost news.server.com alt.test
*/
NntpClient c = new NntpClient(args[0]);
c.setGroup(args[1]);
NewsgroupInfo ni = c.getGroup(args[1]);
int first = ni.firstArticle;
int last = ni.lastArticle;
for (int i = first; i <= last; i++) {
String aLine;
BufferedReader br = null;
InputStream anArticle = null;
try {
anArticle = c.getArticle(i);
br = new BufferedReader(new InputStreamReader(anArticle));
System.out.println("−−−−−−−−−−−−−−−−−\nArticle " + i);
while ((aLine = br.readLine()) != null) {
System.out.println(aLine);
}
}

18.23 Read messages from a newsserver


catch (NntpProtocolException e) {
/*
** probably a cancelled article, just skip it
*/
}
}
}
}

18.24 Get a list of headers from a newsgroup


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0089.html

This snippet uses an undocumented Sun package [JDK1.1]

import sun.net.nntp.*;
import java.io.*;

public class NntpHeader {


public static void main(String[] args)
throws IOException {
/*
** pass your news server as parameter
** eg. java NttpPost news.server.com
*/
NntpClient c = new NntpClient(args[0]);
String newsgroup = "alt.test";
c.setGroup(newsgroup);
NewsgroupInfo ni = c.getGroup(newsgroup);
int first = ni.firstArticle;
int last = ni.lastArticle;
for (int i = first; i <= last; i++) {
try {
InputStream theHeader = c.getHeader(i);
BufferedReader br = new BufferedReader(new
InputStreamReader(theHeader));
String theLine;
System.out.println("−−−−−−−−−−−−−−−−−\nHeader " + i + "/" + last);
while ((theLine = br.readLine()) != null)
System.out.println(theLine);
}
catch (NntpProtocolException ne) {
/*
** probably a cancelled article, just skip it
*/
}
}
}
}

18.25 Get a list of all available newsgroup from a newsserver


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0090.html

This snippet uses an undocumented Sun package [JDK1.1]

18.24 Get a list of headers from a newsgroup


import sun.net.nntp.*;
import sun.net.*;
import java.io.*;
import java.util.*;

public class ListGroups extends NntpClient {


public static void main(String[] args) {
String server = "news";
try {
System.out.println("opening server");
NntpClient nc = new NntpClient(server);
System.out.println("asking for help");
nc.serverOutput.println("HELP");
String theLine = "";
DataInputStream dis = new DataInputStream(nc.serverInput);
while ((theLine = dis.readLine()) != null) {
if (theLine.equals(".")) break;
System.out.println(theLine);
}
nc.askServer("QUIT");
nc.closeServer();
}
catch (IOException e) {
System.err.println(e);
}
}
}

18.26 Detect if Swing is installed


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0194.html

public class SwingSniffer extends java.applet.Applet {


public void init() {
try {
com.sun.java.swing.JButton dummy =
new com.sun.java.swing.JButton("foo");
System.out.println("Swing is here");
// getAppletContext().showDocument
// (new URL(getCodeBase()+"AppletPageWithNoArchiveTag.html"));
}
catch(Exception e) {
System.out.println
("Swing is not here, you must download or install it");
// getAppletContext().showDocument
// (new URL(getCodeBase()+"AppletPageWithArchiveTag.html"));
}
}
}

<HTML><HEAD></HEAD><BODY>
<APPLET CODE="SwingSniffer.class"
HEIGHT=1 WIDTH=1>
<A HREF="/nojava.html">
Oups! You don't have JAVA enabled, click here.</A>
</APPLET>
/BODY/HTML

18.26 Detect if Swing is installed


18.27 Make Swing always available from Netscape
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0195.html

To be able use Swing classes (without download delay) from Netscape, copy Swing JAR files
(swingall.jar) in the PLUGINS directory and restart Netscape. This is ok with pre−Java 2 Swing.
With that version you need the Java plug−in to be able to use the swing classes.

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

18.27 Make Swing always available from Netscape


19 String/Number
19.1 java−stringnumber

19.2 * Read me *
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0290.html

If you can't find what you are looking here, you may want to look at these other sites :

Java Glossary
The Java Developers Almanac 1.4 (exampledepot.com)
Sun Developers Online Community

Also check out my Java links page.

Usenet's newgroups are very useful too. Check out the comp.lang.java.* groups on your favorite
Usenet newserver.

Specialized server from vendors can be accessed to obtain support :

• forums.sybase.com

Easerver and Powerbuilder


• news.gmane.org

Netbeans, look for the hierarchy gmane.comp.java.netbeans.*


• news.eclipse.org

Eclipse, need to ask for username first at http://www.eclipse.org/newsgroups/register.php.


• news.mozilla.org

Mozilla
• msnews.microsoft.com

Microsoft
• news.software.ibm.com

IBM (WebSphere)
• newsgroups.bea.com

BEA WebLogic

19 String/Number
19.3 Convert from type X to type Y
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0004.html

integer to String :

int i = 42;
String str = Integer.toString(i);
or
String str = "" + i

double to String :

String str = Double.toString(i);

long to String :

String str = Long.toString(l);

float to String :

String str = Float.tString(f);

String to integer :

str = "25";
int i = Integer.valueOf(str).intValue();
or
int i = Integer.parseInt(str);

String to double :

Double d = Double.valueOf(str).doubleValue();

String to long :

long l = Long.valueOf(str).longValue();
or
Long L = Long.parseLong(str);

String to float :

Float f = Float.valueOf(str).floatValue();

decimal to binary :

int i = 42;
String bin = Integer.toBinaryString(i);

decimal to hexadecimal :

19.3 Convert from type X to type Y


int i = 42;
String hexstr = Integer.toString(i, 16);

or
String hexstr = Integer.toHexString(i);

or (with leading zeroes and uppercase)


public class Hex {
public static void main(String args[]){
int i = 42;
System.out.print
(Integer.toHexString( 0x10000 | i).substring(1).toUpperCase());
}
}

Byte array to hexadecimal string:


See this How−to

hexadecimal (String) to integer :

int i = Integer.valueOf("B8DA3", 16).intValue();


or
int i = Integer.parseInt("B8DA3", 16);

ASCII code to String

int i = 64;
String aChar = new Character((Char)i).toString();

integer to ASCII code (byte)

char c = 'A';
int i = (int) c; // i == 65 DECIMAL

To extract Ascii codes from a String

String test = "ABCD";


for ( int i = 0; i <test.length(); ++i ) {
char c = test.charAt( i );
int j = (int) c;
System.out.println(j);
}

integer to boolean

b = (i != 0);
// ex : 42 != 0 −−> true

boolean to integer

i = (b)?1:0;
// true −−> 1

19.3 Convert from type X to type Y


Note :To catch illegal number conversion, try using the try/catch mechanism.

try{
i = Integer.parseInt(aString);
}
catch(NumberFormatException e) {
...
}

19.4 Strip certain characters from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0018.html

This example keeps only a given set of accepted characters.

public class StringUtils {


public static void main(String args[]) {
System.out.println
(StringUtils.stripGarbage("A good String"));
System.out.println
(StringUtils.stripGarbage("String with !%garbage &*("));
/*
output :
A good String
String with garbage
*/
}

public static String stripGarbage(String s) {


String good =
" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String result = "";
for ( int i = 0; i < s.length(); i++ ) {
if ( good.indexOf(s.charAt(i)) >= 0 )
result += s.charAt(i);
}
return result;
}
}

NOTE: You may want to look at How−to optimize string operations

The following snippet will strip or keep from a given string the specified characters.

Thanks to T. GUIRADO for the idea

public class StringUtils {


/**
* @param s source string
* @param toMatch target character(s)
* @param boolean true=keep false=strip
**/
public static String cleanUp
( String s, String sToMatch, boolean isToKeep ) {
final int size = s.length();
StringBuffer buf = new StringBuffer( size );
if ( ! isToKeep ) {

19.4 Strip certain characters from a String


for ( int i = 0; i < size; i++ ){
if ( sToMatch.indexOf(s.charAt(i) ) == −1 ){
buf.append( s.charAt(i) );
}
}
}
else {
for ( int i = 0; i < size; i++ ){
if ( sToMatch.indexOf(s.charAt(i) ) != −1 ){
buf.append( s.charAt(i) );
}
}
}
return buf.toString();
}

public static void main(String args[]) {


System.out.println(cleanUp("realhowGARBhowtoAGE", "GARBAGE", false));
System.out.println(cleanUp("THISrealIShowtoGOOD", "THISISGOOD", true));
/*
* output :
* realhowhowto
* THISISGOOD
*/
}

19.5 Replace/remove character in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0030.html

To replace all occurences of a given character :

String tmpString = myString.replace( '\'', '*' );


System.out.println( "Original = " + myString );
System.out.println( "Result = " + tmpString );

To replace a character at a specified position :

public static String replaceCharAt(String s, int pos, char c) {


return s.substring(0,pos) + c + s.substring(pos+1);
}

To remove a character :

public static String removeChar(String s, char c) {


String r = "";
for (int i = 0; i < s.length(); i ++) {
if (s.charAt(i) != c) r += s.charAt(i);
}
return r;
}

To remove a character at a specified position:

public static String removeCharAt(String s, int pos) {

19.5 Replace/remove character in a String


return s.substring(0,pos)+s.substring(pos+1);
}

Check this Optimize How−to for a more efficient String handling technique.

New with JDK1.4, the String class offers the replaceAll() method that can be used with String or
char.

String.replaceAll("\n", ""); // Remove all \n


String.replaceAll("\n", "\r"); // Replace \n by \r

Thanks to jsanza for the tip!

19.6 Replace every occurences of a string within a string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0320.html

Since Java String are immutable (can't be changed), we return a new String.

public static String replace (String target, String from, String to) {
// target is the original string
// from is the string to be replaced
// to is the string which will used to replace
// returns a new String!
int start = target.indexOf(from);
if (start == −1) return target;
int lf = from.length();
char [] targetChars = target.toCharArray();
StringBuffer buffer = new StringBuffer();
int copyFrom = 0;
while (start != −1) {
buffer.append (targetChars, copyFrom, start−copyFrom);
buffer.append (to);
copyFrom = start + lf;
start = target.indexOf (from, copyFrom);
}
buffer.append (targetChars, copyFrom, targetChars.length − copyFrom);
return buffer.toString();
}

The String.replaceAll() method can also be used. You need to provide a regular expression.

[JDK1.4]

public class Test{


public static void main(String[] args){
String text = "hello world from www.rgagnon.com : hello world";

System.out.println
(text.replaceAll("(?:hello world)+", "bonjour le monde"));

System.out.println
(text.replaceFirst("(?:hello world)+", "bonjour le monde"));

/*
output :

19.6 Replace every occurences of a string within a string


bonjour le monde from www.rgagnon.com : bonjour le monde
bonjour le monde from www.rgagnon.com : hello world
*/
}
}

Keep in mind, that you need to escape characters like $ or | since they have special meaning when
used in a regular expression.

19.7 "Tokenize" a string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0015.html

StringTokenizer st =
new StringTokenizer
("This is the string to be tokenized", " ");

while(st.hasMoreTokens()){
String s=st.nextToken();
System.out.println(s);
}

/*
output is :
This
is
the
string
to
be
tokenized
*/

StringTokenizer does not react correctly if you have two separators consecutively.

Here an enhanced StringTokenizer (thanks to jsanza) to deal with that :

import java.util.*;
/**
* This class wraps a standard java.util.StringTokenizer, but provides
* an additional mode of operation (NO_CONSECUTIVE_DELIMS).
*
*/
public class EnhancedStringTokenizer implements Enumeration {
public static final int NO_RETURN_DELIMS = 0;
public static final int RETURN_DELIMS = 1;
public static final int NO_CONSECUTIVE_DELIMS = 2;
protected int Mode = NO_CONSECUTIVE_DELIMS;

void setMode(int mode) {


Mode = mode;
}

public int getMode() {


return Mode;
}

19.7 "Tokenize" a string


// default delimiter in the StringTokenizer
protected String Delimiter = " \t\n\r\f";
protected void setDelimiter(String delim){
Delimiter = delim;
}

public String getDelimiter() {


return Delimiter;
}

protected String Remainder = "";


protected void setRemainder(String str) {
Remainder = str;
}

public String getRemainder() {


return Remainder;
}

protected java.util.StringTokenizer st = null;


/**
* Same as the StringTokenizer constructor. No added functionality.
*/
public EnhancedStringTokenizer(String str) {
setMode(this.NO_RETURN_DELIMS);
st = new StringTokenizer(str);
}

/**
* Same as the StringTokenizer constructor. No added functionality.
*/
public EnhancedStringTokenizer(String str, String delim){
setMode(this.NO_RETURN_DELIMS);
setDelimiter(delim);
st = new StringTokenizer(str, delim);
}

/**
* Same as the StringTokenizer constructor. No added functionality.
*/
public EnhancedStringTokenizer
(String str, String delim, boolean returnDelims) {
if (returnDelims) {
setMode(RETURN_DELIMS);
}
else {
setMode(NO_RETURN_DELIMS);
}
setDelimiter(delim);
st = new StringTokenizer(str, delim, returnDelims);
}

/**
* Using this constructor allows use of the NO_CONSECUTIVE_DELIMS mode
* of operation.
*/
public EnhancedStringTokenizer(String str, String delim, int mode) {
setMode(mode);
setDelimiter(delim);

19.7 "Tokenize" a string


switch (getMode()) {
case NO_RETURN_DELIMS :
st = new StringTokenizer(str, delim, false);
break;
case RETURN_DELIMS :
st = new StringTokenizer(str, delim, true);
break;
case NO_CONSECUTIVE_DELIMS :
default :
init(str);
break;
}
}

void init(String str) {


setRemainder(str);
}

public int countTokens() {


switch (getMode()) { {
case NO_CONSECUTIVE_DELIMS :
{
String oldRem = getRemainder();
int count = 0;
try {
String temp;
while (true) {
temp = nextToken();
count++;
}
}
catch (NoSuchElementException nsee) {
setRemainder(oldRem);
return count;
}
}
default :
return st.countTokens();
}
}

public boolean hasMoreElements() {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != −1) {
return true;
}
else {
if (getRemainder().length() > 0) {
return true;
}
else {
return false;
}
}
default :
return st.hasMoreElements();
}
}

19.7 "Tokenize" a string


public Object nextElement() throws NoSuchElementException {
switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != −1) {
String retValue =
getRemainder().substring(0, intIndex);
setRemainder(getRemainder().substring(intIndex + 1));
return retValue;
}
else {
if (getRemainder().length() > 0) {
String retValue = getRemainder();
setRemainder("");
return retValue;
}
else {
throw new NoSuchElementException();
}
}
default :
return st.nextElement();
}
}

public boolean hasMoreTokens() {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != −1) {
return true;
}
else {
if (getRemainder().length() > 0) {
return true;
}
else {
return false;
}
}
default :
return st.hasMoreElements();
}
}

public String nextToken() throws NoSuchElementException {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
int intIndex = 0;
intIndex =
getRemainder().indexOf(getDelimiter(), intIndex);
if (intIndex != −1) {
String retValue =
getRemainder().substring(0, intIndex);
setRemainder(getRemainder().substring(intIndex + 1));
return retValue;
}
else {
if (getRemainder().length() > 0) {

19.7 "Tokenize" a string


String retValue = getRemainder();
setRemainder("");
return retValue;
}
else {
throw new NoSuchElementException();
}
}
default :
return st.nextToken();
}
}

public String nextToken(String delim) throws NoSuchElementException {


switch (getMode()) {
case NO_CONSECUTIVE_DELIMS :
setDelimiter(delim);
return nextToken();
default :
return st.nextToken(delim);
}
}

public static void main(String a[]) {


String testStr = "|One|Two|Three||Five";
EnhancedStringTokenizer st =
new EnhancedStringTokenizer(
testStr,
"|",
EnhancedStringTokenizer.NO_CONSECUTIVE_DELIMS);
while (st.hasMoreTokens()) {
String aux = st.nextToken();
System.out.print(aux.length());
System.out.println("−>"+aux+"<−");
}
}
}

19.8 Split a string using String.split()


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0438.html

[JDK1.4]

public class StringSplit {


public static void main(String args[]) throws Exception{
new StringSplit().doit();
}

public void doit() {


String s3 = "Real−How−To";
String [] temp = null;
temp = s3.split("−");
dump(temp);
}

public void dump(String []s) {

19.8 Split a string using String.split()


System.out.println("−−−−−−−−−−−−");
for (int i = 0 ; i < s.length ; i++) {
System.out.println(s[i]);
}
System.out.println("−−−−−−−−−−−−");
}
}

/*
output :
−−−−−−−−−−−−
Real
How
To
−−−−−−−−−−−−
*/

split() is based on regex expression, a special attention is needed with some characters which have
a special meaning in a regex expression.

For example :

String s3 = "Real.How.To";
...
temp = s3.split("\\.");

or

String s3 = "Real|How|To";
...
temp = s3.split("\\|");

The special character needs to be escaped with a "\" but since "\" is also a special character in
Java, you need to escape it again with another "\" !

Some notes from A. Gonzales about String.Split()

An interesting thing about String.split():

" s".split(" ") −> {"","","s"}


"".split("" ) −> {""}
" ".split(" ") −> {} (!)
" ".split(" ") −> {} (!)
" s ".split(" ") −> {"","","s"} (!)

Is important to note that an invocation like:

param = req.getParam(...);
String[] words = param.split(" ");
String firstWord = words[0];

will generate a NullPointerException if param.equals(" ").

Using split() with a space can be a problem. Consider the following :


public class StringSplit {
public static void main(String args[]) throws Exception{
new StringSplit().doit();
}

19.8 Split a string using String.split()


public void doit() {
// extra spaces
String s3 = "Real How To";
String [] temp = null;
temp = s3.split(" ");
dump(temp);
}

public void dump(String []s) {


System.out.println("−−−−−−−−−−−−");
for (int i = 0 ; i < s.length ; i++) {
System.out.println(s[i]);
}
System.out.println("−−−−−−−−−−−−");
}
}
/*
output :
−−−−−−−−−−−−
Real

How
To
−−−−−−−−−−−−
*/

We have an extra element. The fix is to specify a regular expression to match one or more spaces.

public class StringSplit {


public static void main(String args[]) throws Exception{
new StringSplit().doit();
}

public void doit() {


// extra spaces
String s3 = "Real How To";
String [] temp = null;
temp = s3.split("\\s+");
dump(temp);
}

public void dump(String []s) {


System.out.println("−−−−−−−−−−−−");
for (int i = 0 ; i < s.length ; i++) {
System.out.println(s[i]);
}
System.out.println("−−−−−−−−−−−−");
}
}
/*
output :
−−−−−−−−−−−−
Real
How
To
−−−−−−−−−−−−
*/

Since String.split() is based on regular expression, you can make some complex operations with a
simple call!
public class StringSplit {
public static void main(String args[]) throws Exception{

19.8 Split a string using String.split()


new StringSplit().doit();
}

public void doit() {


String s3 = "{RealHowto}{java−0438.html}{usage of String.split()}";
String[] temp = s3.split("[{}]");
dump(temp);
}

public void dump(String []s) {


System.out.println("−−−−−−−−−−−−");
for (int i = 0 ; i < s.length ; i++) {
System.out.println(s[i]);
}
System.out.println("−−−−−−−−−−−−");
}
}

/*
output :
−−−−−−−−−−−−

RealHowto

java−0438.html

usage of String.split()
−−−−−−−−−−−−
note : extra element with empty string :−(
*/

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

19.9 Optimize String operations


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0129.html

(thanks to B. Wilkinson)
String concatenation via the "+" operator is one of the most convenient things to do in Java. It is
also one of the most expensive, in terms of memory and performance.

When the compiler sees

String s = "abc" + someint + somearray[index];

or any other concatenation, it **ACTUALLY** generates (for runtime use) the code sequence that
follows (or, at least, the bytecode equivalent of it):

StringBuffer temp = new StringBuffer( );


temp.append( String.valueOf( "abc" ) );
temp.append( String.valueOf( someInt ) );
temp.append( String.valueOf( someArray[index] );
String s = temp.toString( );

19.9 Optimize String operations


The weak spot in all this is the construction of the StringBuffer object: the size of the buffer is
ALWAYS 16 characters. Then, as data is appended to the buffer, if more space is needed the size
of the buffer is doubled and the old data is copied to the new buffer.

So to optimize we have to bypass the automatic StringBuffer when possible. In this JAVA How−to, a
snippet is given to replace a character at a specific position. An optimized version, using the
StringBuffer would be:

public static String replaceCharAt(String s, int pos, char c) {


StringBuffer buf = new StringBuffer( s );
buf.setCharAt( pos, c );
return buf.toString( );
}

Only one buffer created, exactly the right size. Converting a StringBuffer to a String costs almost
nothing, as the actual buffer is shared between the two.

In the same How−to, a snippet about removing a character in a String can be optimized like:

public static String removeChar(String s, char c) {


StringBuffer r = new StringBuffer( s.length() );
r.setLength( s.length() );
int current = 0;
for (int i = 0; i < s.length(); i ++) {
char cur = s.charAt(i);
if (cur != c) r.setCharAt( current++, cur );
}
return r.toString();
}

In the original version, a new String object was created and discarded immediately!

The weak spot of the original method to remove a character is when the parameter s passed havee
than 17 characters, the temporary StringBuffer created by the compiler will have to be extended. To
optimize, simply rewrite the method using a StringBuffer with the correct size:

public static String removeCharAt(String s, int pos) {


StringBuffer buf = new StringBuffer( s.length() − 1 );
buf.append( s.substring(0,pos) ).append( s.substring(pos+1) );
return buf.toString();
}

Check this nice article about String/StringBuffer optimization.

19.10 Remove spaces from a string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0352.html

Remove all spaces

public String removeSpaces(String s) {


StringTokenizer st = new StringTokenizer(s," ",false);
String t="";
while (st.hasMoreElements()) t += st.nextElement();

19.10 Remove spaces from a string


return t;
}

[JDK1.5]
The String trim() method returns a copy of the string, with leading and trailing whitespace omitted.

ref : http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#trim()

[JDK1.4]
Here a complete solution to remove leading or trailing spaces in a String using regular expressions.

import java.util.regex.*;

public class BlankRemover


{

/* remove leading whitespace */


public static String ltrim(String source) {
return source.replaceAll("^\\s+", "");
}

/* remove trailing whitespace */


public static String rtrim(String source) {
return source.replaceAll("\\s+$", "");
}

/* replace multiple whitespaces between words with single blank */


public static String itrim(String source) {
return source.replaceAll("\\b\\s{2,}\\b", " ");
}

/* remove all superfluous whitespaces in source string */


public static String trim(String source) {
return itrim(ltrim(rtrim(source)));
}

public static String lrtrim(String source){


return ltrim(rtrim(source));
}

public static void main(String[] args){


String oldStr =
"> <1−2−1−2−1−2−1−2−1−2−1−−−−−2−1−2−1−2−1−2−1−2−1−2−1−2> <";
String newStr = oldStr.replaceAll("−", " ");
System.out.println(newStr);
System.out.println(ltrim(newStr));
System.out.println(rtrim(newStr));
System.out.println(itrim(newStr));
System.out.println(lrtrim(newStr));
}

Thanks to jsanza for the tip!

19.10 Remove spaces from a string


19.11 Test if a String starts with a digit or uppercase letter
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0430.html

With JDK1.4, regex expression can be handled directly.

import java.util.regex.Pattern;

boolean startsWithDigitOrUpper(String s) {
return Pattern.compile("^[A−Z0−9]").matcher(s).find();
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.12 Get InputStream from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0442.html

public static final String ENCODING = "UTF8"; // see note

public static InputStream fromString(String str) {


byte[] bytes = str.getBytes(ENCODING);
return new ByteArrayInputStream(bytes);
}

Note : List of supported encodings here

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.13 Easy String padding


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0448.html

/**
** pad a string S with a size of N with char C
** on the left (True) or on the right(flase)
**/
public synchronized String paddingString
( String s, int n, char c , boolean paddingLeft ) {
StringBuffer str = new StringBuffer(s);
int strLength = str.length();
if ( n > 0 && n > strLength ) {
for ( int i = 0; i <= n ; i ++ ) {
if ( paddingLeft ) {
if ( i < n − strLength ) str.insert( 0, c );

19.11 Test if a String starts with a digit or uppercase letter


}
else {
if ( i > strLength ) str.append( c );
}
}
}
return str.toString();
}

Thanks to Thierry GUIRADO for this snippet.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.14 Replace \r\n with the <br> tag


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0454.html

This can be done easily a regular expression.

[JDK1.4]

import java.util.regex.Pattern;
import java.util.regex.Matcher;

...
// 4 different combinaisons
Pattern CRLF = Pattern.compile("(\r\n|\r|\n|\n\r)");
Matcher m = CRLF.matcher(myString);

if (m.find()) {
newString = m.replaceAll("<br>");
}

or use the String.replaceAll(regex,replacement) method which is doing basically the same thing.

newString = myString.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.15 Unaccent letters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0456.html

The following snippet removes from a String accentued letters and replace them by their regular
ASCII equivalent.

19.14 Replace \r\n with the <br> tag


This can be useful before inserting data into a database to made sorting easier.

Technique 1
It's a simple using the sun.text.Normalizer class. However, since the class is in sun.* package, it is
considered outside of the Java platform, can be different across OS platforms (Solaris, Windows,
Linux, Macintosh, etc.) and can change at any time without notice with SDK versions (1.2, 1.2.1,
1.2.3, etc). In general, writing java programs that rely on sun.* is risky: they are not portable, and
are not supported.

For an alternative to the sun.text.Normalizer class, you may to take a look at IBM's ICU4J project on SourceForge.

We are calling the normalize() with the option DECOMP (for decomposition, see Unicode
Normalization). So if we pass à, the method returns a + ` . Then using a regular expression, we
clean up the string to keep only valid US−ASCII characters.

JDK1.4

import sun.text.Normalizer;

public class Accent {


public static String value = "é à î _ @";

public static void main(String args[]) throws Exception{


System.out.println(formatString(value));
// output : e a i _ @
}

public static String formatString(String s) {


String temp = Normalizer.normalize(s, Normalizer.DECOMP, 0);
return temp.replaceAll("[^\\p{ASCII}]","");
}

A note from ajmacher:

The Normalizer API changed in JDK6... it can now be found in java.text.Normalizer and its usage is
slightly different (but enough to break it), so Technique 1 will cause compiler errors in JDK6. Try :

java.text.Normalizer.normalize(s, java.text.Normalizer.Form.NFD);

Technique 2
As an alternative, replaceAll() and regular expressions on a String can also be used :

public class Test {


public static void main(String args[]) {
String s = "È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô";

s = s.replaceAll("[èéêë]","e");
s = s.replaceAll("[ûù]","u");
s = s.replaceAll("[ïî]","i");
s = s.replaceAll("[àâ]","a");
s = s.replaceAll("Ô","o");

s = s.replaceAll("[ÈÉÊË]","E");
s = s.replaceAll("[ÛÙ]","U");
s = s.replaceAll("[ÏÎ]","I");
s = s.replaceAll("[ÀÂ]","A");

19.14 Replace \r\n with the <br> tag


s = s.replaceAll("Ô","O");

System.out.println(s);
// output : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o
}
}

Technique 3
While the two techniques above are ok... there are a little bit slow.

The following HowTo is faster because we using one String to contain all the possible characters to
be converted and a String with the ASCII equivalent. So we need to detect the position in the first
String and then do a lookup in the second String.

public class AsciiUtils {


private static final String PLAIN_ASCII =
"AaEeIiOoUu" // grave
+ "AaEeIiOoUuYy" // acute
+ "AaEeIiOoUuYy" // circumflex
+ "AaOo" // tilde
+ "AaEeIiOoUuYy" // umlaut
+ "Aa" // ring
+ "Cc" // cedilla
;

private static final String UNICODE =


"\u00C0\u00E0\u00C8\u00E8\u00CC\u00EC\u00D2\u00F2\u00D9\u00F9"
+"\u00C1\u00E1\u00C9\u00E9\u00CD\u00ED\u00D3\u00F3\u00DA\u00FA\u00DD\u00FD"
+"\u00C2\u00E2\u00CA\u00EA\u00CE\u00EE\u00D4\u00F4\u00DB\u00FB\u0176\u0177"
+"\u00C3\u00E3\u00D5\u00F5"
+"\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF"
+"\u00C5\u00E5"
+"\u00C7\u00E7"
;

// private constructor, can't be instanciated!


private AsciiUtils() { }

// remove accentued from a string and replace with ascii equivalent


public static String convertNonAscii(String s) {
StringBuffer sb = new StringBuffer();
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
int pos = UNICODE.indexOf(c);
if (pos > −1){
sb.append(PLAIN_ASCII.charAt(pos));
}
else {
sb.append(c);
}
}
return sb.toString();
}

public static void main(String args[]) {


String s =
"The result : È,É,Ê,Ë,Û,Ù,Ï,Î,À,Â,Ô,è,é,ê,ë,û,ù,ï,î,à,â,ô,ç";
System.out.println(AsciiUtils.convertNonAscii(s));
// output :
// The result : E,E,E,E,U,U,I,I,A,A,O,e,e,e,e,u,u,i,i,a,a,o,c

19.14 Replace \r\n with the <br> tag


}
}

Thanks to MV Bastos for the "tilde" bug fix!

19.16 Apply a mask to String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0457.html

JDK1.4

public class TestMF {


public static String value = "A1234B567Z";
public static String mask = "A−AAAA−AAAA−A";

public static void main(String args[]) {


try {
System.out.println(formatString(value,mask));
// output : A−1234−B567−Z
}
catch (java.text.ParseException e) {
e.printStackTrace();
}
}

public static String formatString(String string, String mask)


throws java.text.ParseException {
javax.swing.text.MaskFormatter mf =
new javax.swing.text.MaskFormatter(mask);
mf.setValueContainsLiteralCharacters(false);
return mf.valueToString(string);
}
}

NOTE : Since this is Swing class, it is designed to be used in conjunction with a


JFormattedTextField.

MaskFormatter format = new MaskFormatter("A##−##");


JFormattedTextField textField = new JFormattedTextField( format );
textField.setFocusLostBehavior(JFormattedTextField.COMMIT);

The possible mask values are

Character Description
# Any valid number, uses Character.isDigit .
' Escape character, used to escape any of
the special formatting characters.
U Any character ( Character.isLetter ).
All lowercase letters are mapped to upper case.
L Any character ( Character.isLetter ).
All upper case letters are mapped to lower case.
A Any character or number
( Character.isLetter or Character.isDigit )
? Any character ( Character.isLetter ).
* Anything.
H Any hex character (0−9, a−f or A−F).

19.16 Apply a mask to String


If you find this article useful, consider making a small donation
to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.17 Format a String (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0463.html

JDK1.5 simplifies the operation of formatting a String based on parameters.

The String class now provides a new method called format(). The parameter substitution
mechanism is heavily inspired by C's printf.

String s = String.format
("Welcome %s at %s", "Real's HowTo", "http://www.rgagnon.com");
// output : Welcome Real's HowTo at http://www.rgagnon.com

A printf method has been added to System.out !

System.out.printf
("Welcome %s at %s", "Real's HowTo", "http://www.rgagnon.com");

As you can see, it is now possible to call a method with a variable number of parameters. But it is
also possible to use an array (with the new String.format()).

String a[] = { "Real's HowTo", "http://www.rgagnon.com" };

String s = String.format("Welcome %s at %s", a);


System.out.println(s);

Object a[] = { "Real's HowTo", "http://www.rgagnon.com" ,


java.util.Calendar.getInstance()};

String s = String.format("Welcome %1$s at %2$s ( %3$tY %3$tm %3$te )", a);


// output : Welcome Real's HowTo at http://www.rgagnon.com (2004 03 7)

You can use this new feature to quickly format strings into table :

public class Divers {


public static void main(String args[]){
String format = "|%1$−10s|%2$−10s|%3$−20s|\n";
System.out.format(format, "FirstName", "Init.", "LastName");
System.out.format(format, "Real", "", "Gagnon");
System.out.format(format, "John", "D", "Doe");

String ex[] = { "John", "F.", "Kennedy" };

System.out.format(String.format(format, (Object[])ex));
}
}

Output:

|FirstName |Init. |LastName |

19.17 Format a String (JDK1.5)


|Real | |Gagnon |
|John |D |Doe |
|John |F. |Kennedy |

19.18 Replace a "\" by "\\"


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0476.html

It can be quite an adventure to deal with the "\" since it is considered as an escape character in
Java. You always need to "\\" a "\" in a String. But the fun begins when you want to use a "\" in
regex expression, because the "\" is an escape character in regex too. So for a single "\" you need
to use "\\\\" in a regex expression.

So the regex expression to replace "\" to "\\" is

myString = myString.replaceAll("\\\\","\\\\\\\\");

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.19 Substitute tokens in a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0494.html

Object[] params = new Object[]{"hello", "!"};


String msg = MessageFormat.format("{0} world {1]", params);
// hello world !

java.text.MessageFormat is a very powerful API, you should study the javadoc to see all the
possibilities.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.20 Compare accentuated letters


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0496.html

class Test {
public static void main(String args[]) {

String s1 = "état";
String s2 = "famille";

19.18 Replace a "\" by "\\"


// (javadoc)
// The result of String.compareTo() is a negative integer
// if this String object lexicographically precedes the
// argument string. The result is a positive integer if
// this String object lexicographically follows the argument
// string. The result is zero if the strings are equal;
// compareTo returns 0 exactly when the equals(Object)
// method would return true.

// here we are expecting "é" < "f"


if (s1.compareTo(s2) > 0) {
// s1 lexicographically follows s2 which is not true!
System.out.println("not ok s1 > s2 ");
}

// (javadoc)
// Collator.compare() compares the source string to the target string
// according to the collation rules for this Collator.
// Returns an integer less than, equal to or greater than zero
// depending on whether the source String is less than,
// equal to or greater than the target string.
java.text.Collator frCollator =
java.text.Collator.getInstance(java.util.Locale.FRANCE);
frCollator.setStrength(java.text.Collator.CANONICAL_DECOMPOSITION);
// or frCollator.setStrength(java.text.Collator.SECONDARY);
// to be non case sensitive
if (frCollator.compare(s1, s2) < 0) {
// s2 lexicographically follows s1
System.out.println("ok s1 < s2 ");
}
}
}

Equality

class Test {
public static void main(String args[]) {

String s1 = "état";
String s2 = "État";

// here we are expecting "état" == "État"


if (s1.compareTo(s2) != 0) {
System.out.println("not ok s1 != s2 ");
}

java.text.Collator frCollator =
java.text.Collator.getInstance(java.util.Locale.FRANCE);
frCollator.setStrength(java.text.Collator.SECONDARY);
if (frCollator.compare(s1, s2) == 0) {
// s2 lexicographically follows s1
System.out.println("ok s1 == s2 ");
}
}
}

NOTE: Also, another possibility is to convert to uppercase/lowercase both items to be compared.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.18 Replace a "\" by "\\"


19.21 Create a String with fixed length and filled with a specific
character
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0512.html

public class StringFixedAndFilled {


public static void main(String argv[]) {
String s = ">" + fillString('X', 25) + "<";
System.out.println(s);
s = ">" + fillString(' ', 25) + "<";
System.out.println(s);
/*
output : >XXXXXXXXXXXXXXXXXXXXXXXXX<
> <
*/

public static String fillString(char fillChar, int count){


// creates a string of 'x' repeating characters
char[] chars = new char[count];
while (count>0) chars[−−count] = fillChar;
return new String(chars);
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.22 Unquote a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0522.html

We use the fact that the Properties unquote a String, so we simply simulate a Property read with our
String.

Maybe not the best way but it is certainly very easy!

import java.io.*;
import java.util.*;

public class Unquote {


public static void main(String[] args) {
String a = "Visit Real\\'s at http://www.rgagnon.com";
String b = unquote(a);
System.out.println(a);
System.out.println(b);
/*
output :
Visit Real\'s at http://www.rgagnon.com

19.21 Create a String with fixed length and filled with a specific character
Visit Real's at http://www.rgagnon.com
*/
}

public static String unquote(String a) {


Properties prop = new Properties();
try {
prop.load(new ByteArrayInputStream(("x=" + a).getBytes()));
}
catch (IOException ignore) {}
return prop.getProperty("x");
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.23 Escape HTML special characters from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0306.html

public static final String escapeHTML(String s){


StringBuffer sb = new StringBuffer();
int n = s.length();
for (int i = 0; i <n; i++) {
char c = s.charAt(i);
switch (c) {
case '<': sb.append("&lt;"); break;
case '>': sb.append("&gt;"); break;
case '&': sb.append("&amp;"); break;
case '"': sb.append("&quot;"); break;
case 'à': sb.append("&agrave;");break;
case 'À': sb.append("&Agrave;");break;
case 'â': sb.append("&acirc;");break;
case 'Â': sb.append("&Acirc;");break;
case 'ä': sb.append("&auml;");break;
case 'Ä': sb.append("&Auml;");break;
case 'å': sb.append("&aring;");break;
case 'Å': sb.append("&Aring;");break;
case 'æ': sb.append("&aelig;");break;
case 'Æ': sb.append("&AElig;");break;
case 'ç': sb.append("&ccedil;");break;
case 'Ç': sb.append("&Ccedil;");break;
case 'é': sb.append("&eacute;");break;
case 'É': sb.append("&Eacute;");break;
case 'è': sb.append("&egrave;");break;
case 'È': sb.append("&Egrave;");break;
case 'ê': sb.append("&ecirc;");break;
case 'Ê': sb.append("&Ecirc;");break;
case 'ë': sb.append("&euml;");break;
case 'Ë': sb.append("&Euml;");break;
case 'ï': sb.append("&iuml;");break;
case 'Ï': sb.append("&Iuml;");break;
case 'ô': sb.append("&ocirc;");break;
case 'Ô': sb.append("&Ocirc;");break;
case 'ö': sb.append("&ouml;");break;
case 'Ö': sb.append("&Ouml;");break;

19.23 Escape HTML special characters from a String


case 'ø': sb.append("&oslash;");break;
case 'Ø': sb.append("&Oslash;");break;
case 'ß': sb.append("&szlig;");break;
case 'ù': sb.append("&ugrave;");break;
case 'Ù': sb.append("&Ugrave;");break;
case 'û': sb.append("&ucirc;");break;
case 'Û': sb.append("&Ucirc;");break;
case 'ü': sb.append("&uuml;");break;
case 'Ü': sb.append("&Uuml;");break;
case '®': sb.append("&reg;");break;
case '©': sb.append("&copy;");break;
case '€': sb.append("&euro;"); break;
// be carefull with this one (non−breaking whitee space)
case ' ': sb.append("&nbsp;");break;

default: sb.append(c); break;


}
}
return sb.toString();
}

Here another snippet to convert a String to HTML. This one is little bit better because it deals with
space versus non−breaking space (&nbsp;) and Unicode characters.

Submitted by S. Bayer. (PS. Thanks to ablage_p for the fix!)

public static String stringToHTMLString(String string) {


StringBuffer sb = new StringBuffer(string.length());
// true if last char was blank
boolean lastWasBlankChar = false;
int len = string.length();
char c;

for (int i = 0; i < len; i++)


{
c = string.charAt(i);
if (c == ' ') {
// blank gets extra work,
// this solves the problem you get if you replace all
// blanks with &nbsp;, if you do that you loss
// word breaking
if (lastWasBlankChar) {
lastWasBlankChar = false;
sb.append("&nbsp;");
}
else {
lastWasBlankChar = true;
sb.append(' ');
}
}
else {
lastWasBlankChar = false;
//
// HTML Special Chars
if (c == '"')
sb.append("&quot;");
else if (c == '&')
sb.append("&amp;");
else if (c == '<')
sb.append("&lt;");
else if (c == '>')
sb.append("&gt;");

19.23 Escape HTML special characters from a String


else if (c == '\n')
// Handle Newline
sb.append("&lt;br/&gt;");
else {
int ci = 0xffff & c;
if (ci < 160 )
// nothing special only 7 Bit
sb.append(c);
else {
// Not 7 Bit use the unicode system
sb.append("&#");
sb.append(new Integer(ci).toString());
sb.append(';');
}
}
}
}
return sb.toString();
}

19.24 Unescape HTML special characters from a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0307.html

19.25 Using HashMap


import java.util.*;

public class StringUtils {

private static HashMap htmlEntities;


static {
htmlEntities = new HashMap<String,String>();
htmlEntities.put("&lt;","<") ; htmlEntities.put("&gt;",">");
htmlEntities.put("&amp;","&") ; htmlEntities.put("&quot;","\"");
htmlEntities.put("&agrave;","à"); htmlEntities.put("&Agrave;","À");
htmlEntities.put("&acirc;","â") ; htmlEntities.put("&auml;","ä");
htmlEntities.put("&Auml;","Ä") ; htmlEntities.put("&Acirc;","Â");
htmlEntities.put("&aring;","å") ; htmlEntities.put("&Aring;","Å");
htmlEntities.put("&aelig;","æ") ; htmlEntities.put("&AElig;","Æ" );
htmlEntities.put("&ccedil;","ç"); htmlEntities.put("&Ccedil;","Ç");
htmlEntities.put("&eacute;","é"); htmlEntities.put("&Eacute;","É" );
htmlEntities.put("&egrave;","è"); htmlEntities.put("&Egrave;","È");
htmlEntities.put("&ecirc;","ê") ; htmlEntities.put("&Ecirc;","Ê");
htmlEntities.put("&euml;","ë") ; htmlEntities.put("&Euml;","Ë");
htmlEntities.put("&iuml;","ï") ; htmlEntities.put("&Iuml;","Ï");
htmlEntities.put("&ocirc;","ô") ; htmlEntities.put("&Ocirc;","Ô");
htmlEntities.put("&ouml;","ö") ; htmlEntities.put("&Ouml;","Ö");
htmlEntities.put("&oslash;","ø) ; htmlEntities.put("&Oslash;","Ø");
htmlEntities.put("&szlig;","ß") ; htmlEntities.put("&ugrave;","ù");
htmlEntities.put("&Ugrave;","Ù"); htmlEntities.put("&ucirc;","û");
htmlEntities.put("&Ucirc;","Û") ; htmlEntities.put("&uuml;","ü");
htmlEntities.put("&Uuml;","Ü") ; htmlEntities.put("&nbsp;"," ");
htmlEntities.put("&copy;","\u00a9");
htmlEntities.put("&reg;","\u00ae");
htmlEntities.put("&euro;","\u20a0");
}

19.24 Unescape HTML special characters from a String


public static final String unescapeHTML(String source, int start){
int i,j;

i = source.indexOf("&", start);
if (i > −1) {
j = source.indexOf(";" ,i);
if (j > i) {
String entityToLookFor = source.substring(i , j + 1);
String value = (String)htmlEntities.get(entityToLookFor);
if (value != null) {
source = new StringBuffer().append(source.substring(0 , i))
.append(value)
.append(source.substring(j + 1))
.toString();
return unescapeHTML(source, start + 1); // recursive call
}
}
}
return source;
}

public static void main(String args[]) throws Exception {


// to see accentued character to the console
java.io.PrintStream ps = new java.io.PrintStream(System.out, true, "Cp850");
String test = "© 2007 Réal Gagnon <www.rgagnon.com>";
ps.println(test + "\n−−>\n" +unescapeHTML(test, 0));

/*
output :
&copy; 2007 R&eacute;al Gagnon &lt;www.rgagnon.com&gt;
−−>
© 2007 Réal Gagnon <www.rgagnon.com>
*/
}
}

19.26 Using Array


public class StringUtils {

private static String [][] htmlEscape =


{{ "&lt;" , "<" } , { "&gt;" , ">" } ,
{ "&amp;" , "&" } , { "&quot;" , "\"" } ,
{ "&agrave;" , "à" } , { "&Agrave;" , "À" } ,
{ "&acirc;" , "â" } , { "&auml;" , "ä" } ,
{ "&Auml;" , "Ä" } , { "&Acirc;" , "Â" } ,
{ "&aring;" , "å" } , { "&Aring;" , "Å" } ,
{ "&aelig;" , "æ" } , { "&AElig;" , "Æ" } ,
{ "&ccedil;" , "ç" } , { "&Ccedil;" , "Ç" } ,
{ "&eacute;" , "é" } , { "&Eacute;" , "É" } ,
{ "&egrave;" , "è" } , { "&Egrave;" , "È" } ,
{ "&ecirc;" , "ê" } , { "&Ecirc;" , "Ê" } ,
{ "&euml;" , "ë" } , { "&Euml;" , "Ë" } ,
{ "&iuml;" , "ï" } , { "&Iuml;" , "Ï" } ,
{ "&ocirc;" , "ô" } , { "&Ocirc;" , "Ô" } ,
{ "&ouml;" , "ö" } , { "&Ouml;" , "Ö" } ,
{ "&oslash;" , "ø" } , { "&Oslash;" , "Ø" } ,
{ "&szlig;" , "ß" } , { "&ugrave;" , "ù" } ,
{ "&Ugrave;" , "Ù" } , { "&ucirc;" , "û" } ,
{ "&Ucirc;" , "Û" } , { "&uuml;" , "ü" } ,
{ "&Uuml;" , "Ü" } , { "&nbsp;" , " " } ,
{ "&copy;" , "\u00a9" } ,

19.26 Using Array


{ "&reg;" , "\u00ae" } ,
{ "&euro;" , "\u20a0" }
};

public static final String unescapeHTML(String s, int start){


int i, j, k, l ;

i = s.indexOf("&", start);
start = i + 1;
if (i > −1) {
j = s.indexOf(";" ,i);
/*
we don't want to start from the beginning
the next time, to handle the case of the &
thanks to Pieter Hertogh for the bug fix!
*/
if (j > i) {
// ok this is not most optimized way to
// do it, a StringBuffer would be better,
// this is left as an exercise to the reader!
String temp = s.substring(i , j + 1);
// search in htmlEscape[][] if temp is there
k = 0;
while (k < htmlEscape.length) {
if (htmlEscape[k][0].equals(temp)) break;
else k++;
}
if (k < htmlEscape.length) {
s = s.substring(0 , i)
+ htmlEscape[k][1] + s.substring(j + 1);
return unescapeHTML(s, start); // recursive call
}
}
}
return s;
}

public static void main(String args[]) throws Exception {


// to see accentued character to the console
java.io.PrintStream ps = new java.io.PrintStream(System.out, true, "Cp850");
String test = "© 2000 Réal Gagnon <www.rgagnon.com>";
ps.println(test + "\n−−>\n" +unescapeHTML(test, 0));

/*
output :
&copy; 2000 R&eacute;al Gagnon &lt;www.rgagnon.com&gt;
−−>
© 2000 Réal Gagnon <www.rgagnon.com>
*/
}
}

This HowTo deals only with a small subset of the available HTML entities. See this Wikipedia article
for a complete list :
http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Character_entities_in_HT

19.27 Detect non−ASCII character in a String


Current version of this HowTo :

19.27 Detect non−ASCII character in a String


http://www.rgagnon.com/javadetails/../javadetails/java−0536.html

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharacterCodingException;

public class TestAscii {

public static void main (String args[])


throws Exception {
// this String throws an Exception, it contains an accentued letter
String test = "Réal";
// this String is OK
//String test = "Real";

byte bytearray [] = test.getBytes();


System.out.println("Test string : " + test);

CharsetDecoder d = Charset.forName("US−ASCII").newDecoder();
try {
CharBuffer r = d.decode(ByteBuffer.wrap(bytearray));
r.toString();
}
catch(CharacterCodingException e) {
System.out.println("only regular ASCII characters please!");
// interrupt the processing
throw new Exception(e);
}
System.out.println("Ok, it's ASCII only!");
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2006


[ home ]

19.28 Remove HTML tags from a file to extract only the TEXT
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0424.html

import java.io.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;

public class Html2Text extends HTMLEditorKit.ParserCallback {


StringBuffer s;

public Html2Text() {}

public void parse(Reader in) throws IOException {


s = new StringBuffer();
ParserDelegator delegator = new ParserDelegator();
// the third parameter is TRUE to ignore charset directive
delegator.parse(in, this, Boolean.TRUE);
}

19.28 Remove HTML tags from a file to extract only the TEXT
public void handleText(char[] text, int pos) {
s.append(text);
}

public String getText() {


return s.toString();
}

public static void main (String[] args) {


try {
// the HTML to convert
FileReader in = new FileReader("java−new.html");
Html2Text parser = new Html2Text();
parser.parse(in);
in.close();
System.out.println(parser.getText());
}
catch (Exception e) {
e.printStackTrace();
}
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2007


[ home ]

19.29 Convert a byte array to a Hex string


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0596.html

The simple way

public static String getHexString(byte[] b) throws Exception {


String result = "";
for (int i=0; i < b.length; i++) {
result +=
Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring( 1 );
}
return result;
}

A faster way

import java.io.UnsupportedEncodingException;

public class StringUtils {

static final byte[] HEX_CHAR_TABLE = {


(byte)'0', (byte)'1', (byte)'2', (byte)'3',
(byte)'4', (byte)'5', (byte)'6', (byte)'7',
(byte)'8', (byte)'9', (byte)'a', (byte)'b',
(byte)'c', (byte)'d', (byte)'e', (byte)'f'
};

public static String getHexString(byte[] raw)

19.29 Convert a byte array to a Hex string


throws UnsupportedEncodingException
{
byte[] hex = new byte[2 * raw.length];
int index = 0;

for (byte b : raw) {


int v = b & 0xFF;
hex[index++] = HEX_CHAR_TABLE[v >>> 4];
hex[index++] = HEX_CHAR_TABLE[v & 0xF];
}
return new String(hex, "ASCII");
}

public static void main(String args[]) throws Exception{


byte[] byteArray = {
(byte)255, (byte)254, (byte)253,
(byte)252, (byte)251, (byte)250
};

System.out.println(StringUtils.getHexString(byteArray));

/*
* output :
* fffefdfcfbfa
*/

}
}

19.30 Apply proper uppercase and lowercase on a String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0594.html

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringUtils {

public static String upperCaseWordFirst(String str) {


StringBuffer sb = new StringBuffer();
Matcher m = Pattern.compile
("([a−z])([a−z]*)",Pattern.CASE_INSENSITIVE).matcher(str);
while (m.find()) {
m.appendReplacement(sb, m.group(1).toUpperCase()
+ m.group(2).toLowerCase()) ;
}
str = m.appendTail(sb).toString();
return str;
}

public static void main(String [] args) {


System.out.println(StringUtils.upperCaseWordFirst(" #600how−to"));
System.out.println(StringUtils.upperCaseWordFirst("ELVis preSLEY"));
System.out.println(StringUtils.upperCaseWordFirst("john o'connor &steeve mcmillan"));
/*
output :

#600How−To
Elvis Presley

19.30 Apply proper uppercase and lowercase on a String


John O'Connor &Steeve Mcmillan

for the "mcmillan", well this may be not enough and you will need
to process it as a special case if needed...
*/
}
}

19.31 Encode/Decode to/from Base64


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0598.html

As seen in this HowTo, the sun.misc.BASE64Encoder/Decoder or creating your own Base64


handling are the best way to deal with Base64 encoding/decoding.

19.32 Using javax.mail.internet.MimeUtility


import javax.mail.internet.MimeUtility;
import java.io.*;

public class Base64Utils {


public static byte[] encode(byte[] b) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = MimeUtility.encode(baos, "base64");
b64os.write(b);
b64os.close();
return baos.toByteArray();
}

public static byte[] decode(byte[] b) throws Exception {


ByteArrayInputStream bais = new ByteArrayInputStream(b);
InputStream b64is = MimeUtility.decode(bais, "Base64");
byte[] tmp = new byte[b.length];
int n = b64is.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return res;
}

public static void main(String[] args) throws Exception {


String test = "realhowto";

byte res1[] = Base64Utils.encode(test.getBytes());


System.out.println(test + " base64 −> " + java.util.Arrays.toString(res1));
System.out.println(new String(res1));
byte res2[] = Base64Utils.decode(res1);
System.out.println("");
System.out.println( java.util.Arrays.toString(res1) + " string −−> "
+ new String(res2));

/*
* output
* realhowto base64 −>
* [99, 109, 86, 104, 98, 71, 104, 118, 100, 51, 82, 118]
* cmVhbGhvd3Rv
* [99, 109, 86, 104, 98, 71, 104, 118, 100, 51, 82, 118]
* string −−> realhowto

19.31 Encode/Decode to/from Base64


*/
}

19.33 Using Apache Commons Codec


Apache Commons Codec provides implementations of common encoders and decoders such as
Base64, Hex, Phonetic and URLs. Download at http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Base64;

public class Codec {


public static void main(String[] args) {
try {
String clearText = "Hello world";
String encodedText;

// Base64
encodedText = new String(Base64.encodeBase64(clearText.getBytes()));
System.out.println("Encoded: " + encodedText);
System.out.println("Decoded:"
+ new String(Base64.decodeBase64(encodedText.getBytes())));
//
// output :
// Encoded: SGVsbG8gd29ybGQ=
// Decoded:Hello world
//
}
catch (Exception e) {
e.printStackTrace();
}
}
}

19.34 MiGBase64
• MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

19.35 Convert from type X to type Y


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0004.html

integer to String :

int i = 42;
String str = Integer.toString(i);
or
String str = "" + i

double to String :

String str = Double.toString(i);

19.33 Using Apache Commons Codec


long to String :

String str = Long.toString(l);

float to String :

String str = Float.tString(f);

String to integer :

str = "25";
int i = Integer.valueOf(str).intValue();
or
int i = Integer.parseInt(str);

String to double :

Double d = Double.valueOf(str).doubleValue();

String to long :

long l = Long.valueOf(str).longValue();
or
Long L = Long.parseLong(str);

String to float :

Float f = Float.valueOf(str).floatValue();

decimal to binary :

int i = 42;
String bin = Integer.toBinaryString(i);

decimal to hexadecimal :

int i = 42;
String hexstr = Integer.toString(i, 16);

or
String hexstr = Integer.toHexString(i);

or (with leading zeroes and uppercase)


public class Hex {
public static void main(String args[]){
int i = 42;
System.out.print
(Integer.toHexString( 0x10000 | i).substring(1).toUpperCase());
}
}

Byte array to hexadecimal string:


See this How−to

19.33 Using Apache Commons Codec


hexadecimal (String) to integer :

int i = Integer.valueOf("B8DA3", 16).intValue();


or
int i = Integer.parseInt("B8DA3", 16);

ASCII code to String

int i = 64;
String aChar = new Character((Char)i).toString();

integer to ASCII code (byte)

char c = 'A';
int i = (int) c; // i == 65 DECIMAL

To extract Ascii codes from a String

String test = "ABCD";


for ( int i = 0; i <test.length(); ++i ) {
char c = test.charAt( i );
int j = (int) c;
System.out.println(j);
}

integer to boolean

b = (i != 0);
// ex : 42 != 0 −−> true

boolean to integer

i = (b)?1:0;
// true −−> 1

Note :To catch illegal number conversion, try using the try/catch mechanism.

try{
i = Integer.parseInt(aString);
}
catch(NumberFormatException e) {
...
}

19.36 Type conversion (JDK1.5)


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0464.html

19.36 Type conversion (JDK1.5)


JDK1.5 simplifies the operation of conversion between primitive types (such as int) and wrapper
types (such as Integer). This feature is called Autoboxing/Unboxing.

public class Test15 {


public static void main(String ... args) {
Integer integer = 1; // int into Integer
System.out.println(integer);

int i = integer + 3; // mix Integer and ints


System.out.println(i);

// output :
// 1
// 4
}
}

In the next example, a boolean is being stored and then retrieved from an ArrayList. The 1.5
version leaves the conversion required to transition to an Boolean and back to the compiler.

import java.util.Collection.*;
import java.util.*;

public class Test15 {


public static void main(String ... args) {
ArrayList<Boolean> list = new ArrayList<Boolean>();
list.add(0, true);
boolean flag = list.get(0);
System.out.println(flag);
}
}

The old way (pre 1.5) is more cryptic...

import java.util.Collection.*;
import java.util.*;

public class Test15 {


public static void main(String args[]) {
ArrayList list = new ArrayList();
list.add(0, new Boolean(true));
boolean flag = ((Boolean)list.get(0)).booleanValue();
System.out.println(flag);
}
}

Note : To be able to compile that code with the JDK1.5, you need to specify the switch −source
1.4 on the javac command line.

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.37 Round a double

19.37 Round a double


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0016.html

JDK1.0.2

public class TestRound102 {


public static void main(String args[]){
double d = 3.1537;
// output is 3.15
System.out.println(d + " : " + round(d, 2));
// output is 3.154
System.out.println(d + " : " + round(d, 3));
}

public static double round(double value, int decimalPlace)


{
double power_of_ten = 1;
while (decimalPlace−− > 0)
power_of_ten *= 10.0;
return Math.round(value * power_of_ten) / power_of_ten;
}
}

JDK1.1

import java.math.*;
public class TestRound11 {
public static void main(String args[]){
double d = 3.1537;
BigDecimal bd = new BigDecimal(d);
bd = bd.setScale(2,BigDecimal.ROUND_HALF_UP);
// output is 3.15
System.out.println(d + " : " + round(d, 2));
// output is 3.154
System.out.println(d + " : " + round(d, 3));
}

public static double round(double d, int decimalPlace){


// see the Javadoc about why we use a String in the constructor
// http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html#BigDecimal(double)
BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();
}
}

19.38 Display numbers with commas


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0019.html

[JDK1.1]

import java.text.*;
public class DemoNumber {
public static void main(String args[]) {
double d = 123456.78;
DecimalFormat df = new DecimalFormat("#####0.00");

19.38 Display numbers with commas


System.out.println(df.format(d));
}
}

On Windows, the regional settings (Control Panel) are used for decimal point and hundred
separator.

If the decimal separator is set to "," in your Regional Settings and you really want a "." then

import java.text.*;
public class DemoNumber {
public static void main(String args[]) {
double d = 123456.78;
DecimalFormat df = new DecimalFormat("#####0.00");
DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
// make sure it's a '.'
dfs.setDecimalSeparator('.');
df.setDecimalFormatSymbols(dfs);
System.out.println(df.format(d));
}
}

19.39 Display numbers in scientific notation


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0020.html

JDK1.0.2

public static String toScientific(double num,int places) {


double power=(int)(Math.log(num)/Math.log(10));
if(power < 0) power−−;
double fraction=num/Math.pow(10,power);
String result="";
String sign="";
fraction=round(fraction,places);
if(power > 0) sign="+";
result+=fraction+"e"+sign+power;
return result;
}

public static double round(double value, int decimalPlace) {


double power_of_ten = 1;
while (decimalPlace−− > 0)
power_of_ten *= 10.0;
return Math.round(value * power_of_ten) / power_of_ten;
}

JDK1.2 A much better way is now in the java.text package :

import java.text.*;
import java.math.*;

public class TestScientific {

public static void main(String args[]) {


new TestScientific().doit();

19.39 Display numbers in scientific notation


}

public void doit() {


NumberFormat formatter = new DecimalFormat();

int maxinteger = Integer.MAX_VALUE;


System.out.println(maxinteger); // 2147483647

formatter = new DecimalFormat("0.######E0");


System.out.println(formatter.format(maxinteger)); // 2,147484E9

formatter = new DecimalFormat("0.#####E0");


System.out.println(formatter.format(maxinteger)); // 2.14748E9

int mininteger = Integer.MIN_VALUE;


System.out.println(mininteger); // −2147483648

formatter = new DecimalFormat("0.######E0");


System.out.println(formatter.format(mininteger)); // −2.147484E9

formatter = new DecimalFormat("0.#####E0");


System.out.println(formatter.format(mininteger)); // −2.14748E9

double d = 0.12345;
formatter = new DecimalFormat("0.#####E0");
System.out.println(formatter.format(d)); // 1.2345E−1

formatter = new DecimalFormat("000000E0");


System.out.println(formatter.format(d)); // 12345E−6
}
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.40 Display numbers with leading zeroes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0021.html

import java.text.*;
public class DemoNumber {
public static void main(String args[]) {
long n = 123456;
String mask = "00000000000";
// jdk1.1
DecimalFormat df = new DecimalFormat(mask);
System.out.println(df.format(n));

// pre−jdk1.1
String ds = Long.toString(n); // double to string
String z = mask.substring(0 , mask.length() − ds.length()) + ds;
System.out.println(z);
}
}

19.40 Display numbers with leading zeroes


19.41 Get a random number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0017.html

JDK1.1, Random.nextInt() returns the next pseudorandom, uniformly distributed int value from
this random number generator's sequence.

// random number between 0 AND 10


import java.util.Random;

Random r = new Random();


int randint = Math.abs(r.nextInt()) % 11;

JDK1.2, Random.nextInt(n) returns a pseudorandom, uniformly distributed int value between 0


(inclusive) and n (exclusive).

// random number between 0 AND 10


import java.util.Random;

Random r = new Random();


int randint = r.nextInt(10);

19.42 Convert an UNSIGNED byte to a JAVA type


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0026.html

In JAVA, a byte always considered as signed when converted to another type. We must mask the
sign bit to JAVA, cast to an integer and process the masked bit if needed. The following method
implements this idea :

public class UnsignedByte {


public static void main (String args[]) {
byte b1 = 127;
byte b2 = −128;
byte b3 = −1;

System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(unsignedByteToInt(b1));
System.out.println(unsignedByteToInt(b2));
System.out.println(unsignedByteToInt(b3));
/*
127
−128
−1
127
128
255
*/
}

public static int unsignedByteToInt(byte b) {


return (int) b & 0xFF;

19.41 Get a random number


}
}

Therefore for an array of 4 bytes (buf[]), which represents an integer :

int i = 0;
int pos = 0;
i += unsignedByteToInt(buf[pos++]) << 24;
i += unsignedByteToInt(buf[pos++]) << 16;
i += unsignedByteToInt(buf[pos++]) << 8;
I += unsignedByteToInt(buf[pos++]) << 0;

To convert a byte to it's hexadecimal equivalent

public static String byteToHex(byte b){


int i = b &0xFF;
return Integer.toHexString(i);
}

NOTE: when converting byte representing an integer, it's possible that you will have to deal with the big−endian vs little−endian format. See
this How−to

19.43 Deal with big−endian and little−endian order


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0007.html

Java virtual machine always used big−endian, Intel x86 used little−endian.

public class Swab {


public final static int swabInt(int v) {
return (v >>> 24) | (v << 24) |
((v << 8) &0x00FF0000) | ((v >> 8) &0x0000FF00);
}

public static void main(String argv[]) {


// before 0x01020304
// after 0x04030201
int v = 0x01020304;
System.out.println("before : 0x" + Integer.toString(v,16));
System.out.println("after : 0x" + Integer.toString(swabInt(v),16));
}
}

NOTE: to convert UNSIGNED byte to integer, look at this How−to

19.44 Pass an integer by reference


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0035.html

Sometimes you may need to pass an integer to be able to change its value. "integer" are always
passed by value in Java. An easy way to pass by reference is to use a single element array.

int[] a = new int[1];

19.43 Deal with big−endian and little−endian order


a[0] = 1;
add2(a);
// a[0] now = 3
...

void add2(int[] a) {
a[0] = a[0] + 2;
}

19.45 Pass floats as string literals to a method


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0050.html

Color c = new Color(0.1,0.2,0.4);

returns "Incompatible type for constructor. Explicit cast needed to convert double to int." even if
the constructor Color (float r, float g, float b) is valid. That's because the compiler interprets
numbers like 0.1 as double not float. You must use the suffixe "f" to indicate that the number is a
float.

Color c = new Color(0.1f,0.2f,0.4f);

19.46 Get random numbers


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0419.html

public class MyTest {


public static void main(String args[]) {
new MyTest().doit();
}
public void doit() {
java.util.Random rand = new java.util.Random();
// random integer 0 to 10
int max = 10;
for (int i=0; i<10; i++) {
System.out.println(rand.nextInt(max + 1));
}
// random double 0 to 10
double maxd = 10;
for (int i=0; i<10; i++) {
System.out.println(maxd * rand.nextDouble());
}
}
}

The output

4
0
0
10
10
4

19.45 Pass floats as string literals to a method


10
10
6
10
8.13013058393518
0.6631286078928067
4.382003543427801
7.2768144451559795
7.312852816962123
8.69257797289748
2.4967782036871657
4.451145854389913
1.82517092998838

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.47 Convert number into words


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0426.html

English

class EnglishDecimalFormat {
private static final String[] majorNames = {
"",
" thousand",
" million",
" billion",
" trillion",
" quadrillion",
" quintillion"
};

private static final String[] tensNames = {


"",
" ten",
" twenty",
" thirty",
" fourty",
" fifty",
" sixty",
" seventy",
" eighty",
" ninety"
};

private static final String[] numNames = {


"",
" one",
" two",
" three",
" four",
" five",
" six",
" seven",

19.47 Convert number into words


" eight",
" nine",
" ten",
" eleven",
" twelve",
" thirteen",
" fourteen",
" fifteen",
" sixteen",
" seventeen",
" eighteen",
" nineteen"
};

private String convertLessThanOneThousand(int number) {


String soFar;

if (number % 100 < 20){


soFar = numNames[number % 100];
number /= 100;
}
else {
soFar = numNames[number % 10];
number /= 10;

soFar = tensNames[number % 10] + soFar;


number /= 10;
}
if (number == 0) return soFar;
return numNames[number] + " hundred" + soFar;
}

public String convert(int number) {


/* special case */
if (number == 0) { return "zero"; }

String prefix = "";

if (number < 0) {
number = −number;
prefix = "negative";
}

String soFar = "";


int place = 0;

do {
int n = number % 1000;
if (n != 0){
String s = convertLessThanOneThousand(n);
soFar = s + majorNames[place] + soFar;
}
place++;
number /= 1000;
} while (number > 0);

return (prefix + soFar).trim();


}

public static void main(String[] args) {


EnglishDecimalFormat f = new EnglishDecimalFormat();
System.out.println("*** " + f.convert(0));
System.out.println("*** " + f.convert(1));

19.47 Convert number into words


System.out.println("*** " + f.convert(16));
System.out.println("*** " + f.convert(100));
System.out.println("*** " + f.convert(118));
System.out.println("*** " + f.convert(200));
System.out.println("*** " + f.convert(219));
System.out.println("*** " + f.convert(800));
System.out.println("*** " + f.convert(801));
System.out.println("*** " + f.convert(1316));
System.out.println("*** " + f.convert(1000000));
System.out.println("*** " + f.convert(2000000));
System.out.println("*** " + f.convert(3000200));
System.out.println("*** " + f.convert(700000));
System.out.println("*** " + f.convert(9000000));
System.out.println("*** " + f.convert(123456789));
System.out.println("*** " + f.convert(−45));
/*
*** zero
*** one
*** sixteen
*** one hundred
*** one hundred eighteen
*** two hundred
*** two hundred nineteen
*** eight hundred
*** eight hundred one
*** one thousand three hundred sixteen
*** one million
*** two million
*** three million two hundred
*** seven hundred thousand
*** nine million
*** one hundred twenty three million four hundred
** fifty six thousand seven hundred eighty nine
*** negative fourty five
*/
}
}

Français
Quite different than the english version but french is a lot more difficult!

import java.text.*;

class FrenchDecimalFormat {
private static final String[] dizaineNames = {
"",
"",
"vingt",
"trente",
"quarante",
"cinquante",
"soixante",
"soixante",
"quatre−vingt",
"quatre−vingt"
};

private static final String[] uniteNames1 = {


"",
"un",
"deux",
"trois",

19.47 Convert number into words


"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf",
"dix",
"onze",
"douze",
"treize",
"quatorze",
"quinze",
"seize",
"dix−sept",
"dix−huit",
"dix−neuf"
};

private static final String[] uniteNames2 = {


"",
"",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf",
"dix"
};

private String convertZeroToHundred(int number) {

int laDizaine = number / 10;


int lUnite = number % 10;
String resultat = "";

switch (laDizaine) {
case 1 :
case 7 :
case 9 :
lUnite = lUnite + 10;
break;
default:
}

// séparateur "−" "et" ""


String laLiaison = "";
if (laDizaine > 1) {
laLiaison = "−";
}
// cas particuliers
switch (lUnite) {
case 0:
laLiaison = "";
break;
case 1 :
if (laDizaine == 8) {
laLiaison = "−";
}
else {
laLiaison = " et ";

19.47 Convert number into words


}
break;
case 11 :
if (laDizaine==7) {
laLiaison = " et ";
}
break;
default:
}

// dizaines en lettres
switch (laDizaine) {
case 0:
resultat = uniteNames1[lUnite];
break;
case 8 :
if (lUnite == 0) {
resultat = dizaineNames[laDizaine];
}
else {
resultat = dizaineNames[laDizaine]
+ laLiaison + uniteNames1[lUnite];
}
break;
default :
resultat = dizaineNames[laDizaine]
+ laLiaison + uniteNames1[lUnite];
}

return resultat;
}

private String convertLessThanOneThousand(int number) {

int lesCentaines = number / 100;


int leReste = number % 100;
String sReste = convertZeroToHundred(leReste);

String resultat;
switch (lesCentaines) {
case 0:
resultat = sReste;
break;
case 1 :
if (leReste > 0) {
resultat = "cent " + sReste;
}
else {
resultat = "cent";
}
break;
default :
if (leReste > 0) {
resultat = uniteNames2[lesCentaines] + " cent " + sReste;
}
else {
resultat = uniteNames2[lesCentaines] + " cents";
}
}
return resultat;
}

19.47 Convert number into words


public String convert(long number) {
// 0 à 999 999 999 999
if (number == 0) { return "zéro"; }

String snumber = Long.toString(number);

// pad des "0"


String mask = "000000000000";
DecimalFormat df = new DecimalFormat(mask);
snumber = df.format(number);

// XXXnnnnnnnnn
int lesMilliards = Integer.parseInt(snumber.substring(0,3));
// nnnXXXnnnnnn
int lesMillions = Integer.parseInt(snumber.substring(3,6));
// nnnnnnXXXnnn
int lesCentMille = Integer.parseInt(snumber.substring(6,9));
// nnnnnnnnnXXX
int lesMille = Integer.parseInt(snumber.substring(9,12));

String tradMilliards;
switch (lesMilliards) {
case 0:
tradMilliards = "";
break;
case 1 :
tradMilliards = convertLessThanOneThousand(lesMilliards)
+ " milliard ";
break;
default :
tradMilliards = convertLessThanOneThousand(lesMilliards)
+ " milliards ";
}
String resultat = tradMilliards;

String tradMillions;
switch (lesMillions) {
case 0:
tradMillions = "";
break;
case 1 :
tradMillions = convertLessThanOneThousand(lesMillions)
+ " million ";
break;
default :
tradMillions = convertLessThanOneThousand(lesMillions)
+ " millions ";
}
resultat = resultat + tradMillions;

String tradCentMille;
switch (lesCentMille) {
case 0:
tradCentMille = "";
break;
case 1 :
tradCentMille = "mille ";
break;
default :
tradCentMille = convertLessThanOneThousand(lesCentMille)
+ " mille ";
}
resultat = resultat + tradCentMille;

19.47 Convert number into words


String tradMille;
tradMille = convertLessThanOneThousand(lesMille);
resultat = resultat + tradMille;

return resultat;
}

public static void main(String[] args) {


FrenchDecimalFormat f = new FrenchDecimalFormat();
System.out.println("*** " + f.convert(0));
System.out.println("*** " + f.convert(9));
System.out.println("*** " + f.convert(19));
System.out.println("*** " + f.convert(21));
System.out.println("*** " + f.convert(28));
System.out.println("*** " + f.convert(71));
System.out.println("*** " + f.convert(72));
System.out.println("*** " + f.convert(80));
System.out.println("*** " + f.convert(81));
System.out.println("*** " + f.convert(89));
System.out.println("*** " + f.convert(90));
System.out.println("*** " + f.convert(91));
System.out.println("*** " + f.convert(97));
System.out.println("*** " + f.convert(100));
System.out.println("*** " + f.convert(101));
System.out.println("*** " + f.convert(110));
System.out.println("*** " + f.convert(120));
System.out.println("*** " + f.convert(200));
System.out.println("*** " + f.convert(201));
System.out.println("*** " + f.convert(232));
System.out.println("*** " + f.convert(999));
System.out.println("*** " + f.convert(1000));
System.out.println("*** " + f.convert(1001));
System.out.println("*** " + f.convert(10000));
System.out.println("*** " + f.convert(10001));
System.out.println("*** " + f.convert(100000));
System.out.println("*** " + f.convert(2000000));
System.out.println("*** " + f.convert(3000000000L));
/*
*** OUTPUT
*** zéro
*** neuf
*** dix−neuf
*** vingt et un
*** vingt−huit
*** soixante et onze
*** soixante−douze
*** quatre−vingt
*** quatre−vingt−un
*** quatre−vingt−neuf
*** quatre−vingt−dix
*** quatre−vingt−onze
*** quatre−vingt−dix−sept
*** cent
*** cent un
*** cent dix
*** cent vingt
*** deux cents
*** deux cent un
*** deux cent trente−deux
*** neuf cent quatre−vingt−dix−neuf
*** mille
*** mille un

19.47 Convert number into words


*** dix mille
*** dix mille un
*** cent mille
*** deux millions
*** trois milliards
*/
}
}

You can handle "dollar and cent" conversion by calling the "convert" method two times.

String phrase = "12345.67" ;


Float num = new Float( phrase ) ;
int dollars = (int)Math.floor( num ) ;
int cent = (int)Math.floor( ( num − dollars ) * 100.0f ) ;

String s = "$ " + f.convert( dollars ) + " and "


+ f.convert( cent ) + " cents" ;

Another way to use a built−in function of your DBMS (if available).

For Oracle

SQL> select to_char(to_date(873,'J'), 'JSP') as converted_form from dual;

CONVERTED_FORM
−−−−−−−−−−−−−−−−−−−−−−−−−−−
EIGHT HUNDRED SEVENTY−THREE

SQL>

'JSP' means :
• J : the Julian format.
• SP : spells the word for the number passed to to_date

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.48 Arithmetic with double


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0474.html

You may find that

System.out.println( 1.33 − 1.3 );


// output : 0.030000000000000027

The unexpected result is coming from the fact that internal floating−point number representation
is not well suited for that kind of operation.

The easiest way to solve this limitation is to the BigDecimal class :

19.48 Arithmetic with double


import java.math.BigDecimal;
...
System.out.println
(BigDecimal.valueOf(1.33).subtract(BigDecimal.valueOf(1.3)));

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.49 Detect even/odd number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0488.html

Use the modulus operator.

For Other interesting modulus operations, see http://mindprod.com/jgloss/modulus.html

if (x % 2 == 0) {
// even
}

if (x % 2 != 0) {
// odd
}

... or binary AND operator...

if (( x & 1 ) == 0) {
// even
}

if (( x & 1 ) != 0) {
// odd
}

If you find this article useful, consider making a small donation


to show your support for this Web site and its content.

Written and compiled by Réal Gagnon ©1998−2005


[ home ]

19.50 Convert bytes to megabytes


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0540.html

import java .io.*;

public class Test {

public static void main(String args[]) {


// a big file ...
File f = new File("news.easynews.com.newsrc");
System.out.println(f.length());

19.49 Detect even/odd number


System.out.println(bytesToMeg(f.length()) + " Mb");
}

private static final long MEGABYTE = 1024L * 1024L;

public static long bytesToMeg(long bytes) {


return bytes / MEGABYTE ;
}
}

19.51 Validate a number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java−0599.html

public class NumberUtils {

// Check if given string is a number (digits only)


public static boolean isNumber(String string) {
return string.matches("^\\d+$");
}

// Check if given string is numeric (−+0..9(.)0...9)


public static boolean isNumeric(String string) {
return string.matches("^[−+]?\\d+(\\.\\d+)?$");
}

// Check if given string is number with dot separator and two decimals.
public static boolean isNumberWith2Decimals(String string) {
return string.matches("^\\d+\\.\\d{2}$");
}

public static void main(String[] args) {


System.out.println("42 valid ? " + NumberUtils.isNumber("42"));
System.out.println("42.1 valid ? " + NumberUtils.isNumber("42.1"));

System.out.println("42 valid ? " + NumberUtils.isNumeric("42"));


System.out.println("42.1 valid ? " + NumberUtils.isNumeric("42.1"));
System.out.println("−42.1 valid ? " + NumberUtils.isNumeric("42.1"));
System.out.println("−42.1a valid ? " + NumberUtils.isNumeric("42.1a"));

System.out.println("42.10 valid ? " + NumberUtils.isNumberWith2Decimals("42.10"));


System.out.println("42.101 valid ? " + NumberUtils.isNumberWith2Decimals("42.101"));
System.out.println("42,10 valid ? " + NumberUtils.isNumberWith2Decimals("42,10"));
System.out.println("42 valid ? " + NumberUtils.isNumberWith2Decimals("42"));

/*
* output
* 42.1 valid ? false
* 42 valid ? true
*
* 42.1 valid ? true
* −42.1 valid ? true
* −42.1a valid ? false
*
* 42.10 valid ? true
* 42.101 valid ? false
* 42,10 valid ? false
* 42 valid ? false
*/

19.51 Validate a number


}
}

Written and compiled Réal Gagnon ©2007 real@rgagnon.com


http://www.rgagnon.com

19.51 Validate a number

Вам также может понравиться