You are on page 1of 1080

Real's HowTo PDF version.

This is the PDF version of the Real's HowTo Web site ( http://www.rgagnon.com/howto.html ).
For uptodate 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 Howto'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 javaapplet........................................................................................................................1
1.2 Goto to a new URL from an AppletTag(s): Applet.............................................................1
1.3 Determine the host from where the Applet is loadedTag(s): Applet..................................3
1.4 Have a scrolling status lineTag(s): Applet..........................................................................3
1.5 Use a search engineTag(s): Applet...................................................................................5
1.6 Have an onscreen clockTag(s): Applet............................................................................6
1.7 Have Applets on the same page communicate with each otherTag(s): Applet.................8
1.8 Have Applets on different frames communicates with each otherTag(s): Applet..............9
1.9 Send a message from an Applet to another Applet on a different pageTag(s): Applet....11
1.10 Have an applet launch an other appletTag(s): Applet....................................................13
1.11 Get the user nameTag(s): Applet Security.....................................................................14
1.12 Access parameters passed in the URLTag(s): Applet...................................................15
1.13 Convert an Applet to Application Tag(s): Applet............................................................17
1.14 Change the mouse cursor in AppletTag(s): Applet........................................................18
1.15 Use an Image as the Applet backgroundTag(s): Applet AWT.......................................19
1.16 Handle the new Control Activation mechanism in IETag(s): Applet...............................20
1.16.1 Solution #1............................................................................................................20
1.16.2 Solution #2............................................................................................................21
1.16.3 Solution #3............................................................................................................22
1.17 Pass parameters to the Applet JVM (WIN)Tag(s): Applet.............................................23
1.18 See the Java Console Window Log (Java plugin)Tag(s): Applet Environment..............24
1.19 Display debugging infos for an AppletTag(s): Applet.....................................................24
1.20 Have an invisible Applet Tag(s): Applet.........................................................................25
1.21 Keep the JVM loadedTag(s): Applet..............................................................................25
1.22 Detect browser type from an AppletTag(s): Applet Environment Javascript
interaction.............................................................................................................................25
1.23 Call a Javascript from the Applet...................................................................................26
1.24 Get the value from the serverside................................................................................27
2 Date and Time...............................................................................................................................28
2.1 javadate.........................................................................................................................28
2.2 Have year on 4 digits from a Date objectTag(s): Date and Time.....................................28
2.3 Get the current Date and TimeTag(s): Date and Time....................................................28
2.4 Compute days between 2 datesTag(s): Date and Time..................................................29
2.5 Get the number of days in a monthTag(s): Date and Time..............................................31
2.6 Validate a dateTag(s): Date and Time.............................................................................31
2.6.1 Using DateFormat...................................................................................................31
2.6.2 Using GregorianCalendar.......................................................................................33
2.7 Determine to day of the weekTag(s): Date and Time......................................................33
2.8 Add/Substract Day/Month/Year to a DateTag(s): Date and Time....................................34
2.9 Get the correct TimeZone on DateFormatTag(s): Date and Time...................................35
2.10 Simply format a date as "YYYYMMDD"Tag(s): Date and Time.....................................35
2.11 Compare 2 datesTag(s): Date and Time.......................................................................36
2.12 Parse a String to obtain a Date/GregorianCalendar objectTag(s): Date and Time........37
2.13 Use System time to generate unique IDTag(s): Date and Time Date and Time
Varia.......................................................................................................................................38
2.14 Get the day nameTag(s): Date and Time......................................................................38
2.15 Find the current date formatTag(s): Date and Time.......................................................39
2.16 Get a julian dateTag(s): Date and Time.........................................................................40

2.17 Calculate the ageTag(s): Date and Time

Real's HowTo@www.rgagnon.com
2 Date and Time
2.17 Calculate the ageTag(s): Date and Time.......................................................................43
2.18 Format a duration in milliseconds into a humanreadable formatTag(s): Date and
Time......................................................................................................................................43
2.19 Get the atomic timeTag(s): Date and Time....................................................................46
2.20 Get a date intervalTag(s): Date and Time......................................................................48
2.21 Determine if an hour is between an intervalTag(s): Date and Time...............................50
2.22 Set the computer clockTag(s): Date and Time JNI........................................................51
2.23 Use System time to generate unique IDTag(s): Date and Time Date and Time
Varia.......................................................................................................................................52
2.24 Get the month (or day) name (localized)Tag(s): Date and Time Internationalization....52
2.25 Detect a leap yearTag(s): Date and Time......................................................................53
3 AWT................................................................................................................................................55
3.1 javaawt...........................................................................................................................55
3.2 Use The CardLayout managerTag(s): AWT....................................................................55
3.3 Detect which card is visible with a CardLayoutTag(s): AWT...........................................57
3.4 Use PopupsTag(s): AWT.................................................................................................58
3.5 Use a File DialogTag(s): AWT.........................................................................................60
3.6 Use TrueType fontTag(s): AWT.......................................................................................61
3.7 Display available fontsTag(s): AWT.................................................................................62
3.8 Font with 3D effectTag(s): AWT.......................................................................................62
3.9 Use the System ClipboardTag(s): AWT...........................................................................63
3.10 Maximize a FrameTag(s): AWT.....................................................................................64
3.11 Center a Frame/DialogTag(s): AWT..............................................................................65
3.12 Close a FrameTag(s): AWT...........................................................................................66
3.13 Call events on a Frame from a PanelTag(s): AWT........................................................68
3.14 Set the small topleft icon on a FrameTag(s): AWT......................................................70
3.15 Prevent a Frame to be resizedTag(s): AWT..................................................................70
3.16 Embed an image into a FrameTag(s): AWT AWT.........................................................72
3.17 Display a message boxTag(s): AWT.............................................................................74
3.18 Display a Splash screenTag(s): AWT............................................................................75
3.19 Vibrate a WindowTag(s): AWT......................................................................................77
3.20 Limit TextField input to numeric valueTag(s): AWT.......................................................79
3.21 Limit TextField input to a maximum lengthTag(s): AWT................................................81
3.22 React to the ENTER key in a TextfieldTag(s): AWT......................................................82
3.23 Make the ENTER key act like the TAB keyTag(s): AWT...............................................83
3.24 Reset all textfields in one shotTag(s): AWT...................................................................83
3.25 Limit a TextField to UppercaseTag(s): AWT..................................................................84
3.26 Have an ImageButtonTag(s): AWT................................................................................85
3.27 Reset a checkbox groupTag(s): AWT............................................................................88
3.28 Set the listbox widthTag(s): AWT...................................................................................89
3.29 Align the column in a ListTag(s): AWT...........................................................................90
3.30 Have a srolling text displayTag(s): AWT........................................................................90
3.31 Label dynamic resizingTag(s): AWT..............................................................................91
3.32 Make a TextArea "wordwrap"Tag(s): AWT..................................................................93
3.33 Synchronize a TextArea vs a ChoiceTag(s): AWT........................................................93
3.34 Display underlined textTag(s): AWT..............................................................................94
3.35 Display vertical textTag(s): AWT....................................................................................94
3.36 Have Label with many linesTag(s): AWT.......................................................................95

Real's HowTo@www.rgagnon.com
3 AWT
3.37 Have a Label with underlined text Tag(s): AWT............................................................99
3.38 Have a Label acting as HTML HREF (URLLabel)Tag(s): AWT...................................100
3.39 Display a GIF in a CanvasTag(s): AWT.......................................................................102
3.40 Embed an image into a FrameTag(s): AWT AWT.......................................................103
3.41 Load several images from a single GIFTag(s): AWT...................................................105
3.42 Load an Image from a JAR fileTag(s): AWT................................................................106
3.43 Load an Icon from a jar (again)Tag(s): AWT...............................................................107
3.44 Scale an ImageTag(s): AWT........................................................................................107
3.45 Fade an imageTag(s): AWT.........................................................................................109
3.46 Rotate an imageTag(s): AWT......................................................................................111
3.47 Create a scrollable canvasTag(s): AWT......................................................................113
3.48 Use an Image as the Applet backgroundTag(s): Applet AWT.....................................117
3.49 Have a simple Image browserTag(s): AWT.................................................................118
3.50 Simulate a "mouse over" event to toggle an imageTag(s): AWT.................................121
3.51 Hide the mouse cursorTag(s): AWT............................................................................123
3.52 Make a color transparentTag(s): AWT.........................................................................123
3.53 Save an Image as a GIF or JPEG fileTag(s): AWT.....................................................124
3.54 Use the same background color as the browserTag(s): AWT.....................................126
3.55 Do simple animation using ImagesTag(s): AWT..........................................................126
3.56 Do simple animation to show "work in progress"Tag(s): AWT.....................................128
3.57 Get the color of a specific pixelTag(s): AWT................................................................129
3.58 Do "rubberband" drawingTag(s): AWT......................................................................130
3.59 Convert RGB value to Hexadecimal (to be used in HTML for example)Tag(s):
AWT....................................................................................................................................132
3.60 Draw a line or set a pixel in my own imageTag(s): AWT.............................................133
3.61 Draw a dashed lineTag(s): AWT..................................................................................133
3.62 Draw a line with a thicknessTag(s): AWT....................................................................134
3.63 Draw a pie chartTag(s): AWT......................................................................................136
3.64 Draw faster rectanglesTag(s): AWT.............................................................................138
3.65 Get a screen capture and save it as a JPEGTag(s): AWT..........................................139
3.66 Detect a double click vs simple clickTag(s): AWT.......................................................140
3.67 Detect the mouse button used when clickingTag(s): AWT..........................................141
3.68 Exit an application from a menuTag(s): AWT..............................................................142
3.69 Trigger a click on a ButtonTag(s): AWT Swing............................................................143
3.70 Display a TIFTag(s): AWT...........................................................................................144
3.71 Convert a multipage TIF into singlepage TIFTag(s): AWT......................................146
3.72 Convert many singlepage TIF into one multipage TIF Tag(s): AWT.......................147
3.73 Convert an Image to a BufferedImageTag(s): AWT....................................................148
3.74 Detect if a TIF is blank Tag(s): AWT............................................................................149
3.75 Convert TIF to PDFTag(s): AWT IO IO Open Source..................................................152
3.76 Convert a TIF to a JPGTag(s): AWT............................................................................153
4 Environment................................................................................................................................155
4.1 javaenv........................................................................................................................155
4.2 Read environment variables from an applicationTag(s): Environment..........................155
4.3 Retrieve environment variables (JDK1.5)Tag(s): Environment......................................159
4.4 Retrieve environment variable (JNI)Tag(s): Environment JNI.......................................159
4.5 Use a MAKE fileTag(s): Environment............................................................................160
4.6 Detect the browser/JVM type (deprecated)Tag(s): Environment DEPRECATED.........161

4.7 Fix the "Wrong magic number" error messageTag(s): Environment

Real's HowTo@www.rgagnon.com
4 Environment
4.7 Fix the "Wrong magic number" error messageTag(s): Environment.............................163
4.8 Use a precompiler " la C" with JavaTag(s): Environment............................................164
4.9 Open source packages..................................................................................................164
4.10 Ant................................................................................................................................164
4.11 Simple boolean flag.....................................................................................................165
4.12 Determine what are the classes actually used in a Java Applet or application
Tag(s): Environment............................................................................................................165
4.13 Set the memory available to the JVMTag(s): Environment..........................................166
4.14 Generate the Javadoc "en franais"Tag(s): Environment Environment
Internationalization...............................................................................................................166
4.15 Use JDK1.5 new featuresTag(s): Environment............................................................167
4.16 Check the class versionTag(s): Environment..............................................................168
4.17 Get the system properties or the JVM uptimeTag(s): Environment.............................169
4.18 Detect if running in a 64bit JVMTag(s): Environment..................................................170
4.19 Set the default JVM typeTag(s): Environment.............................................................171
4.20 Select a particular JRE from the command lineTag(s): Environment..........................172
4.21 Get the PID (pure Java solution)Tag(s): Environment.................................................173
4.22 Get the PIDTag(s): Environment JNI...........................................................................174
4.23 Set default value for java property (system wide)Tag(s): Environment.......................175
4.24 Detect if running in a debug modeTag(s): Environment..............................................176
4.25 Capture the output of JAVACTag(s): Environment......................................................176
4.26 Freeze the JVIEW window in MS VJ++Tag(s): Environment.......................................177
4.27 Wrap a Java beans in a COM objectTag(s): Environment...........................................177
4.28 Know details about the JAVA at runtimeTag(s): Environment...................................179
4.29 Detect the Microsoft JVM version installedTag(s): Environment.................................180
4.30 Run JAVA as a Windows serviceTag(s): Environment Open Source..........................181
4.31 Execute a class from Windows ExplorerTag(s): Environment.....................................181
4.32 Create an icon to launch java apps for Windows?Tag(s): Environment......................183
4.33 Fix the "out of environment" error when setting a new CLASSPATHTag(s):
Environment........................................................................................................................183
4.34 Query Windows registryTag(s): Environment..............................................................184
4.35 Read/Write the Registry (Windows)Tag(s): Environment............................................186
4.36 Quickly retrieve available Java JVM on a workstation (Windows)Tag(s):
Environment........................................................................................................................194
4.37 Using regedit................................................................................................................194
4.38 Using a CMD file..........................................................................................................195
4.39 Get a return code from a VBSTag(s): IO Environment................................................196
4.40 List currently running processes (Windows)Tag(s): Environment................................197
4.40.1 Using TASKLIST.EXE.........................................................................................197
4.40.2 Using a VBS........................................................................................................198
4.41 Check if a program or process is running (Windows)Tag(s): Environment..................199
4.42 Detect if a process is running using WMIC Tag(s): Misc Prog HowTo Java
Environment........................................................................................................................201
4.43 Windows registry vs. Java JDK/JRE installationTag(s): Environment.........................202
4.44 Get the current Java version from a BAT fileTag(s): Environment..............................203
4.45 Get the Windows "My Documents" pathTag(s): Environment.....................................204
4.46 Get the Windows Desktop pathTag(s): Environment...................................................204
4.47 Get the Windows Special FoldersTag(s): Environment...............................................206
4.48 Create an Internet Shortcut (Windows)Tag(s): Environment.......................................207

Real's HowTo@www.rgagnon.com
4 Environment
4.49 Detect if running in remote session (Windows)Tag(s): Environment...........................208
4.50 Detect if running a Citrix session (Windows)Tag(s): IO...............................................210
4.51 Create a Taglet to document database access (Javadoc)Tag(s): Environment..........210
4.51.1 newMethod.........................................................................................................211
4.52 Generate the Javadoc "en franais"Tag(s): Environment Environment
Internationalization...............................................................................................................214
4.53 Document a package using Javadoc Tag(s): Environment.........................................215
4.54 Display a comment in a JavadocTag(s): Environment.................................................216
4.55 Display XML in a javadocTag(s): Environment............................................................217
4.56 Add a copyright notice to a JavadocTag(s): Environment...........................................218
4.57 Use a Log fileTag(s): Environment..............................................................................218
4.58 Trace the executionTag(s): Environment.....................................................................221
4.59 Time the executionTag(s): Environment......................................................................222
4.60 Log information efficiently (with Log4J)Tag(s): Environment.......................................223
4.61 Change the logging level onthefly (Log4J)Tag(s): Environment..............................224
4.62 Enable debug log level on OpenSource package(Apache Commons Logging)
Tag(s): Environment............................................................................................................225
4.63 Use a JAR/ZIP/CAB file with an AppletTag(s): Environment.......................................226
4.64 Make ZIP/JAR file always accessible from appletTag(s): Environment.......................228
4.65 Make a JAR executableTag(s): Environment..............................................................228
4.66 Accessing jars from within a jarTag(s): Environment...................................................230
4.67 Access a JAR outside the CLASSPATHTag(s): Environment.....................................230
4.68 Extract a file from a JarTag(s): IO Environment...........................................................231
4.69 Determine if running from JARTag(s): Environment....................................................232
4.70 Get list of classes in package (in a Jar)Tag(s): Environment.......................................234
4.71 Add version to Jar packagingTag(s): Environment......................................................235
4.72 Use ANT to Build a JAR with version/build numberTag(s): Environment....................237
4.73 Include all jars in the classpath definitionTag(s): Environment....................................241
4.74 Windows batch file.......................................................................................................241
4.75 JDK6............................................................................................................................242
4.76 JAR (and ANT).............................................................................................................242
4.77 Detect browser type from an AppletTag(s): Applet Environment Javascript
interaction...........................................................................................................................244
4.78 Call a Javascript from the Applet.................................................................................244
4.79 Get the value from the serverside..............................................................................245
4.80 Detect if Java is enabled from HTMLTag(s): Environment..........................................245
4.81 See the Java Console Window Log (Java plugin)Tag(s): Applet Environment............246
5 Internationalization.....................................................................................................................247
5.1 javainter.......................................................................................................................247
5.2 Load resources based upon client environment at startupTag(s):
Internationalization..............................................................................................................247
5.3 Load resources dynamicallyTag(s): Internationalization................................................250
5.4 Load resources via a resources fileTag(s): Internationalization.....................................253
5.5 Display "special character" using UnicodeTag(s): Internationalization..........................257
5.6 Display chinese/japanese charactersTag(s): Internationalization..................................258
5.7 Localize a JOptionPane dialogTag(s): Internationalization Swing.................................258
5.8 Validate/Convert a number using the current Locale()Tag(s): Internationalization
String/Number......................................................................................................................260

5.9 Localize a JFileChooserTag(s): Internationalization Swing

Real's HowTo@www.rgagnon.com
5 Internationalization
5.9 Localize a JFileChooserTag(s): Internationalization Swing...........................................261
5.10 Disable localizationTag(s): Internationalization............................................................264
5.11 Generate the Javadoc "en franais"Tag(s): Environment Environment
Internationalization...............................................................................................................264
5.12 Sort a String arrayTag(s): Internationalization Varia....................................................266
5.13 Accentuated characters in Properties/ResourceBundle fileTag(s):
Internationalization Language.............................................................................................268
5.14 Compare accentuated lettersTag(s): Internationalization String/Number....................268
5.15 Unaccent lettersTag(s): Internationalization String/Number........................................270
5.15.1 Using java.text.Normalizer..................................................................................270
5.15.2 Using String.replaceAll().....................................................................................271
5.15.3 The String.indexOf()............................................................................................271
5.16 Output accentuated characters to the consoleTag(s): IO Internationalization.............273
5.17 Java 1.6 or more..........................................................................................................273
5.18 Java 1.5 or less............................................................................................................274
5.19 Get the default character set of the JVMTag(s): IO Internationalization......................274
5.20 Convert OEM (DOS) file to Ansi (Windows)Tag(s): IO Internationalization.................275
5.21 Detect nonASCII character in a StringTag(s): Internationalization String/Number....276
5.22 Get the month (or day) name (localized)Tag(s): Date and Time
Internationalization...............................................................................................................277
6 IO..................................................................................................................................................279
6.1 javaio...........................................................................................................................279
6.2 Redirect output(stdout/stderr) to a frameTag(s): IO.......................................................279
6.3 Redirect printStackTrace() to a StringTag(s): IO...........................................................280
6.4 Redirect to a NULL deviceTag(s): IO.............................................................................281
6.5 Print a text file using the javax.print APITag(s): IO........................................................282
6.6 Print a String to a printer Tag(s): IO...............................................................................284
6.7 Print text to a printer easilyTag(s): IO............................................................................285
6.8 Print without a DialogTag(s): IO.....................................................................................286
6.9 Initialize and write to a serial portTag(s): IO..................................................................286
6.10 Open or close a CD/DVD driveTag(s): IO....................................................................287
6.11 Get the volume labelTag(s): IO....................................................................................288
6.12 Detect the storage device typeTag(s): IO....................................................................289
6.13 Turn on MQ Debug mode Tag(s): IO...........................................................................290
6.14 Get faster console output (System.out.println() replacement)Tag(s): IO.....................291
6.15 Simple input from the keyboardTag(s): IO...................................................................292
6.16 Output accentuated characters to the consoleTag(s): IO Internationalization.............294
6.17 Java 1.6 or more..........................................................................................................294
6.18 Java 1.5 or less............................................................................................................294
6.19 Clear the console and control attributesTag(s): IO Open Source................................295
6.20 Jansi.............................................................................................................................295
6.21 JCurses........................................................................................................................296
6.22 Easy keyboard input (JDK1.5)Tag(s): IO.....................................................................297
6.23 Force keyboard input in CAPS LOCK onTag(s): IO.....................................................298
6.24 Automatic conversion of System.out output Tag(s): IO...............................................299
6.25 Execute an external programTag(s): IO.......................................................................301
6.26 Using Runtime.exec()..................................................................................................301
6.27 Launch a Windows CMD (or BAT) file and retrieve the errorlevel or exitcode.............302

Real's HowTo@www.rgagnon.com
6 IO
6.28 Launch a Unix script....................................................................................................303
6.29 Using the ProcessBuilder.............................................................................................303
6.30 Windows rundll32 utility...............................................................................................303
6.31 PDF (Windows only)....................................................................................................304
6.32 PDF (Mac only)............................................................................................................304
6.33 Path to executable with spaces in them.......................................................................304
6.34 VBSCRIPT...................................................................................................................305
6.35 HTML Help (Windows only).........................................................................................305
6.36 Start Excel....................................................................................................................305
6.37 Start a Windows application under another account....................................................306
6.38 Windows : execute something in Program Files..........................................................306
6.39 Launch the application associated with a file extensionTag(s): IO..............................307
6.40 Launch an application from another applicationTag(s): IO Language.........................308
6.41 Start the default browser from an applicationTag(s): IO..............................................310
6.42 Execute a Windows Shortcut (.lnk)Tag(s): IO..............................................................312
6.43 Create a file association with a Java programTag(s): IO Misc Prog HowTo................312
6.44 Capture the output from a VBSTag(s): IO....................................................................314
6.45 Get a return code from a VBSTag(s): IO Environment................................................315
6.46 Execute a CMD file stored in a JARTag(s): IO............................................................316
6.47 Open the default file explorerTag(s): IO.......................................................................318
6.48 Read the content of a fileTag(s): IO.............................................................................318
6.49 From a Java application...............................................................................................318
6.50 From a Java applet......................................................................................................319
6.51 Read a text file from a jarTag(s): IO.............................................................................321
6.52 Read a file from the internet Tag(s): Networking IO....................................................323
6.53 Extract a file from a JarTag(s): IO Environment...........................................................324
6.54 Read a data file with floatsTag(s): IO...........................................................................325
6.55 Write to the end of a fileTag(s): IO...............................................................................326
6.56 Write "real" ascii fileTag(s): IO.....................................................................................327
6.57 Copy a fileTag(s): IO....................................................................................................328
6.58 Use a "log file"Tag(s): IO.............................................................................................330
6.59 Delete files with a certain extensionTag(s): IO............................................................332
6.60 Insert a line in a fileTag(s): IO......................................................................................333
6.61 Read a file into a variable in one shotTag(s): IO..........................................................334
6.62 Serialize an object to a fileTag(s): IO...........................................................................334
6.63 Redirect stdout to a fileTag(s): IO................................................................................336
6.64 Get the "last modified" date from a fileTag(s): IO........................................................336
6.65 Check if a file existsTag(s): IO.....................................................................................337
6.66 Detect file modificationTag(s): IO.................................................................................337
6.67 File/directory polling to detect changeTag(s): IO Open Source...................................340
6.68 jpoller (directory poller)................................................................................................340
6.69 JNotify..........................................................................................................................340
6.70 Java Native Access (JNA)...........................................................................................340
6.71 Call native methods in a DLL from Java (NativeCall)..................................................341
6.72 Java 7..........................................................................................................................341
6.73 The simple (and naive!) approach...............................................................................341
6.74 Get the current directoryTag(s): IO..............................................................................341
6.75 Get the "root" of an applicationTag(s): IO....................................................................342
6.76 Get the content of a directory with a FilterTag(s): IO...................................................342

6.77 Get the content of a directory with subdirectoriesTag(s): IO

Real's HowTo@www.rgagnon.com
6 IO
6.77 Get the content of a directory with subdirectoriesTag(s): IO........................................345
6.78 Get directory content faster with many files Tag(s): IO................................................346
6.79 Make a directoryTag(s): IO..........................................................................................348
6.80 Create a fixedlength fileTag(s): IO.............................................................................348
6.81 Delete a nonempty directoryTag(s): IO......................................................................349
6.82 Create a temporary fileTag(s): IO................................................................................349
6.83 Get the default character set of the JVMTag(s): IO Internationalization......................350
6.84 Parse a pathnameTag(s): IO.......................................................................................351
6.85 Handle CSV fileTag(s): IO Open Source.....................................................................352
6.86 com.Ostermiller.util CSV Utils......................................................................................352
6.87 opencsv........................................................................................................................352
6.88 ServingXML.................................................................................................................352
6.89 Super CSV...................................................................................................................352
6.90 csvreader.....................................................................................................................352
6.91 CSVFile........................................................................................................................352
6.92 FlatPack.......................................................................................................................352
6.93 CSVJDBC....................................................................................................................353
6.94 FFP..............................................................................................................................353
6.95 Convert OEM (DOS) file to Ansi (Windows)Tag(s): IO Internationalization.................353
6.96 Close a stream in a try/catch blockTag(s): IO..............................................................354
6.97 Rename a file extensionTag(s): IO..............................................................................355
6.98 Remove file extension Tag(s): IO................................................................................357
6.99 Remove HTML tags from a file to extract only the TEXTTag(s): IO String/Number
Networking...........................................................................................................................357
6.100 Using regular expression...........................................................................................357
6.101 Using javax.swing.text.html.HTMLEditorKit...............................................................358
6.102 Using an HTML parser...............................................................................................358
6.103 Using Apache Tika.....................................................................................................359
6.104 Get the Mime Type from a FileTag(s): IO..................................................................360
6.104.1 Using Java 7.....................................................................................................360
6.104.2 Using javax.activation.MimetypesFileTypeMap................................................360
6.104.3 Using java.net.URL...........................................................................................361
6.104.4 Using Apache Tika............................................................................................362
6.104.5 Using JMimeMagic............................................................................................363
6.104.6 Using mimeutil................................................................................................363
6.104.7 Using Droid.......................................................................................................363
6.104.8 Aperture framework...........................................................................................364
6.105 Sort a directory listing (based on the last modified timestamp)Tag(s): IO.................364
6.106 Sort files by the extensionTag(s): IO..........................................................................365
6.107 Filter a directory listing by dateTag(s): IO..................................................................367
6.108 Convert wildcard to a regex expressionTag(s): IO.....................................................368
6.109 Shorten a long pathTag(s): IO String/Number...........................................................369
6.110 Force a valid Windows filenameTag(s): IO................................................................373
6.111 Check if filename is validTag(s): IO...........................................................................374
6.112 Dump a file to a HEX fileTag(s): IO............................................................................375
6.113 List all files in the classpath or in a JarTag(s): IO......................................................376
6.114 Handle UTF8 file with BOMTag(s): IO.......................................................................377
6.115 Touch a file Tag(s): IO...............................................................................................380
6.116 Handle Excel filesTag(s): IO JDBC Open Source......................................................380

Real's HowTo@www.rgagnon.com
6 IO
6.117 JDBCODBC Excel driver.........................................................................................381
6.118 JExcel........................................................................................................................381
6.119 POI.............................................................................................................................382
6.120 JXLS..........................................................................................................................382
6.121 xlSQL.........................................................................................................................383
6.122 JCOM.........................................................................................................................383
6.123 OpenXLS Java Spreadsheet SDK.............................................................................385
6.124 Create an Excel fileTag(s): IO....................................................................................387
6.125 Detect if a XLS Excel file contains a macro (using POI)Tag(s): IO............................387
6.126 Create or process a PDF fileTag(s): IO Open Source...............................................388
6.127 Create a PDFTag(s): IO Open Source.......................................................................390
6.128 iText...........................................................................................................................390
6.129 Split a PDF file (using iText)Tag(s): IO Open Source................................................392
6.130 Concatenate PDF files (using iText)Tag(s): IO Open Source....................................393
6.131 Convert TIF to PDFTag(s): AWT IO IO Open Source................................................394
6.132 Convert HTML to PDF using iTextTag(s): IO Open Source.......................................396
6.133 Convert HTML to PDF using YAHP Tag(s): IO OpenSource.....................................398
6.134 Convert a png/jpg/gif file to PDF using iTextTag(s): IO Open Source.......................400
6.135 Print a PDFTag(s): IO Open Source..........................................................................401
6.136 Extract text from a PDF (with Apache Tika) Tag(s): IO OpenSource........................402
6.137 Create a compressed (ZIP) fileTag(s): IO..................................................................402
6.138 Display compressed (ZIP) file contentTag(s): IO.......................................................403
6.139 Expand the compressed (ZIP) fileTag(s): IO.............................................................405
6.140 Emit a beepTag(s): IO................................................................................................405
6.141 Emit a ToneTag(s): IO...............................................................................................406
6.142 Play an audio file from an applicationTag(s): IO........................................................407
6.143 Produce special sound effectTag(s): IO.....................................................................409
6.144 Use the Java Speech API (JSPAPI)Tag(s): IO..........................................................412
6.145 Play a Windows sound Tag(s): IO.............................................................................414
7 JDBC............................................................................................................................................416
7.1 javajdbc........................................................................................................................416
7.2 Get JDBC driver for major database vendorsTag(s): JDBC..........................................416
7.3 Connect to a database via JDBCODBCTag(s): JDBC.................................................416
7.4 SELECT data from a tableTag(s): JDBC.......................................................................417
7.5 INSERT data into a tableTag(s): JDBC.........................................................................419
7.6 Tag(s): JDBC.................................................................................................................420
7.7 Tag(s): JDBC.................................................................................................................421
7.8 Test for an empty ResultSetTag(s): JDBC.....................................................................421
7.9 Get a record count with a SQL StatementTag(s): JDBC...............................................422
7.10 Store and retrieve an object from a tableTag(s): JDBC...............................................422
7.11 Retrieve an ImageTag(s): JDBC..................................................................................424
7.12 Insert an ImageTag(s): JDBC......................................................................................425
7.13 Call a stored procedureTag(s): JDBC..........................................................................425
7.14 Stored procedure with Input/Output parms and a ResultSetTag(s): JDBC..................426
7.15 Fix incomplete field returned by the ResultSetTag(s): JDBC.......................................427
7.16 Transfer a ResultSet to a JTableTag(s): JDBC Swing.................................................427
7.17 Detect SQL errors or warningsTag(s): JDBC...............................................................428
7.18 Using DSNless connectionTag(s): JDBC...................................................................430

7.19 Specify a CharSet when connecting to a DBMSTag(s): JDBC

Real's HowTo@www.rgagnon.com
7 JDBC
7.19 Specify a CharSet when connecting to a DBMSTag(s): JDBC....................................430
7.20 List tables in a databaseTag(s): JDBC........................................................................431
7.21 Enable JDBC loggingTag(s): JDBC.............................................................................432
7.22 Detect if a table existsTag(s): JDBC............................................................................433
7.23 Convert a ResultSet to XMLTag(s): JDBC XML..........................................................434
7.24 Display ResultSet data in an HTML Table in ServletTag(s): JDBC Servlet/JSP.........436
7.25 Escape special character in a LIKE clauseTag(s): JDBC............................................436
7.26 Log the SQL StatementsTag(s): JDBC........................................................................437
7.27 Plain JDBC Logging.....................................................................................................437
7.28 P6Spy..........................................................................................................................437
7.29 Proxool.........................................................................................................................438
7.30 JDBC Logger...............................................................................................................438
7.31 Log4JDBC....................................................................................................................438
7.32 Oracle JDBC................................................................................................................438
7.33 Insert data in batch modeTag(s): JDBC.......................................................................438
7.34 Retrieve large ResultSetTag(s): JDBC........................................................................440
7.35 Handle datesTag(s): JDBC..........................................................................................442
7.36 Get current date using JDBCTag(s): JDBC.................................................................443
7.37 Insert the current dateTag(s): JDBC............................................................................444
7.38 Read data from Excel worksheetTag(s): JDBC...........................................................444
7.39 Handle Excel filesTag(s): IO JDBC Open Source........................................................446
7.40 JDBCODBC Excel driver...........................................................................................446
7.41 JExcel..........................................................................................................................446
7.42 POI...............................................................................................................................447
7.43 JXLS............................................................................................................................448
7.44 xlSQL...........................................................................................................................449
7.45 JCOM...........................................................................................................................449
7.46 OpenXLS Java Spreadsheet SDK...............................................................................450
7.47 Connect to an Oracle database with JDBCTag(s): JDBC............................................452
7.48 Connect to Oracle using a connection poolTag(s): JDBC...........................................454
7.49 Retrieve the generated keys (JDBC Oracle)Tag(s): JDBC..........................................457
7.50 Debug Oracle JDBC connectionTag(s): JDBC............................................................458
7.51 Connect to an Oracle database using KerberosTag(s): JDBC....................................460
7.52 Identify the connected program to an Oracle databaseTag(s): JDBC.........................461
7.53 Use a CHAR field in the WHERE clause in a PreparedStatementTag(s): JDBC........463
8 JNI................................................................................................................................................465
8.1 javajni...........................................................................................................................465
8.2 Use native code through JNITag(s): JNI........................................................................465
8.3 Pass a string to/from Java to/from CTag(s): JNI............................................................465
8.4 Set the computer clockTag(s): Date and Time JNI........................................................467
8.5 Determine the signature of a methodTag(s): JNI...........................................................468
8.6 Use arraysTag(s): JNI....................................................................................................469
8.7 Load a DLLTag(s): JNI...................................................................................................471
8.8 Use the MouseWheelTag(s): JNI...................................................................................471
8.9 Throw an Exception (from JNI code)Tag(s): JNI............................................................472
8.10 Throw my own Exception (from JNI code)Tag(s): JNI.................................................472
8.11 JNI from a packageTag(s): JNI....................................................................................473
8.12 Make a Window "stay on top"Tag(s): JNI....................................................................474

Real's HowTo@www.rgagnon.com
8 JNI
8.13 Start a JVM from CTag(s): JNI.....................................................................................474
8.14 Retrieve environment variable (JNI)Tag(s): Environment JNI.....................................475
8.15 Get the PIDTag(s): Environment JNI...........................................................................476
8.16 Clear the console, set color and cursor position (JNI)Tag(s): JNI...............................477
8.17 Call Windows API (Open source solution)Tag(s): JNI Open Source...........................480
8.18 Detect if a program is running (JNA)Tag(s): JNI/JNA..................................................480
8.19 Get Windows Special Folders (JNA) Tag(s): JNI/JNA.................................................481
9 Javascript interaction.................................................................................................................483
9.1 javajs............................................................................................................................483
9.2 * Read me *Tag(s): Javascript interaction.....................................................................483
9.3 Wakeup a Java appletTag(s): Javascript interaction...................................................483
9.4 Call a Java method from JavascriptTag(s): Javascript interaction.................................486
9.5 Calling Java applets methods using DOM and JavaScriptTag(s): Javascript
interaction...........................................................................................................................487
9.6 Access Java variables from JavascriptTag(s): Javascript interaction............................488
9.7 Call Javascript from a Java appletTag(s): Javascript interaction...................................489
9.8 Using the javascript: protocol.........................................................................................489
9.9 Using the netscape.javascript.JSObject package..........................................................490
9.10 Create dynamic HTML from a Java appletTag(s): Javascript interaction....................491
9.11 Have Applets on different frames communicates with each otherTag(s):
Javascript interaction..........................................................................................................492
9.12 Send a message from an Applet to another Applet on a different pageTag(s):
Javascript interaction..........................................................................................................494
9.13 Retrieve values from a Java applet for HTML form (CGI)Tag(s): Javascript
interaction...........................................................................................................................496
9.14 Detect if an Applet is readyTag(s): Javascript interaction............................................497
9.15 Read/Write HTML field values from JAVATag(s): Javascript interaction.....................498
9.16 Detect if Java is enabledTag(s): Javascript interaction................................................500
9.17 Detect if Java 1.1 (with event delegation) is availableTag(s): Javascript interaction...500
9.18 Access Cookies from a Java AppletTag(s): Javascript interaction..............................501
9.19 Set Applet PARAM VALUE from javascriptTag(s): Javascript interaction...................503
9.20 Pass an Array between Java and JavascriptTag(s): Javascript interaction.................504
9.21 Interaction without LiveConnectTag(s): Javascript interaction.....................................507
9.22 Directory listing on the Web server in a Java AppletTag(s): Javascript interaction.....512
9.23 Have a Java button close the browser windowTag(s): Javascript interaction..............514
9.24 Detect if cookies are enabledTag(s): Javascript interaction........................................515
9.25 Display a page after all applets are loadedTag(s): Javascript interaction....................516
9.26 Detect browser type from an AppletTag(s): Applet Environment Javascript
interaction...........................................................................................................................516
9.27 Call a Javascript from the Applet.................................................................................516
9.28 Get the value from the serverside..............................................................................518
10 Servlet/JSP................................................................................................................................519
10.1 javajsp........................................................................................................................519
10.2 Read meTag(s): Servlet/JSP.......................................................................................519
10.3 Get parameters passed to a servletTag(s): Servlet/JSP..............................................519
10.4 Detect no argument condition in a ServletTag(s): Servlet/JSP....................................520
10.5 Set a Cookie from a servletTag(s): Servlet/JSP..........................................................521

10.6 Read a Cookie from a servletTag(s): Servlet/JSP

Real's HowTo@www.rgagnon.com
10 Servlet/JSP
10.6 Read a Cookie from a servletTag(s): Servlet/JSP.......................................................521
10.7 Delete (or expire) a Cookie from a servletTag(s): Servlet/JSP....................................522
10.8 Ask for a password from a ServletTag(s): Servlet/JSP................................................522
10.9 Talk to a CGI/ServletTag(s): Networking Servlet/JSP.................................................523
10.10 Test for CookiesTag(s): Servlet/JSP..........................................................................524
10.11 Display ResultSet data in an HTML Table in ServletTag(s): JDBC Servlet/JSP.......524
10.12 Specify the filename to be used for a file sent by a ServletTag(s): Servlet/JSP........525
10.13 Pass information to another servlet/jspTag(s): Servlet/JSP.......................................526
10.14 Handle PDF outputTag(s): Servlet/JSP.....................................................................526
10.15 Detect if the connection is via a secure channelTag(s): Servlet/JSP.........................527
10.16 In a Servlet, check if Form Field is presentTag(s): Servlet/JSP.................................527
10.17 Get the root dir of a web appTag(s): Servlet/JSP Servlet/JSP..................................527
10.18 Get client IP address from JSPTag(s): Servlet/JSP...................................................528
10.19 Output a binary stream from a JSPTag(s): Servlet/JSP............................................528
10.20 Use a connection cache from JSPTag(s): Servlet/JSP Jaguar/EAServer.................529
10.21 Read a Web Application propertyTag(s): Servlet/JSP...............................................531
10.22 Use EJB from JSPTag(s): Servlet/JSP......................................................................531
10.23 Define a method in a JSP pageTag(s): Servlet/JSP..................................................532
10.24 Precompile JSP pagesTag(s): Servlet/JSP...............................................................532
10.25 Get a list of directories for JSPTag(s): Servlet/JSP...................................................533
10.26 Use and share a class in JSP pages Tag(s): Servlet/JSP.........................................534
10.27 Get the root dir of a web appTag(s): Servlet/JSP Servlet/JSP..................................535
10.28 Launch an applet from a JSPTag(s): Servlet/JSP.....................................................536
10.29 Prevent caching of a JSP outputTag(s): Servlet/JSP................................................536
10.30 Launch an external program, capture its output and display it in a JSPTag(s):
Servlet/JSP.........................................................................................................................537
10.31 Call another EJBTag(s): Servlet/JSP Jaguar/EAServer............................................539
10.32 Keep java files generated from JSP (BEA WLS)Tag(s): Servlet/JSP........................539
10.33 Get the server version (BEA WLS)Tag(s): Servlet/JSP.............................................539
10.34 Quickly create a Web application with BEA WLSTag(s): Servlet/JSP.......................540
10.35 Nicely display WEB.XML informationsTag(s): Servlet/JSP XML Jaguar/EAServer...540
10.36 Reverse the CLASSLOADER order (BEA)Tag(s): Servlet/JSP.................................542
10.37 Detect change in JSP and recompile (BEA)Tag(s): Servlet/JSP...............................543
10.38 Obtain a remote connection to a DataSource or EJB (Weblogic)Tag(s):
Servlet/JSP.........................................................................................................................543
11 Language...................................................................................................................................546
11.1 javalanguage.............................................................................................................546
11.2 * Read me *Tag(s): Language String/Number.............................................................546
11.3 Obtain from where a Class is loadedTag(s): Language Varia.....................................547
11.4 Get the class name in a static methodTag(s): Language............................................548
11.5 Get the current method nameTag(s): Language..........................................................549
11.6 JDK1.4.........................................................................................................................549
11.7 JDK1.5.........................................................................................................................549
11.8 Call a method dynamically (Reflection)Tag(s): Language...........................................550
11.9 Detect if a package is availableTag(s): Language.......................................................552
11.10 Create an object from a stringTag(s): Language.......................................................553
11.11 Get a variable value from the variable nameTag(s): Language.................................554
11.12 Make methods that have unspecified number of parametersTag(s): Language........555

Real's HowTo@www.rgagnon.com
11 Language
11.13 Create a java source dynamically, compile and callTag(s): Language......................556
11.14 Java 1.6.....................................................................................................................556
11.15 Java 1.5 or less..........................................................................................................557
11.16 Launch an application from another applicationTag(s): IO Language.......................558
11.17 Access the enclosing class from an inner classTag(s): Language............................560
11.18 Access inner class from outsideTag(s): Language....................................................561
11.19 Use globally defined constantsTag(s): Language......................................................562
11.20 Serialize an ObjectTag(s): Language........................................................................563
11.21 Serialize an Object over a socketTag(s): Language..................................................565
11.22 Easily remove my debugging codeTag(s): Language................................................565
11.23 Have a singletonTag(s): Language............................................................................566
11.24 Multiple expressions in for loopsTag(s): Language...................................................566
11.25 Handle the List conflictTag(s): Language..................................................................567
11.26 Use a generic toString()Tag(s): Language.................................................................567
11.27 Use Object.clone()Tag(s): Language.........................................................................569
11.28 Static field, constructor and exceptionTag(s): Language...........................................570
11.29 Use a Label breakTag(s): Language.........................................................................571
11.30 Put printStackTrace() into a StringTag(s): Language................................................572
11.31 Iterate enum valuesTag(s): Language.......................................................................573
11.32 Get fields and values from an Object Tag(s): Language...........................................573
11.33 Use a HashtableTag(s): Language............................................................................575
11.34 Scan the content of a hashtableTag(s): Language....................................................575
11.35 Sort an arrayTag(s): Language Varia........................................................................575
11.36 Initialize multidimensional arrayTag(s): Language.....................................................577
11.37 Get array upperboundTag(s): Language...................................................................578
11.38 Convert a String to an array or an array to a stringTag(s): Language.......................578
11.38.1 String to Array...................................................................................................578
11.38.2 Array to String...................................................................................................579
11.39 Sort in reverse orderTag(s): Language......................................................................580
11.40 Resize an arrayTag(s): Language.............................................................................580
11.41 Dump array contentTag(s): Language.......................................................................582
11.42 Initialize a static arrayTag(s): Language....................................................................583
11.43 Sort an HashtableTag(s): Language..........................................................................583
11.44 Eliminate "[unchecked] unchecked call ..." compiler warning Tag(s): Language.......585
12 ANT............................................................................................................................................587
12.1 Sort on many fieldsTag(s): Language..........................................................................587
12.2 Optimize Collection usageTag(s): Language...............................................................589
12.3 Sort an HashMapTag(s): Language.............................................................................591
12.4 Get keys corresponding to a value from a MapTag(s): Language...............................592
12.5 Iterate a Collection and remove an itemTag(s): Language..........................................594
12.6 Count distinct elements in a VectorTag(s): Language.................................................595
12.7 Dump the content of a Collection (JDK 1.5)Tag(s): Language....................................596
12.7.1 List......................................................................................................................596
12.7.2 Map.....................................................................................................................597
12.8 Initialize a CollectionTag(s): Language........................................................................597
12.9 Merge (or add) two arrays into oneTag(s): Language.................................................600
12.10 Define an array (or Map, or ENUM) of functionsTag(s): Language...........................601
12.10.1 Using an interface.............................................................................................601

12.10.2 Using an enum

Real's HowTo@www.rgagnon.com
12 ANT
12.10.2 Using an enum..................................................................................................602
12.11 Join a List as a StringTag(s): Language....................................................................603
12.12 Remove duplicates from a List Tag(s): Language.....................................................604
12.13 Convert a Map to a Properties (or vice versa)Tag(s): Language...............................605
12.14 Use an INI file (properties)Tag(s): Language.............................................................606
12.15 Open Source packages.............................................................................................606
12.16 Using Properties........................................................................................................606
12.17 Load a properties fileTag(s): Language.....................................................................608
12.18 Accentuated characters in Properties/ResourceBundle fileTag(s):
Internationalization Language.............................................................................................609
12.19 Have a multiline value in a properties fileTag(s): Language....................................609
12.20 Use XML with PropertiesTag(s): Language XML.......................................................610
12.21 Use the Registry to store informations (Preferences API)Tag(s): Language.............611
12.22 Sort Properties when savingTag(s): Language..........................................................612
13 Networking................................................................................................................................614
13.1 javanet.......................................................................................................................614
13.2 Extract network card addressTag(s): Networking........................................................614
13.3 Get the workstation name/ipTag(s): Networking..........................................................617
13.4 Find port number not in useTag(s): Networking...........................................................618
13.5 Disable DNS cachingTag(s): Networking.....................................................................619
13.6 Allow user:password in URLTag(s): Networking Security Common problems
WinAPI/Registry...................................................................................................................620
13.7 Encode/Decode to/from Base64Tag(s): String/Number Networking...........................621
13.8 Using javax.mail.internet.MimeUtility...........................................................................621
13.9 Using Apache Commons Codec..................................................................................622
13.10 MiGBase64................................................................................................................622
13.11 Lookup using MX record to validate mail serverTag(s): Networking..........................622
13.12 Send an email using the SMTP protocolTag(s): Networking.....................................631
13.13 Check if there is mail waitingTag(s): Networking.......................................................632
13.14 Receive emailTag(s): Networking..............................................................................634
13.15 Send email with an attachmentTag(s): Networking...................................................636
13.16 Send email with JavaMailTag(s): Networking............................................................641
13.17 Send email with authenticationTag(s): Networking....................................................644
13.18 Send HTML mail with images (Javamail)Tag(s): Networking....................................645
13.19 Debug a JavaMail ProgramTag(s): Networking.........................................................647
13.20 JavaMail Debug mode...............................................................................................647
13.21 Verify connectivity to the MailServer with Telnet :.....................................................648
13.22 Use a JavaMail server mockup to act as "inmemory" mail server.........................648
13.23 Send email with SMTPS (eg. Google GMail) (Javamail)Tag(s): Networking.............648
13.23.1 Settings for well known mail providers..............................................................650
13.24 Mix plain text and HTML content in a mailTag(s): Networking...................................650
13.25 Read an Outlook MSG fileTag(s): Networking Open Source.....................................651
13.26 Apache POI HSMF....................................................................................................651
13.27 msgparser..................................................................................................................653
13.28 jmbox.........................................................................................................................654
13.29 Handle EML file with JavaMailTag(s): Networking.....................................................654
13.30 Loading an .EML file..................................................................................................654
13.31 Saving an email to .EML file......................................................................................655

Real's HowTo@www.rgagnon.com
13 Networking
13.32 Receive email using IMAPTag(s): Networking...........................................................656
13.33 Receive email using POP3Tag(s): Networking..........................................................659
13.34 Check if a file was modified on the serverTag(s): Networking...................................661
13.35 Check if a page existsTag(s): Networking.................................................................661
13.36 Connect through a ProxyTag(s): Networking Networking..........................................663
13.36.1 The Networking Properties................................................................................663
13.36.2 Proxy and Username/Password........................................................................664
13.36.3 Bypass a Proxy.................................................................................................666
13.37 Identify yourself using HTTP AuthentificationTag(s): Networking..............................666
13.38 Talk to a CGI/ServletTag(s): Networking Servlet/JSP...............................................668
13.39 Write/Read cookies using HTTPTag(s): Networking.................................................669
13.40 Read a file from the internet Tag(s): Networking IO..................................................671
13.41 Read a GIF or CLASS from an URL save it locallyTag(s): Networking.....................672
13.42 Resolve a relative URLTag(s): Networking................................................................674
13.43 File size from URLTag(s): Networking.......................................................................674
13.44 Use the HTTPS protocolTag(s): Networking..............................................................675
13.45 Fix certificate problem in HTTPSTag(s): Networking.................................................675
13.46 Fetch a page from GoogleTag(s): Networking...........................................................677
13.47 Upload a file to a serverTag(s): Networking...............................................................678
13.48 Remove HTML tags from a file to extract only the TEXTTag(s): IO
String/Number Networking...................................................................................................679
13.49 Using regular expression...........................................................................................679
13.50 Using javax.swing.text.html.HTMLEditorKit...............................................................679
13.51 Using an HTML parser...............................................................................................680
13.52 Using Apache Tika.....................................................................................................681
13.53 Extract links from an HTML pageTag(s): String/Number Networking........................682
13.54 Using javax.swing.text.html.HTMLEditorKit...............................................................682
13.55 Using an HTML parser...............................................................................................682
13.56 Call a web service (generated with BEA ServiceGen)Tag(s): Networking................683
13.57 Do basic authentication when calling a webservice Tag(s): Networking...................685
13.58 WS authentication from Weblogic..............................................................................686
13.59 Have a simple HTTP serverTag(s): Networking........................................................686
13.60 Connect through a ProxyTag(s): Networking Networking..........................................688
13.60.1 The Networking Properties................................................................................688
13.60.2 Proxy and Username/Password........................................................................690
13.60.3 Bypass a Proxy.................................................................................................691
13.61 Have timeout on socket connectionTag(s): Networking.............................................691
13.62 Ping a serverTag(s): Networking...............................................................................692
13.63 Get the Date from serverTag(s): Networking.............................................................693
13.64 Use the java.net.Socket.setSoLinger methodTag(s): Networking.............................694
13.65 Use the java.net.Socket.setTcpNoDelay methodTag(s): Networking........................694
13.66 Find out who is accessing my ServerSocketTag(s): Networking...............................695
13.67 Transfer a file via SocketTag(s): Networking.............................................................695
14 Security......................................................................................................................................698
14.1 javasecurity................................................................................................................698
14.2 Encrypt a passwordTag(s): Security............................................................................698
14.3 Transmit a password with MessageDigest..................................................................698
14.4 Store a password in a properties file............................................................................699

14.5 Create a checksumTag(s): Security

Real's HowTo@www.rgagnon.com
14 Security
14.5 Create a checksumTag(s): Security.............................................................................702
14.6 Get the user nameTag(s): Applet Security...................................................................706
14.7 Get username using NT Challenge (NTLM)Tag(s): Security.......................................707
14.8 Check if the current user belongs a specific Windows group/roleTag(s): Security
Powerscript..........................................................................................................................709
14.9 Allow user:password in URLTag(s): Networking Security Common problems
WinAPI/Registry...................................................................................................................709
14.10 Prompt for password from the consoleTag(s): Security.............................................710
14.11 Prevent XSS exploitTag(s): Security..........................................................................711
14.12 Sanitize the input by removing suspicious tags.........................................................711
14.13 Sanitize the input based on a policy file.....................................................................712
14.14 Sanitize the output by removing suspicious characters.............................................712
14.15 Display a simple username/password Dialog from an AppletTag(s): Security..........713
15 Swing.........................................................................................................................................716
15.1 javaswing...................................................................................................................716
15.2 * Read me *Tag(s): Swing...........................................................................................716
15.3 Change component default fontTag(s): Swing.............................................................716
15.4 Repaint problem under the mouse cursor (JDK1.2)Tag(s): Swing..............................717
15.5 Set the LookAndFeelTag(s): Swing.............................................................................717
15.6 Use any LookAndFeel on any plateformTag(s): Swing................................................718
15.7 Use a TimerTag(s): Swing...........................................................................................719
15.8 Share ActionEvent handlerTag(s): Swing....................................................................719
15.9 Get default values for Swingbased user interfaceTag(s): Swing...............................721
15.10 Have a systray icon (Windows)Tag(s): Swing...........................................................722
15.11 Close a JFrame under conditionTag(s): Swing..........................................................724
15.12 Maximize a JFrameTag(s): Swing.............................................................................725
15.13 Capture System.out into a JFrameTag(s): Swing......................................................725
15.14 Remove the titlebar of JInternalFrameTag(s): Swing................................................728
15.15 Have borders on a JWindow/JFrameTag(s): Swing..................................................728
15.16 Display HTML in a JScrollPaneTag(s): Swing...........................................................729
15.17 Use a JOptionPaneTag(s): Swing..............................................................................730
15.18 Localize a JOptionPane dialogTag(s): Internationalization Swing.............................731
15.19 Customize JOptionPane buttonsTag(s): Swing.........................................................733
15.20 Localize a JFileChooserTag(s): Internationalization Swing.......................................733
15.21 Select a directory with a JFileChooserTag(s): Swing................................................736
15.22 Disable the JFileChooser's "New folder" buttonTag(s): Swing..................................737
15.23 Validate a filename from a JFileChooserTag(s): Swing.............................................739
15.24 Make a JFrame looks like a JDialogTag(s): Swing....................................................740
15.25 Make a JFrame always visibleTag(s): Swing.............................................................741
15.26 Show a JFrame on a specific screen in a dual monitor configuration Tag(s):
Swing..................................................................................................................................742
15.27 Make a JFrame not visible in the the TaskBar Tag(s): Swing....................................742
15.28 Based on JTextField content, enable or disable a JButtonTag(s): Swing..................743
15.29 Apply special filter to a JtextFieldTag(s): Swing........................................................744
15.30 Limit JTextField input to a maximum lengthTag(s): Swing........................................747
15.31 Validate a value on the lostFocus eventTag(s): Swing..............................................748
15.32 Make sure that my jTextfield has the focus when a JFrame is createdTag(s):
Swing..................................................................................................................................751

Real's HowTo@www.rgagnon.com
15 Swing
15.33 Stop the beep on JFormattedTextFieldTag(s): Swing...............................................752
15.34 Right justified JTextfield contentTag(s): Swing..........................................................752
15.35 Set the focus on a particuliar JTextFieldTag(s): Swing..............................................752
15.36 Make JTextField unselectableTag(s): Swing.............................................................753
15.37 Disable copy paste functionality on JTextFieldTag(s): Swing....................................754
15.38 Use a JTree to navigate in a siteTag(s): Swing.........................................................755
15.39 Expand or collapse a JTreeTag(s): Swing.................................................................761
15.40 Have a popup attached to a JTreeTag(s): Swing......................................................763
15.41 Traverse a JTreeTag(s): Swing.................................................................................765
15.42 Show dotted lines in a JTreeTag(s): Swing...............................................................767
15.43 Explore directories with a JTreeTag(s): Swing..........................................................768
15.44 Prevent JTree collapsingTag(s): Swing.....................................................................769
15.45 Single selection in a JTreeTag(s): Swing...................................................................769
15.46 Reduce JTree children indentationTag(s): Swing......................................................770
15.47 Use + or for JTree IconsTag(s): Swing...................................................................770
15.48 Change the JTable header colorTag(s): Swing.........................................................772
15.49 Double click on a JTableTag(s): Swing......................................................................773
15.50 Read a data file into a JTableTag(s): Swing..............................................................775
15.51 Disable row selection in a JTableTag(s): Swing........................................................777
15.52 Read a data file into a JTable and reload if data file have changedTag(s): Swing....777
15.53 Hide a column in JTableTag(s): Swing......................................................................780
15.54 Scroll a JTable to the last rowTag(s): Swing..............................................................781
15.55 Transfer a ResultSet to a JTableTag(s): JDBC Swing...............................................782
15.56 Have on a JScrollPane/JTable an horizontal JScrollbarTag(s): Swing......................782
15.57 Make a JList select an item on doubleclick or the ENTER keyTag(s): Swing............783
15.58 Make a JList like a scrolling text displayTag(s): Swing..............................................784
15.59 Have images in a JListTag(s): Swing.........................................................................785
15.60 Add a row and clear a JListTag(s): Swing.................................................................787
15.61 Sort a JListTag(s): Swing...........................................................................................788
15.62 Double click on a JListTag(s): Swing.........................................................................790
15.63 Have a PopUp on a JListTag(s): Swing.....................................................................791
15.64 Make a JLabel selectable with the mouseTag(s): Swing...........................................792
15.65 Change JLabel background colorTag(s): Swing........................................................793
15.66 Bold / Unbold a JLabelTag(s): Swing.........................................................................794
15.67 Multiline JLabelTag(s): Swing..................................................................................794
15.68 Underline a stringTag(s): Swing.................................................................................794
15.69 Update a JLabelTag(s): Swing...................................................................................795
15.70 Display a blinking JLabelTag(s): Swing.....................................................................796
15.71 Set the cursor position in a JTextAreaTag(s): Swing.................................................797
15.72 Have Multiline string in a JToolTipTag(s): Swing.....................................................798
15.73 Change Tooltip colorTag(s): Swing............................................................................798
15.74 Change a JTooltip fontTag(s): Swing.........................................................................798
15.75 Keep a JTooltip visibleTag(s): Swing.........................................................................799
15.76 Display icon associated with an executableTag(s): Swing........................................800
15.77 Have items in JMenubar at rightmost positionTag(s): Swing.....................................802
15.78 Have an JButton with an ImageTag(s): Swing...........................................................803
15.79 Trigger a click on a ButtonTag(s): AWT Swing..........................................................804

16 Thread

Real's HowTo@www.rgagnon.com
16 Thread........................................................................................................................................806
16.1 javathread..................................................................................................................806
16.2 Pipe the output of a thread to the input of another oneTag(s): Thread........................806
16.3 Pipe the output of a thread to the input of other threadsTag(s): Thread......................808
16.4 Wait the for the completion of a threadTag(s): Thread................................................810
16.5 Control a thread from outsideTag(s): Thread...............................................................811
16.6 Create a Timer objectTag(s): Thread...........................................................................812
16.7 Pause the executionTag(s): Thread.............................................................................813
16.8 Execute a method at a specified time intervalTag(s): Thread......................................814
16.9 Execute a process at regular intervalTag(s): Thread...................................................815
16.10 Handle concurrent read/writeTag(s): Thread.............................................................816
16.11 Communicate between threads using a QueueTag(s): Thread.................................818
16.12 Get a unique identifierTag(s): String/Number Thread Varia......................................823
16.13 Using java.rmi.dgc.VMID...........................................................................................823
16.14 Using java.util.UUID...................................................................................................823
16.15 Using Apache commons............................................................................................824
16.16 Using java.util.concurrent.AtomicLong.......................................................................824
17 Varia...........................................................................................................................................825
17.1 javavaria....................................................................................................................825
17.2 Use System time to generate unique IDTag(s): Date and Time Date and Time
Varia.....................................................................................................................................825
17.3 Get a unique identifierTag(s): String/Number Thread Varia........................................825
17.4 Using java.rmi.dgc.VMID.............................................................................................825
17.5 Using java.util.UUID.....................................................................................................826
17.6 Using Apache commons..............................................................................................826
17.7 Using java.util.concurrent.AtomicLong.........................................................................826
17.8 Get the hard disk serial number or Motherboard serial numberTag(s): Varia..............827
17.9 Motherboard serial number..........................................................................................827
17.10 Hard disk serial number.............................................................................................828
17.11 Sort an arrayTag(s): Language Varia........................................................................829
17.12 Sort a String arrayTag(s): Internationalization Varia..................................................831
17.13 Do a selection sortTag(s): Varia................................................................................833
17.14 Validate a Social Security Number (canadian)Tag(s): Varia......................................834
17.15 Validate a Credit Card NumberTag(s): Varia.............................................................835
17.16 Obtain from where a Class is loadedTag(s): Language Varia...................................838
17.17 Get the class name with or without the packageTag(s): Varia...................................839
17.18 See the generated bytecodeTag(s): Varia.................................................................841
17.19 Self replicating programsTag(s): Varia......................................................................843
17.20 A curiosity (strange Java code)Tag(s): Varia.............................................................844
17.21 Classic bugsTag(s): Varia..........................................................................................846
17.22 Number of the beast!Tag(s): Varia.............................................................................846
17.23 Use Java scripting engine (JDK 1.6)Tag(s): Varia.....................................................847
17.24 Pass or retrieve values from a scripting engine (jdk1.6)Tag(s): Varia.......................848
17.25 Preventing multiple instances of an applicationTag(s): Varia....................................850
17.26 Trap JVM shutdownTag(s): Varia..............................................................................854
17.27 Minimize all programs on Windows to show the DesktopTag(s): Varia.....................854
17.28 Display a progress indicator in the consoleTag(s): Varia...........................................855

Real's HowTo@www.rgagnon.com
18 XML............................................................................................................................................857
18.1 javaxml.......................................................................................................................857
18.2 Read meTag(s): XML...................................................................................................857
18.3 Display XML using plain HTMLTag(s): XML................................................................858
18.4 Transform XML into HTML using XSLTTag(s): XML...................................................859
18.5 Parse using SAX or DOMTag(s): XML........................................................................860
18.6 Parse an XML stringTag(s): XML.................................................................................863
18.7 Create an XML document with DOMTag(s): XML.......................................................864
18.8 Attach a stylesheet to an XML fileTag(s): XML............................................................865
18.9 Create an XML file and attach an XSLTag(s): XML XML............................................866
18.10 Nicely display WEB.XML informationsTag(s): Servlet/JSP XML Jaguar/EAServer...869
18.11 Serialize an object using XMLTag(s): XML................................................................871
18.12 Convert a flat file to XML (SAX)Tag(s): XML.............................................................872
18.13 Convert a flat file to XML (DOM)Tag(s): XML............................................................874
18.14 Convert a ResultSet to XMLTag(s): JDBC XML........................................................876
18.15 Parse with XPathTag(s): XML....................................................................................878
18.16 Strip extra spaces in a XML stringTag(s): XML.........................................................882
18.17 Create an XML file and attach an XSLTag(s): XML XML..........................................882
18.18 Use XML with PropertiesTag(s): Language XML.......................................................885
18.19 Change a particular node in XMLTag(s): XML...........................................................886
18.20 Validate XML using a DTDTag(s): XML.....................................................................887
18.21 Validate XML using a XSD (XML Schema)Tag(s): XML............................................891
18.22 Sanitize XML String Tag(s): XML...............................................................................896
18.23 Produce HTML entities when using XSLTTag(s): XML.............................................897
18.24 Create a RSS feed (part 1)Tag(s): XML....................................................................897
18.24.1 RSS 2.0.............................................................................................................898
18.24.2 Atom..................................................................................................................899
18.24.3 Creating a feed..................................................................................................900
18.24.4 Creating a feed with Apache Commons Digester.............................................900
18.24.5 Creating a feed with Rome................................................................................901
18.25 Creating an RSS Feed (part 2)Tag(s): XML..............................................................903
18.26 Parse a RSS XML fileTag(s): XML............................................................................908
18.26.1 Parsing a feed with Apache Commons Digester...............................................909
18.26.2 Parsing a feed with ROME................................................................................910
18.26.3 RSSUTIL.TLD.................................................................................................910
18.27 Add a Live bookmarkTag(s): XML.............................................................................911
18.28 Validate a RSS feedTag(s): XML...............................................................................911
18.29 Attach a CSS to RSS feedTag(s): XML.....................................................................911
19 DEPRECATED...........................................................................................................................914
19.1 javadeprecated..........................................................................................................914
19.2 * Read me * (this howto is deprecated)Tag(s): DEPRECATED.................................914
19.3 Keep the console open after execution (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................914
19.4 Read the Registry (this howto is deprecated)Tag(s): DEPRECATED.........................915
19.5 Call a Win API (this howto is deprecated)Tag(s): DEPRECATED...............................916
19.6 Display a BMP image (this howto is deprecated)Tag(s): DEPRECATED...................917
19.7 Play a WAV audio file (this howto is deprecated)Tag(s): DEPRECATED...................918
19.8 Detect if the MS JVM is used (this howto is deprecated)Tag(s): DEPRECATED........919
19.9 Get the latest MS JVM (this howto is deprecated)Tag(s): DEPRECATED..................919

19.10 Uninstalling the MS JVM (this howto is deprecated)Tag(s): DEPRECATED

Real's HowTo@www.rgagnon.com
19 DEPRECATED
19.10 Uninstalling the MS JVM (this howto is deprecated)Tag(s): DEPRECATED.............919
19.11 Wrap a Java class in a COM object (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................920
19.12 Sign an applet (this howto is deprecated)Tag(s): DEPRECATED.............................921
19.13 Bypass the need for a certificate (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................922
19.14 Start an executable on the client (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................923
19.15 Get rid of the message "Warning unsigned applet window" (this howto is
deprecated)Tag(s): DEPRECATED....................................................................................924
19.16 Read/write a local file from an Applet (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................924
19.17 Write "otherbrowserfriendly" code when using the Netscape Capabilities
package (this howto is deprecated)Tag(s): DEPRECATED...............................................926
19.18 Disable the JIT compiler in Netscape or IE (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................926
19.19 Start automatically JAVA when opening Netscape (this howto is deprecated)
Tag(s): DEPRECATED........................................................................................................927
19.20 Use Netscape Java Console hidden commands (this howto is deprecated)
Tag(s): DEPRECATED........................................................................................................927
19.21 Avoid the Netscape "Couldn't connect to '' with origin from
'localclasspathclasses'" message. (this howto is deprecated)Tag(s): DEPRECATED...928
19.22 Get the client IP address (deprecated)Tag(s): DEPRECATED.................................928
19.23 Detect the browser/JVM type (deprecated)Tag(s): Environment DEPRECATED.....929
19.24 Post a message on a newsserver using NNTP protocol (this howto is
deprecated)Tag(s): DEPRECATED....................................................................................931
19.25 Read messages from a newsserver (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................932
19.26 Get a list of headers from a newsgroup (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................933
19.27 Get a list of all available newsgroup from a newsserver (this howto is
deprecated)Tag(s): DEPRECATED....................................................................................934
19.28 Detect if Swing is installed (this howto is deprecated)Tag(s): DEPRECATED..........935
19.29 Make Swing always available from Netscape (this howto is deprecated)Tag(s):
DEPRECATED...................................................................................................................935
19.30 Send email with attachment (DEPRECATED)Tag(s): DEPRECATED......................936
20 String/Number...........................................................................................................................937
20.1 javastringnumber.......................................................................................................937
20.2 * Read me *Tag(s): Language String/Number.............................................................937
20.3 Convert from type X to type YTag(s): String/Number String/Number..........................938
20.4 Strip certain characters from a StringTag(s): String/Number.......................................940
20.5 Replace/remove character in a StringTag(s): String/Number......................................941
20.6 Replace every occurences of a string within a stringTag(s): String/Number...............943
20.7 "Tokenize" a stringTag(s): String/Number...................................................................944
20.8 Split a string using String.split()Tag(s): String/Number................................................949
20.9 Optimize String operationsTag(s): String/Number.......................................................952
20.9.1 StringBuilder (JDK1.5)........................................................................................954
20.10 Remove spaces from a stringTag(s): String/Number.................................................954

Real's HowTo@www.rgagnon.com
20 String/Number
20.11 Test if a String starts with a digit or uppercase letterTag(s): String/Number.............955
20.12 Get InputStream from a StringTag(s): String/Number...............................................956
20.13 Easy String paddingTag(s): String/Number...............................................................956
20.14 Replace \r\n with the <br> tagTag(s): String/Number................................................958
20.15 Unaccent lettersTag(s): Internationalization String/Number......................................958
20.15.1 Using java.text.Normalizer................................................................................959
20.15.2 Using String.replaceAll()...................................................................................959
20.15.3 The String.indexOf()..........................................................................................960
20.16 Apply a mask to StringTag(s): String/Number...........................................................962
20.17 Format a String (JDK1.5)Tag(s): String/Number.......................................................963
20.18 Replace a "\" by "\\"Tag(s): String/Number................................................................964
20.19 Substitute tokens in a StringTag(s): String/Number...................................................965
20.20 Compare accentuated lettersTag(s): Internationalization String/Number..................965
20.21 Create a String with fixed length and filled with a specific characterTag(s):
String/Number.....................................................................................................................967
20.22 Unquote a StringTag(s): String/Number....................................................................967
20.23 Escape HTML special characters from a StringTag(s): String/Number.....................968
20.24 Unescape HTML special characters from a StringTag(s): String/Number.................970
20.25 Using HashMap.........................................................................................................970
20.26 Using Array................................................................................................................972
20.27 Detect nonASCII character in a StringTag(s): Internationalization
String/Number......................................................................................................................974
20.28 Remove HTML tags from a file to extract only the TEXTTag(s): IO
String/Number Networking...................................................................................................975
20.29 Using regular expression...........................................................................................975
20.30 Using javax.swing.text.html.HTMLEditorKit...............................................................976
20.31 Using an HTML parser...............................................................................................977
20.32 Using Apache Tika.....................................................................................................977
20.33 Extract links from an HTML pageTag(s): String/Number Networking........................978
20.34 Using javax.swing.text.html.HTMLEditorKit...............................................................978
20.35 Using an HTML parser...............................................................................................979
20.36 Convert a byte array to a Hex stringTag(s): String/Number.......................................980
20.37 Apply proper uppercase and lowercase on a StringTag(s): String/Number...............981
20.38 Encode/Decode to/from Base64Tag(s): String/Number Networking.........................982
20.39 Using javax.mail.internet.MimeUtility.........................................................................982
20.40 Using Apache Commons Codec................................................................................983
20.41 MiGBase64................................................................................................................984
20.42 Justify a string with wordwrapTag(s): String/Number................................................984
20.43 Shorten a long pathTag(s): IO String/Number...........................................................985
20.44 Ellipse a StringTag(s): String/Number.......................................................................989
20.45 Display Ascii Banner Tag(s): String...........................................................................990
20.46 Convert from type X to type YTag(s): String/Number String/Number........................991
20.47 Type conversion (JDK1.5)Tag(s): String/Number......................................................993
20.48 Round a doubleTag(s): String/Number......................................................................994
20.49 Display numbers with commasTag(s): String/Number...............................................995
20.50 Display numbers in scientific notationTag(s): String/Number....................................996
20.51 Display numbers with leading zeroesTag(s): String/Number.....................................997
20.52 Get a random numberTag(s): String/Number............................................................999
20.53 Convert an UNSIGNED byte to a JAVA typeTag(s): String/Number.........................999

20.54 Deal with bigendian and littleendian orderTag(s): String/Number

Real's HowTo@www.rgagnon.com
20 String/Number
20.54 Deal with bigendian and littleendian orderTag(s): String/Number.......................1000
20.55 Pass an integer by referenceTag(s): String/Number...............................................1001
20.56 Pass floats as string literals to a methodTag(s): String/Number..............................1001
20.57 Get random numbersTag(s): String/Number...........................................................1002
20.58 Convert number into wordsTag(s): String/Number..................................................1002
20.59 Arithmetic with doubleTag(s): String/Number..........................................................1011
20.60 Detect even/odd numberTag(s): String/Number......................................................1011
20.61 Convert bytes to megabytesTag(s): String/Number.................................................1012
20.62 Validate a numberTag(s): String/Number................................................................1012
20.63 Get a unique identifierTag(s): String/Number Thread Varia....................................1013
20.64 Using java.rmi.dgc.VMID.........................................................................................1013
20.65 Using java.util.UUID.................................................................................................1014
20.66 Using Apache commons..........................................................................................1014
20.67 Using java.util.concurrent.AtomicLong.....................................................................1014
20.68 Validate/Convert a number using the current Locale()Tag(s):
Internationalization String/Number....................................................................................1015
20.69 Convert a fraction to a DoubleTag(s): String/Number..............................................1016
21 Open Source...........................................................................................................................1018
21.1 javaos......................................................................................................................1018
21.2 Call Windows API (Open source solution)Tag(s): JNI Open Source.........................1018
21.3 Call COM objectTag(s): Open Source.......................................................................1018
21.4 com4j.........................................................................................................................1018
21.5 jinterop.....................................................................................................................1019
21.6 jxchange..................................................................................................................1019
21.7 Run JAVA as a Windows serviceTag(s): Environment Open Source........................1019
21.8 Create entityrelation diagramTag(s): Open Source Open Source...........................1020
21.9 Java Remote desktop toolTag(s): Open Source........................................................1020
21.10 Create entityrelation diagramTag(s): Open Source Open Source.........................1021
21.11 Launch a java program as a Windows EXE fileTag(s): Open Source.....................1021
21.12 WinRun4J................................................................................................................1021
21.13 JSmooth...................................................................................................................1022
21.14 Launch4J.................................................................................................................1022
21.15 Handle CSV fileTag(s): IO Open Source.................................................................1022
21.16 com.Ostermiller.util CSV Utils..................................................................................1023
21.17 opencsv....................................................................................................................1023
21.18 ServingXML.............................................................................................................1023
21.19 Super CSV...............................................................................................................1023
21.20 csvreader.................................................................................................................1023
21.21 CSVFile....................................................................................................................1023
21.22 FlatPack...................................................................................................................1023
21.23 CSVJDBC................................................................................................................1023
21.24 FFP..........................................................................................................................1023
21.25 Handle Excel filesTag(s): IO JDBC Open Source....................................................1024
21.26 JDBCODBC Excel driver.......................................................................................1024
21.27 JExcel......................................................................................................................1024
21.28 POI...........................................................................................................................1025
21.29 JXLS........................................................................................................................1025
21.30 xlSQL.......................................................................................................................1026

Real's HowTo@www.rgagnon.com
21 Open Source
21.31 JCOM.......................................................................................................................1027
21.32 OpenXLS Java Spreadsheet SDK...........................................................................1028
21.33 Browse a Queue (JMS/MQ)Tag(s): Open Source...................................................1030
21.34 Convert a .class to .java file (decompiler)Tag(s): Open Source..............................1030
21.35 Jad...........................................................................................................................1030
21.36 JadClipse.................................................................................................................1031
21.37 JD Java decompiler..............................................................................................1031
21.38 JarPlug.....................................................................................................................1031
21.39 Deploy an application as only 1 jarTag(s): Open Source.........................................1032
21.40 OneJar...................................................................................................................1032
21.41 Fat Jar......................................................................................................................1032
21.42 Read an Outlook MSG fileTag(s): Networking Open Source...................................1032
21.43 Apache POI HSMF..................................................................................................1033
21.44 msgparser................................................................................................................1035
21.45 jmbox.......................................................................................................................1035
21.46 File/directory polling to detect changeTag(s): IO Open Source...............................1036
21.47 jpoller (directory poller)............................................................................................1036
21.48 JNotify......................................................................................................................1036
21.49 Java Native Access (JNA).......................................................................................1036
21.50 Call native methods in a DLL from Java (NativeCall)..............................................1036
21.51 Java 7......................................................................................................................1037
21.52 The simple (and naive!) approach...........................................................................1037
21.53 Clear the console and control attributesTag(s): IO Open Source............................1037
21.54 Jansi.........................................................................................................................1037
21.55 JCurses....................................................................................................................1038
21.56 Disable Checkstyle from code Tag(s): OpenSource................................................1039
21.57 Create or process a PDF fileTag(s): IO Open Source.............................................1040
21.58 Create a PDFTag(s): IO Open Source.....................................................................1042
21.59 iText.........................................................................................................................1042
21.60 Split a PDF file (using iText)Tag(s): IO Open Source..............................................1043
21.61 Concatenate PDF files (using iText)Tag(s): IO Open Source..................................1045
21.62 Convert TIF to PDFTag(s): AWT IO IO Open Source..............................................1046
21.63 Convert HTML to PDF using iTextTag(s): IO Open Source.....................................1048
21.64 Convert HTML to PDF using YAHP Tag(s): IO OpenSource...................................1050
21.65 Convert a png/jpg/gif file to PDF using iTextTag(s): IO Open Source.....................1052
21.66 Print a PDFTag(s): IO Open Source........................................................................1053
21.67 Extract text from a PDF (with Apache Tika) Tag(s): IO OpenSource......................1053
21.68 Detect and remove blank page in pdf (iText)Tag(s): PDF.......................................1054

1 Applet
1.1 javaapplet

1.2 Goto to a new URL from an AppletTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0002.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"
"_parent"
"_top"
"_blank"

current frame
parent frame
base frame
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
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
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 loadedTag(s):


Applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0003.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 lineTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0010.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;

1.3 Determine the host from where the Applet is loadedTag(s): Applet

int width;
public void init(){
message = getParameter("message");
if(message == null)
message = " Isn't scrolling text in the status line annoying? ";
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

1.3 Determine the host from where the Applet is loadedTag(s): Applet

}
catch(InterruptedException e){
break;
}
}
}
}

Try it here.

1.5 Use a search engineTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0011.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;

1.5 Use a search engineTag(s): Applet

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;
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 onscreen clockTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0012.html
import
import
import
import

java.applet.*;
java.awt.*;
java.util.*;
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;

1.6 Have an onscreen clockTag(s): Applet

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
(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="yyyyMMdd hh:mm:ss">
</APPLET><P>
<APPLET CODE="MyClock.class"
HEIGHT=25 WIDTH=200>
<PARAM NAME="format" VALUE="h:mm a">

1.6 Have an onscreen clockTag(s): Applet

</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.7 Have Applets on the same page communicate with each


otherTag(s): Applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0022.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;
}
}

1.7 Have Applets on the same page communicate with each otherTag(s): Applet

[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" );
}
}

[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


otherTag(s): Applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0023.html
It is possible to share data between different applets via static variables
[HTML (java0023.html)]
<HTML><HEAD></HEAD>
<FRAMESET COLS="50%,*">
<FRAME SRC="java0023f1.html" NAME="f1">
<FRAME SRC="java0023f2.html" NAME="f2">
</FRAMESET>
</HEAD>

1.8 Have Applets on different frames communicates with each otherTag(s): Applet

[HTML (java0023f1.html AND java0023f2.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);
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 Howto.

1.8 Have Applets on different frames communicates with each otherTag(s): Applet

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


different pageTag(s): Applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0041.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
import
import
import

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

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

1.9 Send a message from an Applet to another Applet on a different pageTag(s): Applet

SecondApplet.java
import java.applet.*;
import java.awt.*;
import java.net.*;
public class
public void
Label l =
add (l);
TextField
add(tf);

SecondAppletJ extends Applet {


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

// 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).
you to convert from a MIME format called "xwwwformurlencoded"
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 3character
strings which begin with the percent sign,
"%xy", where xy is the twodigit hexadecimal
representation of the lower 8bits 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
Howto.

1.9 Send a message from an Applet to another Applet on a different pageTag(s): Applet

1.10 Have an applet launch an other appletTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0025.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;
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) {

1.10 Have an applet launch an other appletTag(s): Applet

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);
}
}

try it here.

1.11 Get the user nameTag(s): Applet Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0048.html
In application :
public class Test {
public static void main(String args[]) {
System.out.println( System.getProperty("user.name") );
}
}

will print the current user. You can't use this technique to secure your application since it is very to
spoof.
1.11 Get the user nameTag(s): Applet Security

You just need to specify a "user.name" from the command line.


> java Duser.name=Elvis Test
Elvis

As an alternative with 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());
System.out.println(NTSystem.getDomain());
}
}

In Applet there is no way unless you ask for it or use a signed applet. If you have access to a
serverside, something like an ASP page can be used to detect the current NT user name if the
client and the server are configured correcty (SSO).
See this related HowTo for a JSP hack!

1.12 Access parameters passed in the URLTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0049.html
import
import
import
import

java.applet.Applet;
java.io.UnsupportedEncodingException;
java.util.HashMap;
java.util.Map;

@SuppressWarnings("serial")
public class AppletUrlParams extends Applet {
HashMap<String,String> parmsMap ;
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 map for easy reference.
ex. String name = parmsMap.get("name")
*/
try {
doit();
dumpMap(parmsMap);

1.12 Access parameters passed in the URLTag(s): Applet

//System.out.println("name is " + parmsMap.get("name"));


}
catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void doit() throws UnsupportedEncodingException {
String completeURL = getDocumentBase().toString();
System.out.println("Complete URL: " + completeURL);
int i = completeURL.indexOf("?");
if (i > 1) {
String searchURL = completeURL.substring(completeURL.indexOf("?") + 1);
System.out.println("Search URL: " + searchURL);
initMap(searchURL);
}
}
public void initMap(String search) throws UnsupportedEncodingException {
parmsMap = new HashMap<String,String>();
String params[] = search.split("&");
for (String param : params) {
String temp[] = param.split("=");
parmsMap.put(temp[0], java.net.URLDecoder.decode(temp[1], "UTF8"));
}
}
public void dumpMap(Map<?,?> map) {
System.out.println("");
for (Map.Entry<?,?> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
System.out.println("");
}
}

Test it here.
The result 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: Netscape won't return the whole URL, but only domain name and directory but without
.html and parameters. In IE and Firefox, it's ok.
So if we have www.domain.com/applets/win.html?winner=Maurice
Then getDocumentBase () returns :
NS: www.domain.com/applets/
IE: www.domain.com/applets/win.html?winner=Maurice

1.12 Access parameters passed in the URLTag(s): Applet

1.13 Convert an Applet to Application Tag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0305.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);

1.13 Convert an Applet to Application Tag(s): Applet

f.pack();
ut.init();
f.setSize(100,100 + 20); // add 20, seems enough for the Frame title,
f.show();
}
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 AppletTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0228.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.14 Change the mouse cursor in AppletTag(s): Applet

1.15 Use an Image as the Applet backgroundTag(s): Applet AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0233.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>

1.15 Use an Image as the Applet backgroundTag(s): Applet AWT

/HMTL

Try it here.

1.16 Handle the new Control Activation mechanism in IETag(s):


Applet
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0526.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 prerelease versions of Windows
Vista SP1 and Windows XP SP3. More at IEBlog
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.

1.16 Handle the new Control Activation mechanism in IETag(s): Applet

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>
<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/internetexplorerflashappletactivationfixxidc19237.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
1.16.2 Solution #2

fact that the Java plugin is an ActiveX. PreXP 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 serverside.
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
('
<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 %>">
<%
}
%>

1.16.3 Solution #3

<script>
writeFooter();
/script

1.17 Pass parameters to the Applet JVM (WIN)Tag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0531.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
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.

1.17 Pass parameters to the Applet JVM (WIN)Tag(s): Applet

1.18 See the Java Console Window Log (Java plugin)Tag(s):


Applet Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0533.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.19 Display debugging infos for an AppletTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0597.html
Make sure that all browsers and JRE are closed. Start the Java Configuration Panel via
StartParameters 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

1.18 See the Java Console Window Log (Java plugin)Tag(s): Applet Environment

1.20 Have an invisible Applet Tag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0620.html
See this interesting article :
http://windyroad.org/2006/08/14/reintroducingjavascriptandhiddenappletsjaha/
The recommended way is to a CSS style to hide the Applet,
<applet id="applet_name"
code="path_to_applet_class/class_name"
style="width: 1px; height: 1px; float: left;"
mayscript></applet>

.. or you can insert your Applet into an invisible frame. See this HowTo for an example.

1.21 Keep the JVM loadedTag(s): Applet


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javakeepthejvmloaded.html
The default Java plugin setting is when the first applet is invoked in a browser, the JVM starts
automatically. If you open further tabs or windows with applets and the previous applet is still
running, the new applets use the same JVM as the first one.
After the last running applet is closed (leave the page where it is embedded to or close the tab or
window), the JVM stops automatically.
After then, when you navigate to a page where an applet is located, a new JVM is launched. To
override this behavior you use a special parameter in the initial applet.
<PARAM NAME="legacy_lifecycle" VALUE="true">

or you unselect the new generation Java plugin option in the Java Panel.

1.22 Detect browser type from an AppletTag(s):


Applet Environment Javascript interaction
1.20 Have an invisible Applet Tag(s): Applet

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javadetectbrowsertypefromanapplet.html

1.23 Call a Javascript from the Applet


With LiveConnect, we call a javascript to return the "UserAgent".
To compile, make sure that you have the plugin.jar in the classpath (or Eclipse Build Path). This
jar is usually located in [JRE]/lib folder. During runtime, it's already included by the Java plugin so
you don't have to worry about that.
The Java class
import
import
import
import

java.applet.*;
java.awt.event.*;
java.awt.*;
netscape.javascript.*;

public class GetUserAgent extends Applet


implements ActionListener {
private static final long serialVersionUID = 1L;
TextField tf;
Button b1;
JSObject win;
public void init(){
setLayout(new FlowLayout());
tf = new TextField(35);
b1 = new Button("get useragent from javascript");
b1.addActionListener(this);
add(tf);add(b1);
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == b1) {
JSObject win = (JSObject)JSObject.getWindow(this);
tf.setText((String)win.eval("getUserAgent();"));
}
}
}

Don't forget the MAYSCRIPT parameter in the APPLET tag, it's required since the Applet is using
the JSObject to interact with the Javascript.
<html>
<head>
<script>
function getUserAgent() {
return navigator.userAgent;
}
</script>
</head><body>
<applet code="GetUserAgent.class" MAYSCRIPT height=100 width=500></Applet>
</body>
</html>

1.23 Call a Javascript from the Applet

Try it here
You need to parse the returned value to detect browser type. Look at this utility,
http://code.google.com/p/useragentutils/ or at this code :
http://nerds.palmdrive.net/useragent/code.html to get the idea.

1.24 Get the value from the serverside


When serving the HTML containing the Applet, you add the UserAgent as parameter for the
Applet.
In a JSP/EL
<applet ... >
<param ... >
<param name="userAgent" value="${header['useragent']}" />
</applet>

and in the Applet


String userAgent = getParameter("userAgent");

and parse the returned value...

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

1.24 Get the value from the serverside

2 Date and Time


2.1 javadate

2.2 Have year on 4 digits from a Date objectTag(s): Date and


Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0096.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 TimeTag(s): Date and Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0106.html
import java.util.Calendar;
import java.text.SimpleDateFormat;
public class DateUtils {
public static final String DATE_FORMAT_NOW = "yyyyMMdd 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;

2 Date and Time

public class DateUtils {

public static String now(String dateFormat) {


Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
return sdf.format(cal.getTime());
}
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 datesTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0097.html
One technique is to compute by hand the number of milliseconds between two dates and then
convert the result in days.
import java.util.*;

public class DateUtils {


private DateUtils() { }
static final long ONE_HOUR = 60 * 60 * 1000L;
public static long daysBetween(Date d1, Date d2){
return ( (d2.getTime() d1.getTime() + ONE_HOUR) /
(ONE_HOUR * 24));
}
/*
testing
*/
public static void main(String[] args) {
java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat("yyyyMMdd");

2.4 Compute days between 2 datesTag(s): Date and Time

Calendar first = Calendar.getInstance();


first.set(2008, Calendar.AUGUST, 1);
Calendar second = Calendar.getInstance();
System.out.println
(daysBetween(first.getTime(),second.getTime())
+ " day(s) between "
+ sdf.format(first.getTime()) + " and "
+ sdf.format(second.getTime()));
/*
* output :
*
21 day(s) between 20080801 and 20080822
*/
}
}
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.

Another 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.
The package java.util.concurrent.TimeUnit; provides a class to make conversion between
milliseconds and days easier.
import java.util.*;
import java.util.concurrent.TimeUnit;
public class DateUtils {
private DateUtils() { }
public static long getDifference(Calendar a, Calendar b, TimeUnit units) {
return
units.convert(b.getTimeInMillis() a.getTimeInMillis(), TimeUnit.MILLISECONDS);
}
/*
testing
*/
public static void main(String[] args) {
java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat("yyyyMMdd");
Calendar augustfirst2008 = Calendar.getInstance();
augustfirst2008.set(2008, Calendar.AUGUST, 1); // 20080801
Calendar today = Calendar.getInstance();
// today
System.out.println
(getDifference(augustfirst2008,today,TimeUnit.DAYS)
+ " day(s) between "
+ sdf.format(augustfirst2008.getTime()) + " and "
+ sdf.format(today.getTime()));
}
/*
* output :
*
921 day(s) between 20080801 and 20110208
*/
}

2.4 Compute days between 2 datesTag(s): Date and Time

2.5 Get the number of days in a monthTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0098.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 dateTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0099.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); // YYYYMMDD
df.setLenient(false);
// this is important!
df.parse(date);
}
catch (ParseException e) {
return false;
}
catch (IllegalArgumentException e) {

2.5 Get the number of days in a monthTag(s): Date and Time

return false;
}
return true;
}
public static void main(String[] args) {
System.out.println(" 19001213 valid ? "
+ DateUtils.isValidDateStr("19001213"));
// "199012/13" throws a ParseException
System.out.println(" 190012/13 valid ? "
+ DateUtils.isValidDateStr("190012/13"));
// "19901312" throws a IllegalArgumentException
System.out.println(" 19001312 valid ? "
+ DateUtils.isValidDateStr("19001312"));
/*
* output :
* 19001213 valid ? true
* 190012/13 valid ? false
* 19001312 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(" 19001213 valid ? "
+ DateUtils.isValidDateStr("19001213","yyyyMMdd"));
// "199012/13" throws a ParseException
System.out.println(" 190012/13 valid ? "
+ DateUtils.isValidDateStr("190012/13","yyyyMMdd"));
// "19901312" throws a IllegalArgumentException
System.out.println(" 19001312 valid ? "
+ DateUtils.isValidDateStr("19001312","yyyyMMdd"));
/*
* output :
* 19001213 valid ? true
* 190012/13 valid ? false
* 19001312 valid ? false
*/
}

2.5 Get the number of days in a monthTag(s): Date and Time

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 weekTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0100.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.6.2 Using GregorianCalendar

2.8 Add/Substract Day/Month/Year to a DateTag(s): Date and


Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0101.html
add() and roll() are used to add or substract values to a Calendar object.
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".
import java.util.Calendar;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
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);
// or Calendar.DAY_OF_MONTH which is a synonym
System.out.println("Date + 20 days is : " + sdf.format(c1.getTime()));
/*
* output :
* Date is : 19990120
* Date + 20 days is : 19990209
*/
}
}

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.
import java.util.Calendar;
import java.text.SimpleDateFormat;
public class Test {
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Calendar c1 = Calendar.getInstance();
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 : "

2.8 Add/Substract Day/Month/Year to a DateTag(s): Date and Time

+ sdf.format(c1.getTime()));
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()));
/*
* output :
* Date is : 19990120
* Date roll down 1 month : 19991220
* Date is : 19990120
* Date minus 1 month : 19981220
*/
}
}

2.9 Get the correct TimeZone on DateFormatTag(s): Date and


Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0102.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
df.setCalendar(Calendar.getInstance());
System.out.println("Good TimeZone from DateFormat : " +
df.getTimeZone.getID());

2.10 Simply format a date as "YYYYMMDD"Tag(s): Date and


Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0103.html
The format "YYYYMMDD" can be useful when sorting records or comparing 2 dates.
2.9 Get the correct TimeZone on DateFormatTag(s): Date and Time

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 datesTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0104.html
import java.util.*;
import java.util.*;
import java.text.*;
public class TestDate {
public static void main(String args[]){
String DATE_FORMAT = "yyyyMMdd";
java.text.SimpleDateFormat sdf =
new java.text.SimpleDateFormat(DATE_FORMAT);
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
// remember months are zerobased : 0 jan 1 feb ...
c1.set(1999, 11 , 31);
c2.set(1999, 0 , 30);
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 ");
}

2.11 Compare 2 datesTag(s): Date and Time

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


objectTag(s): Date and Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0105.html
import
import
import
import

java.util.Date;
java.util.Locale;
java.util.Calendar;
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
("ddMMMyyyy 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 = "24Feb1998 17:39:35";
System.out.println("Timestamp : " + timestampToParse);
SimpleDateFormat sdf =
new java.text.SimpleDateFormat("yyyyMMdd HH:mm:ss");
System.out.println("Calendar : "
+ sdf.format(parseTimestamp(timestampToParse).getTime()));
/*
output :
Timestamp : 24Feb1998 17:39:35
Calendar : 19980224 17:39:35
*/
}
}

2.12 Parse a String to obtain a Date/GregorianCalendar objectTag(s): Date and Time

2.13 Use System time to generate unique IDTag(s): Date and


Time Date and Time Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0385.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 nameTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0403.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
("19891017 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) {

2.13 Use System time to generate unique IDTag(s): Date and Time Date and Time Varia

e.printStackTrace();
return "";
}
}
}

An alternate way :
import
import
import
import

java.util.Calendar;
java.text.SimpleDateFormat;
java.text.DateFormat;
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 formatTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0413.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());
}
}

2.15 Find the current date formatTag(s): Date and Time

2.16 Get a julian dateTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0506.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. and will end on January
22, 3268 (32680122 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.
* 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;

2.16 Get a julian dateTag(s): Date and Time

ja = (int) julian
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[]) {
// 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 20050101 and 20050131 : "
+ (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 20050101 and 20050131 : 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.

2.16 Get a julian dateTag(s): Date and Time

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
dayofyear number. For example, 17July1998 is stored as 98221, since 17July is the 221th
day of the year. This format is not really useful since Y2K! The main reason for using the 5digits
Julian date was to save disk space and still have a format easy to use to handle. dates.
A variation of this idea is to used the first four digits for the year and 3 digits for dayofyear,
17July1998 will be represented by 1998221.
This is a very simple format which can be manipulated easily from Java.
import
import
import
import

java.util.Calendar;
java.util.Date;
java.text.ParseException;
java.text.SimpleDateFormat;

public class DateUtils {


private DateUtils() { }
public static Date getDateFromJulian7(String julianDate)
throws ParseException
{
return new SimpleDateFormat("yyyyD").parse(julianDate);
}
public static String getJulian7FromDate(Date date) {
StringBuilder sb = new StringBuilder();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return

sb.append(cal.get(Calendar.YEAR))
.append(String.format("%03d", cal.get(Calendar.DAY_OF_YEAR)))
.toString();

}
public static void main(String[] args) throws Exception {
String test = "1998221";
Date d = DateUtils.getDateFromJulian7(test);
System.out.println(d);
System.out.println(DateUtils.getJulian7FromDate(d));
/*
* output :
*
Sun Aug 09 00:00:00 EDT 1998
*
1998221
*/
}
}

2.16 Get a julian dateTag(s): Date and Time

2.17 Calculate the ageTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0547.html
import java.util.GregorianCalendar;
import java.util.Calendar;
public class CalcAge {
public static void main(String [] args) {
// remember ... months are 0based : jan=0 feb=1 ...
System.out.println
("19621111 : " + age(1962,10,11));
System.out.println
("19991203 : " + 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 milliseconds into a humanreadable


formatTag(s): Date and Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0585.html
Given a time in ms, this HowTo will output the long form "<w> days, <x> hours, <y> minutes and (z)
seconds" and the short form "<dd:>hh:mm:ss".
public class TimeUtils {
public final static long ONE_SECOND = 1000;
public final static long SECONDS = 60;
public final static long ONE_MINUTE = ONE_SECOND * 60;
public final static long MINUTES = 60;
public final static long ONE_HOUR = ONE_MINUTE * 60;
public final static long HOURS = 24;

2.17 Calculate the ageTag(s): Date and Time

public final static long ONE_DAY = ONE_HOUR * 24;


private TimeUtils() {
}
/**
* converts time (in milliseconds) to humanreadable format
* "<w> days, <x> hours, <y> minutes and (z) seconds"
*/
public static String millisToLongDHMS(long duration) {
StringBuffer res = new StringBuffer();
long temp = 0;
if (duration >= ONE_SECOND) {
temp = duration / ONE_DAY;
if (temp > 0) {
duration = temp * ONE_DAY;
res.append(temp).append(" day").append(temp > 1 ? "s" : "")
.append(duration >= ONE_MINUTE ? ", " : "");
}
temp = duration / ONE_HOUR;
if (temp > 0) {
duration = temp * ONE_HOUR;
res.append(temp).append(" hour").append(temp > 1 ? "s" : "")
.append(duration >= ONE_MINUTE ? ", " : "");
}
temp = duration / ONE_MINUTE;
if (temp > 0) {
duration = temp * ONE_MINUTE;
res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
}
if (!res.toString().equals("") &duration >= ONE_SECOND) {
res.append(" and ");
}
temp = duration / ONE_SECOND;
if (temp > 0) {
res.append(temp).append(" second").append(temp > 1 ? "s" : "");
}
return res.toString();
} else {
return "0 second";
}
}
/**
* converts time (in milliseconds) to humanreadable format
* "<dd:>hh:mm:ss"
*/
public static String millisToShortDHMS(long duration) {
String res = "";
duration /= ONE_SECOND;
int seconds = (int) (duration % SECONDS);
duration /= SECONDS;
int minutes = (int) (duration % MINUTES);
duration /= MINUTES;
int hours = (int) (duration % HOURS);
int days = (int) (duration / HOURS);
if (days == 0) {
res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
} else {

2.17 Calculate the ageTag(s): Date and Time

res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);


}
return res;
}
public static void main(String args[]) {
System.out.println(millisToLongDHMS(123));
System.out.println(millisToLongDHMS((5 * ONE_SECOND) + 123));
System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR));
System.out.println(millisToLongDHMS(ONE_DAY + 2 * ONE_SECOND));
System.out.println(millisToLongDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
System.out.println(millisToLongDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
+ (2 * ONE_MINUTE) + ONE_SECOND));
System.out.println(millisToLongDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
+ ONE_MINUTE + (23 * ONE_SECOND) + 123));
System.out.println(millisToLongDHMS(42 * ONE_DAY));
/*
output :
0 second
5 seconds
1 day, 1 hour
1 day and 2 seconds
1 day, 1 hour, 2 minutes
4 days, 3 hours, 2 minutes and 1 second
5 days, 4 hours, 1 minute and 23 seconds
42 days
*/
System.out.println(millisToShortDHMS(123));
System.out.println(millisToShortDHMS((5 * ONE_SECOND) + 123));
System.out.println(millisToShortDHMS(ONE_DAY + ONE_HOUR));
System.out.println(millisToShortDHMS(ONE_DAY + 2 * ONE_SECOND));
System.out
.println(millisToShortDHMS(ONE_DAY + ONE_HOUR + (2 * ONE_MINUTE)));
System.out.println(millisToShortDHMS((4 * ONE_DAY) + (3 * ONE_HOUR)
+ (2 * ONE_MINUTE) + ONE_SECOND));
System.out.println(millisToShortDHMS((5 * ONE_DAY) + (4 * ONE_HOUR)
+ ONE_MINUTE + (23 * ONE_SECOND) + 123));
System.out.println(millisToShortDHMS(42 * ONE_DAY));
/*
output :
00:00:00
00:00:05
1d01:00:00
1d00:00:02
1d01:02:00
4d03:02:01
5d04:01:23
42d00:00:00
*/
}
}

Using java.util.concurrent.TimeUnit
import java.util.concurrent.TimeUnit;
...
/**
* converts time (in milliseconds) to humanreadable format
* "<dd:>hh:mm:ss"
*/

2.17 Calculate the ageTag(s): Date and Time

public static String millisToShortDHMS(long duration) {


String res = "";
long days = TimeUnit.MILLISECONDS.toDays(duration);
long hours = TimeUnit.MILLISECONDS.toHours(duration)
TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
if (days == 0) {
res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
else {
res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);
}
return res;
}

2.19 Get the atomic timeTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0589.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/timeservers.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 denialofservice attack.
import
import
import
import

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

public final class DateUtils {


// NIST, Boulder, Colorado (timea.timefreq.bldrdoc.gov)
public static final String ATOMICTIME_SERVER="http://132.163.4.101:13";
// NIST, Gaithersburg, Maryland (timea.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;

2.19 Get the atomic timeTag(s): Date and Time

}
}
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 daylightsavingtime
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;
}
finally {
if (in != null) {
in.close();
}
}
}
public static void main(String args[]) throws IOException {
SimpleDateFormat sdf =
new SimpleDateFormat("yyyyMMdd HH:mm:ss");
System.out.println("Atomic time : " +
sdf.format(DateUtils.getAtomicTime().getTime()));
}
/*
ref : http://www.bldrdoc.gov/doctour/atomic_clock.html
49825 950418 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!

It's not possible to set your local computer clock in pure Java.
You need to use an external utility provided by the OS or call a JNI routine, see this HowTo.

2.19 Get the atomic timeTag(s): Date and Time

2.20 Get a date intervalTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0611.html
This HowTo computes a date interval based on the current date or given reference date. The
returned interval can be the previous week ou the previous month relative to the given reference
date.
import java.text.*;
import java.util.*;
public class DateUtils {
public enum IntervalType {
private DateUtils() {

Month, Week

public static Calendar[] getDateIntervals(IntervalType type, Calendar reference) {


if (reference == null) {
reference = Calendar.getInstance();
}
Calendar startDate = (Calendar)reference.clone();
Calendar endDate = (Calendar)reference.clone();
if (type == IntervalType.Month) {
// first date of the month
startDate.set(Calendar.DATE, 1);
// previous month
startDate.add(Calendar.MONTH, 1);
// first date of the month
endDate.set(Calendar.DATE, 1);
// previous month, last date
endDate.add(Calendar.DATE, 1);
}
else {
// previous week by convention (monday ... sunday)
// you will have to adjust this a bit if you want
// sunday to be considered as the first day of the week.
//
start date : decrement until first sunday then
//
down to monday
int dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
while (dayOfWeek != Calendar.SUNDAY) {
startDate.add(Calendar.DATE, 1);
dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
}
while (dayOfWeek != Calendar.MONDAY) {
startDate.add(Calendar.DATE, 1);
dayOfWeek = startDate.get(Calendar.DAY_OF_WEEK);
}
// end date , decrement until the first sunday
dayOfWeek = endDate.get(Calendar.DAY_OF_WEEK);
while (dayOfWeek != Calendar.SUNDAY) {
endDate.add(Calendar.DATE, 1);
dayOfWeek = endDate.get(Calendar.DAY_OF_WEEK);
}

2.20 Get a date intervalTag(s): Date and Time

}
return new Calendar[] { startDate, endDate };
}
public static void main(String[] args) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
System.out.println("** previous month (relative today)");
Calendar [] results = DateUtils.getDateIntervals(IntervalType.Month, null);
System.out.println(sdf.format(results[0].getTime()));
System.out.println(sdf.format(results[1].getTime()));
System.out.println("** previous week (relative today)");
results = DateUtils.getDateIntervals(IntervalType.Week, null);
System.out.println(sdf.format(results[0].getTime()));
System.out.println(sdf.format(results[1].getTime()));
System.out.println("** previous month (relative jan 1, 2007)");
results = DateUtils.getDateIntervals(IntervalType.Month,
new GregorianCalendar(2007, 00, 1));
System.out.println(sdf.format(results[0].getTime()));
System.out.println(sdf.format(results[1].getTime()));
System.out.println("** previous week (relative jan 1, 2007)");
results = DateUtils.getDateIntervals(IntervalType.Week,
new GregorianCalendar(2007, 00, 1));
System.out.println(sdf.format(results[0].getTime()));
System.out.println(sdf.format(results[1].getTime()));
}
catch (Exception e) {
e.printStackTrace();
}
}
/*
output :
** previous
20080601
20080630
** previous
20080630
20080706
** previous
20061201
20061231
** previous
20061225
20061231

month (relative today)

week (relative today)

month (relative jan 1, 2007)

week (relative jan 1, 2007)

*/
}

2.20 Get a date intervalTag(s): Date and Time

2.21 Determine if an hour is between an intervalTag(s): Date and


Time
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0624.html
import java.util.Calendar;
import java.text.SimpleDateFormat;
public class DateUtils {
// format 24hre ex. 12:12 , 17:15
private static String HOUR_FORMAT = "HH:mm";
private DateUtils() {

public static String getCurrentHour() {


Calendar cal = Calendar.getInstance();
SimpleDateFormat sdfHour = new SimpleDateFormat(HOUR_FORMAT);
String hour = sdfHour.format(cal.getTime());
return hour;
}
/**
* @param target hour to check
* @param start
interval start
* @param end
interval end
* @return true
true if the given hour is between
*/
public static boolean isHourInInterval(String target, String start, String end) {
return ((target.compareTo(start) >= 0)
&(target.compareTo(end) <= 0));
}
/**
* @param start
interval start
* @param end
interval end
* @return true
true if the current hour is between
*/
public static boolean isNowInInterval(String start, String end) {
return DateUtils.isHourInInterval
(DateUtils.getCurrentHour(), start, end);
}
//
TEST
public static void main (String[] args) {
String now = DateUtils.getCurrentHour();
String start = "14:00";
String end
= "14:26";
System. out.println(now + " between " + start + "" + end + "?");
System. out.println(DateUtils.isHourInInterval(now,start,end));
/*
* output example :
*
21:01 between 14:0014:26?
*
false
*
*/
}
}

2.21 Determine if an hour is between an intervalTag(s): Date and Time

2.22 Set the computer clockTag(s): Date and Time JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0285.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);
}
}

2.22 Set the computer clockTag(s): Date and Time JNI

2.23 Use System time to generate unique IDTag(s): Date and


Time Date and Time Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0385.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.24 Get the month (or day) name (localized)Tag(s): Date and
Time Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0650.html
import java.text.DateFormatSymbols;
import java.util.Locale;
public class DateUtils {
private DateUtils() { }
public static String getMonthName(int month) {
return getMonthName(month, Locale.getDefault());
}
public static String getMonthName(int month, Locale locale) {
DateFormatSymbols symbols = new DateFormatSymbols(locale);
String[] monthNames = symbols.getMonths();
return monthNames[month 1];
}

public static String getDayName(int day, Locale locale) {


DateFormatSymbols symbols = new DateFormatSymbols(locale);
String[] dayNames = symbols.getWeekdays();
return dayNames[day];
}

2.23 Use System time to generate unique IDTag(s): Date and Time Date and Time Varia

public static void main(String[] args) {


System.out.println(DateUtils.getMonthName(1));
System.out.println(DateUtils.getMonthName(1, new Locale("it")));
System.out.println(DateUtils.getDayName(java.util.Calendar.SUNDAY, Locale.getDefault()));
/*
* output :
*
january
*
gennaio
*
sunday
*/
}
}

2.25 Detect a leap yearTag(s): Date and Time


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0654.html
The algorithm to determine is a given year is leap or not (>365 days) is :
if year modulo 400 is 0 then
leap
else if year modulo 100 is 0 then
no_leap
else if year modulo 4 is 0 then
leap
else
no_leap

Three techniques to check if a year is leap or not :


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

public class DateUtils {


private DateUtils() { }
// using GregorianCalendar
public static boolean isLeap0(int year) {
GregorianCalendar cal = new GregorianCalendar();
cal.set(Calendar.YEAR, year);
return cal.isLeapYear(cal.get(Calendar.YEAR));
}
// using a Calendar
public static boolean isLeap1(int year) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);

2.25 Detect a leap yearTag(s): Date and Time

return cal.getActualMaximum(Calendar.DAY_OF_YEAR) > 365;


}
// directly, maybe faster...
public static boolean isLeap2(int year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}

public static void main(String[]


System.out.println("1900 : " +
System.out.println("1996 : " +
System.out.println("2000 : " +
System.out.println("2010 : " +
System.out.println("");
System.out.println("1900 : " +
System.out.println("1996 : " +
System.out.println("2000 : " +
System.out.println("2010 : " +
System.out.println("");
System.out.println("1900 : " +
System.out.println("1998 : " +
System.out.println("2000 : " +
System.out.println("2010 : " +
}

args) {
DateUtils.isLeap0(1900));
DateUtils.isLeap0(1996));
DateUtils.isLeap0(2000));
DateUtils.isLeap0(2010));
DateUtils.isLeap1(1900));
DateUtils.isLeap1(1996));
DateUtils.isLeap1(2000));
DateUtils.isLeap1(2010));
DateUtils.isLeap2(1900));
DateUtils.isLeap2(1996));
DateUtils.isLeap2(2000));
DateUtils.isLeap2(2010));

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

2.25 Detect a leap yearTag(s): Date and Time

3 AWT
3.1 javaawt

3.2 Use The CardLayout managerTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0237.html
A CardLayout object is a layout manager for a container. It treats each component in the container
as a card. Only one card is visible at a time, and the container acts as a stack of cards.
In this HowTo, when a button is clicked the corresponding card is made visible.

First we define the cards (which are based on a Panel)


import
import
import
import

java.awt.Color;
java.awt.Dimension;
java.awt.LayoutManager;
java.awt.Panel;

class MyPanel extends Panel{


private static final long serialVersionUID = 1L;
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() {
return new Dimension(w,h);
}
}

and then
import
import
import
import
import
import

3 AWT

java.applet.Applet;
java.awt.Button;
java.awt.CardLayout;
java.awt.Choice;
java.awt.Color;
java.awt.Component;

import
import
import
import
import

java.awt.FlowLayout;
java.awt.Panel;
java.awt.TextField;
java.awt.event.ActionEvent;
java.awt.event.ActionListener;

public class CardLayoutDemo extends Applet


implements ActionListener{
private static final long serialVersionUID = 1L;
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(Color.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(Color.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(Color.black,
new FlowLayout(),
100, 100);
t1 = new TextField(8);
t1.setBackground(Color.white);
p3.add(t1);
// Main card (receive the other)
p0 = new MyPanel(Color.white,
new CardLayout(0,0),
100,100);
setLayout(new FlowLayout());
add(p0);
// Add cards
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);

3 AWT

b3.addActionListener(this);
b4.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
//Show the first
((CardLayout)p0.getLayout()).show(p0, "First card");
}
else if (e.getSource() == b2) {
//Show the second
((CardLayout)p0.getLayout()).show(p0, "2nd card");
}
else if (e.getSource() == b3) {
//Show the third
((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 ++;
}
}
}
}
<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 CardLayoutTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0423.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];
}

3.3 Detect which card is visible with a CardLayoutTag(s): AWT

3.4 Use PopupsTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0238.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("file1");
item.addActionListener(this);
m.add(item);
item = new MenuItem("file2");
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");

3.4 Use PopupsTag(s): AWT

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);
}
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);

3.4 Use PopupsTag(s): AWT

}
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 DialogTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0247.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 {
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();

3.5 Use a File DialogTag(s): AWT

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 fontTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0270.html
[JDK1.4]
The names of the most common fonts supported by Java are TimesRoman, Courier, and Helvetica.
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 crossplateform compatibles.

3.6 Use TrueType fontTag(s): AWT

[JDK1.5]
@todo

3.7 Display available fontsTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0278.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.8 Font with 3D effectTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0312.html
import java.awt.*;
import java.applet.*;

3.7 Display available fontsTag(s): AWT

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 ClipboardTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0382.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();
}
public void toClipboard() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
try {

3.9 Use the System ClipboardTag(s): AWT

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 FrameTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0222.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 "fullscreen" Frame is in exclusive mode. In this mode you can change the resolution

3.10 Maximize a FrameTag(s): AWT

import java.awt.*;
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/DialogTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0223.html
// centers the dialog within the screen [1.1]

3.11 Center a Frame/DialogTag(s): AWT

// (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);
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 FrameTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0225.html
[JDK1.0.2]
public boolean handleEvent(Event evt) {
if (evt.id == Event.WINDOW_DESTROY) {

3.12 Close a FrameTag(s): AWT

System.exit(0);
return true;
}
return super.handleEvent(evt);
}

[JDK1.1 Method 1]
public aFrame extends Frame implements WindowListener {
public aFrame(){
addWindowListener( this );
}
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.12 Close a FrameTag(s): AWT

);
}

3.13 Call events on a Frame from a PanelTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0268.html
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);

3.13 Call events on a Frame from a PanelTag(s): AWT

// 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);
}
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() {

3.13 Call events on a Frame from a PanelTag(s): AWT

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

Try it here.

3.14 Set the small topleft icon on a FrameTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0246.html
There is a bug in JDK1.0.2 for Windows, so you are stuck with the JAVA coffee cup.
In JDK1.1, this is fixed. You have to use a GIF file (not ICO file!). The GIF dimension should be
16x16. With 1.5, you can use a PNG or JPG file.
You set the icon with :
frame.setIconImage(Toolkit.getDefaultToolkit().getImage("myIcon.gif"));

To get the image from a Jar instead, do :


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

or
frame.setIconImage(
new ImageIcon(
YourApp.class.getResource("logo.png")
).getImage()
);

3.15 Prevent a Frame to be resizedTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0252.html

3.14 Set the small topleft icon on a FrameTag(s): AWT

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.*;
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);
}

3.14 Set the small topleft icon on a FrameTag(s): AWT

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 Howto may not work with the Microsoft JVM. It's a feature...

3.16 Embed an image into a FrameTag(s): AWT AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0302.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"));
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

3.16 Embed an image into a FrameTag(s): AWT AWT

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 FrameTag(s): AWT AWT

3.17 Display a message boxTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0242.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);
}
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);
}

3.17 Display a message boxTag(s): AWT

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 screenTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0267.html
This Splash class display a window containing a specified image while a parent Frame is doing its
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);

3.18 Display a Splash screenTag(s): AWT

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();
}
}
}

The following example use this 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");

3.18 Display a Splash screenTag(s): AWT

(jht.gif) as the splash image.

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 Vibrate a WindowTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0622.html
This HowTo is based on this post : http://sdnshare.sun.com/view.jsp?id=2326
This can be useful to make a visual effect when an event is occuring.
import java.awt.*;
public class FrameUtils {
private final static int VIBRATION_LENGTH = 20;
private final static int VIBRATION_VELOCITY = 5;
private FrameUtils() { }
public static void vibrate(Frame frame) {
try {
final int originalX = frame.getLocationOnScreen().x;
final int originalY = frame.getLocationOnScreen().y;
for(int i = 0; i < VIBRATION_LENGTH; i++) {
Thread.sleep(10);
frame.setLocation(originalX, originalY + VIBRATION_VELOCITY);
Thread.sleep(10);
frame.setLocation(originalX, originalY VIBRATION_VELOCITY);
Thread.sleep(10);

3.19 Vibrate a WindowTag(s): AWT

frame.setLocation(originalX + VIBRATION_VELOCITY, originalY);


Thread.sleep(10);
frame.setLocation(originalX, originalY);
}
}
catch (Exception err) {
err.printStackTrace();
}
}
}

To use it, simply pass a Frame to the vibrate method.


FrameUtils.vibrate(myFrame);

To make it more Swingoriented, you change the method signature for a JFrame instead.
Here an example.
We display a small window. When a file is added or deleted, the window is shaking for a brief
moment and display the event. By default, the folder c:/temp is used but you can specify another
one on the command line.
First get the code to detect a file modfication in a folder (in this HowTo, you need the DirWatcher
and DirFilterWatcher classes). Plus the following classes.
import java.awt.*;
import java.awt.event.*;
public class DirWatchWindow extends Frame {
Label folder;
Label info;
public DirWatchWindow() {
setTitle("DirWatchWindow");
setSize(600, 100);
setLayout(new BorderLayout());
folder = new Label("");
info
= new Label("");
add(folder, BorderLayout.NORTH);
add(info, BorderLayout.SOUTH);
setVisible(true);
addWindowListener
(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
public void setInfo(String text) {
info.setText(text);
}
public void setFolder(String dir) {
folder.setText("Watching folder : " + dir);
}
}

3.19 Vibrate a WindowTag(s): AWT

import java.util.*;
import java.io.*;
public class DirWatchTest {
public static void main(String args[]) {
String folderToWatch = "c:/temp";
if (args.length > 0) {
folderToWatch = args[0];
}
final DirWatchWindow dww = new DirWatchWindow();
dww.setFolder(folderToWatch);
TimerTask task = new DirWatcher(folderToWatch, "txt" ) {
protected void onChange( File file, String action ) {
// here we code the action on a change
dww.setInfo("File : "+ file.getName() +" action: " + action);
FrameUtils.vibrate(dww);
}
};
Timer timer = new Timer();
timer.schedule( task , new Date(), 1000 );
}
}

You can download an executable JAR here


To launch the demo
java jar DirWatch.jar

to watch the default directory c:/temp or


java jar DirWatch.jar

c:/myfolder

to specify your own folder. This demo is watching for files with the extension txt only.

3.20 Limit TextField input to numeric valueTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0226.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.*;

3.20 Limit TextField input to numeric valueTag(s): AWT

public class app extends java.applet.Applet {


TextField textField1;
public void init() {
setLayout(new FlowLayout());
textField1 = new TextField(10);
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) ;
}

3.20 Limit TextField input to numeric valueTag(s): AWT

3.21 Limit TextField input to a maximum lengthTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0227.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 Limit TextField input to a maximum lengthTag(s): AWT

3.22 React to the ENTER key in a TextfieldTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0253.html
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class testENTER extends Applet
implements KeyListener {
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 React to the ENTER key in a TextfieldTag(s): AWT

3.23 Make the ENTER key act like the TAB keyTag(s): AWT
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0254.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)
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.24 Reset all textfields in one shotTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0274.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;

3.23 Make the ENTER key act like the TAB keyTag(s): AWT

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)
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.25 Limit a TextField to UppercaseTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0279.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);

3.25 Limit a TextField to UppercaseTag(s): AWT

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.26 Have an ImageButtonTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0245.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;

3.26 Have an ImageButtonTag(s): AWT

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 {
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)) {

3.26 Have an ImageButtonTag(s): AWT

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 {
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.*;

3.26 Have an ImageButtonTag(s): AWT

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.27 Reset a checkbox groupTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0221.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"));
}

3.27 Reset a checkbox groupTag(s): AWT

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.28 Set the listbox widthTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0231.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;
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 Set the listbox widthTag(s): AWT

3.29 Align the column in a ListTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0244.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,20col1.length()) +
spaces2 +
col2 +
spaces10.substring(0,10col2.length()) +
col3);
}
In real life, the preferred way would be to extend the java.awt.List and override the addItem method.

3.30 Have a srolling text displayTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0271.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.*;
import java.awt.event.*;
public class TelnetLikeDisplay extends Applet
implements ActionListener {
Button b;
int i = 0;
static final int LINE_BUFFERED = 10;

3.29 Align the column in a ListTag(s): AWT

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.31 Label dynamic resizingTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0232.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 nonvalid
this.validate();

3.31 Label dynamic resizingTag(s): AWT

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.31 Label dynamic resizingTag(s): AWT

3.32 Make a TextArea "wordwrap"Tag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0241.html
Simply create the TextArea with no horizontal scrollbar.
myTextArea = new TextArea
("text", 3 , 100 , TextArea.SCROLLBARS_VERTICAL_ONLY);

3.33 Synchronize a TextArea vs a ChoiceTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0281.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.32 Make a TextArea "wordwrap"Tag(s): AWT

3.34 Display underlined textTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0258.html
import java.applet.*;
import java.awt.*;
public class underlineText extends Applet{
String s = "Underlined text";
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 Howto for underlined text with a Label component.
Check this Howto for underlined text in Swing.

3.35 Display vertical textTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0259.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

3.34 Display underlined textTag(s): AWT

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.36 Have Label with many linesTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0269.html
The Label component included in the AWT do not support "\n" in its definition. The following class
implements a multiline 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;

3.36 Have Label with many linesTag(s): AWT

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);
}
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();
}

3.36 Have Label with many linesTag(s): AWT

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();
}
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

3.36 Have Label with many linesTag(s): AWT

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();
}
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);

3.36 Have Label with many linesTag(s): AWT

}
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.37 Have a Label with underlined text Tag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0272.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(),

3.37 Have a Label with underlined text Tag(s): AWT

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 Howto");
add(ul1);
}
}

[testapplet.html]
<HTML><HEAD></HEAD><BODY>
<APPLET CODE="TestUnderlinedLabel.class"
NAME="myApplet"
HEIGHT=200 WIDTH=200>
/APPLET/BODY/HTML
Check this Howto for underlined text in Swing.

3.38 Have a Label acting as HTML HREF (URLLabel)Tag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0273.html
[URLLabel.java]
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
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");
}

3.38 Have a Label acting as HTML HREF (URLLabel)Tag(s): AWT

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);
}
}
}

[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 Howto");
add(ull1);
URLLabel ull2 = new URLLabel(this,
"http://www.rgagnon.com/bigindex.html",
"Java Howto BigIndex");
add(ull2);
URLLabel ull3 = new URLLabel(this,
"http://www.rgagnon.com/javadetails/java0001.html",
"Java Howto 0001");
add(ull3);
URLLabel ull4 = new URLLabel(this,
"http://www.rgagnon.com/javadetails/java0002.html",
"Java Howto 0002");

3.38 Have a Label acting as HTML HREF (URLLabel)Tag(s): AWT

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.39 Display a GIF in a CanvasTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0229.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);
}
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]));

3.39 Display a GIF in a CanvasTag(s): AWT

frame.resize(400,400);
frame.show();
}
}

3.40 Embed an image into a FrameTag(s): AWT AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0302.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"));
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);
}
}
);

3.40 Embed an image into a FrameTag(s): AWT AWT

}
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.40 Embed an image into a FrameTag(s): AWT AWT

3.41 Load several images from a single GIFTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0239.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
import
import
import

java.applet.*;
java.awt.*;
java.io.*;
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,
g.drawImage(icon[0], 0, 20,
g.drawImage(icon[1], 0, 40,
}

{
this);
this);
this);

public void loadImages(String s) {


MediaTracker t=new MediaTracker(this);
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 several images from a single GIFTag(s): AWT

3.42 Load an Image from a JAR fileTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0240.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
//
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]


3.42 Load an Image from a JAR fileTag(s): AWT

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


button.setIcon(new ImageIcon(url));

3.43 Load an Icon from a jar (again)Tag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0436.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 builtin 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;
}

A list of what icons are available can be found here

3.44 Scale an ImageTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0243.html
import java.awt.image.*;
import java.awt.*;
import java.net.*;
public class app extends java.applet.Applet {
Image source;

3.43 Load an Icon from a jar (again)Tag(s): AWT

Image resizedImage;
public void init() {
MediaTracker media = new MediaTracker(this);
// java howto 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
import
import
import
import

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

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]);
}

3.43 Load an Icon from a jar (again)Tag(s): AWT

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.45 Fade an imageTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0249.html
This example display a GIF with a fadein, fadeout effect.
import
import
import
import

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

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) {

3.45 Fade an imageTag(s): AWT

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 < 0) {
level=0;
sign = sign * 1;
}
if (level > 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 {
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();
}

3.45 Fade an imageTag(s): AWT

}
}
}
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.46 Rotate an imageTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0248.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
import
import
import

java.applet.Applet;
java.awt.*;
java.awt.image.*;
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];
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);

3.46 Rotate an imageTag(s): AWT

try {
grabber.grabPixels();
}
catch(InterruptedException e) {
e.printStackTrace();
}
for(int y = 0; y < 32; y++) {
for(int x = 0; x < 32; x++) {
rotate[((32x1)*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
import
import
import

java.awt.*;
java.awt.event.*;
java.awt.geom.*;
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() {
//rotate 5 degrees at a time
currentAngle+=5.0;
if (currentAngle >= 360.0) {
currentAngle = 0;
}
repaint();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);

3.46 Rotate an imageTag(s): AWT

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.47 Create a scrollable canvasTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0230.html
JDK1.1 using a ScrollPane
import java.applet.*;
import java.awt.*;
public class apptest extends Applet {
Canvas c;
ScrollPane s;

3.47 Create a scrollable canvasTag(s): AWT

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);
}
public boolean handleEvent(Event e) {
if (e.target instanceof Scrollbar) {

3.47 Create a scrollable canvasTag(s): AWT

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;
int rw, rh;
Color b, f;
int x, y;

3.47 Create a scrollable canvasTag(s): AWT

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.47 Create a scrollable canvasTag(s): AWT

3.48 Use an Image as the Applet backgroundTag(s): Applet AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0233.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.48 Use an Image as the Applet backgroundTag(s): Applet AWT

Try it here.

3.49 Have a simple Image browserTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0277.html
[imagelist.txt]
jht.gif|JAVA Howto
jsht.gif|Javascript Howto
pht.gif|Powerbuilder Howto

[application version]
import
import
import
import

java.awt.*;
java.awt.event.*;
java.net.*;
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) {

3.49 Have a simple Image browserTag(s): AWT

String theUrl = url[lbx.getSelectedIndex()];


MediaTracker media = new MediaTracker(this);
Image image =
Toolkit.getDefaultToolkit().getImage(theUrl);
media.addImage(image, 0);
try {
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
import
import
import
import

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

public class ImageBrowserApplet extends Applet {


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

3.49 Have a simple Image browserTag(s): AWT

}
}
class APanel extends Panel implements ActionListener {
private List lbx;
private MyCanvas can;
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) {

3.49 Have a simple Image browserTag(s): AWT

image = i;
repaint();
}
public void paint(Graphics g) {
if (image != null)
g.drawImage(image, 0,0, this);
}
}
NOTE : You can try this example here

3.50 Simulate a "mouse over" event to toggle an imageTag(s):


AWT
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0264.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++;
}

3.50 Simulate a "mouse over" event to toggle an imageTag(s): AWT

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) {}
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 (
).

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 Simulate a "mouse over" event to toggle an imageTag(s): AWT

and

3.51 Hide the mouse cursorTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0440.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.52 Make a color transparentTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0265.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);
}

3.51 Hide the mouse cursorTag(s): AWT

[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 =
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.53 Save an Image as a GIF or JPEG fileTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0266.html
Take a look at the following package :
http://www.obrador.com/essentialjpeg/jpeg.htm for JPEG
3.53 Save an Image as a GIF or JPEG fileTag(s): AWT

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;
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

3.53 Save an Image as a GIF or JPEG fileTag(s): AWT

{
return ImageIO.read(file);
}
public static void writeImageToJPG
(File file,BufferedImage bufferedImage)
throws IOException
{
ImageIO.write(bufferedImage,"jpg",file);
}
}

3.54 Use the same background color as the browserTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0234.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.55 Do simple animation using ImagesTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0262.html
By using a Thread, we switch between 2 GIFs (

import
import
import
import

and

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

public class AnimationGifApplet extends Applet {


Image [] img;
int
index = 0;
int
maxImg;
MediaTracker tracker;

3.54 Use the same background color as the browserTag(s): AWT

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;
}
public void run() {
while (true) {
try {
sleep(delay);
animationApplet.animate();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
}

Try it here.

3.54 Use the same background color as the browserTag(s): AWT

3.56 Do simple animation to show "work in progress"Tag(s):


AWT
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0263.html
Like the previous Howto, using a Thread, we switch between 2 GIFs, for example (
).
Click the button to simulate some work, click again to terminate the "work in progress"
[JDK1.1]
import
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.image.*;
java.awt.event.*;
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);
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) {

3.56 Do simple animation to show "work in progress"Tag(s): AWT

and

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.57 Get the color of a specific pixelTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0257.html
We assume that we have an Image called picture
pixels = new int[width*height];
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.
3.57 Get the color of a specific pixelTag(s): AWT

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 color = 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 color = new Color(red,green,blue);

3.58 Do "rubberband" drawingTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0251.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);
setForeground(new Color(0).white);
}
public void Dragupdate(Graphics g) {

3.58 Do "rubberband" drawingTag(s): AWT

/*
** rubberband 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;
Dragupdate(getGraphics());
return true;
}
return super.handleEvent(e);

3.58 Do "rubberband" drawingTag(s): AWT

}
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(np1);
np;
repaint();
}
}
public void resetDrawing() {
lines.removeAllElements();
np=0;
repaint();
}
}

3.59 Convert RGB value to Hexadecimal (to be used in HTML for


example)Tag(s): AWT
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0255.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 Convert RGB value to Hexadecimal (to be used in HTML for example)Tag(s): AWT

3.60 Draw a line or set a pixel in my own imageTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0250.html
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.61 Draw a dashed lineTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0224.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((x2x1)*(x2x1)+(y2y1)*(y2y1));
double yincrement=(y2y1)/(linelength/(dashlength+spacelength));
double xincdashspace=(x2x1)/(linelength/(dashlength+spacelength));
double yincdashspace=(y2y1)/(linelength/(dashlength+spacelength));

3.60 Draw a line or set a pixel in my own imageTag(s): AWT

double xincdash=(x2x1)/(linelength/(dashlength));
double yincdash=(y2y1)/(linelength/(dashlength));
int counter=0;
for (double i=0;i<linelengthdashlength;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),
(int) (y1+yincdashspace*counter),
x2,y2);
}

3.62 Draw a line with a thicknessTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0260.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...

3.62 Draw a line with a thicknessTag(s): AWT

double
double
ddx +=
ddy +=
int dx
int dy

ddx = scale * (double)dY;


ddy = scale * (double)dX;
(ddx > 0) ? 0.5 : 0.5;
(ddy > 0) ? 0.5 : 0.5;
= (int)ddx;
= (int)ddy;

// Now we can compute the corner points...


int xPoints[] = new int[4];
int yPoints[] = new int[4];
xPoints[0]
xPoints[1]
xPoints[2]
xPoints[3]

=
=
=
=

x1
x1
x2
x2

dx;
dx;
dx;
dx;

yPoints[0]
yPoints[1]
yPoints[2]
yPoints[3]

=
=
=
=

y1
y1
y2
y2

dy;
dy;
dy;
dy;

g.fillPolygon(xPoints, yPoints, 4);


}
}

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);

3.62 Draw a line with a thicknessTag(s): AWT

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.63 Draw a pie chartTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0261.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);
// "valuecolor,valuecolor,..."
StringTokenizer t = new StringTokenizer(at, ",");
String s;
int i;
while (t.hasMoreTokens()) {

3.63 Draw a pie chartTag(s): AWT

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;
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);

3.63 Draw a pie chartTag(s): AWT

}
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>
<PARAM NAME="depth" VALUE="30">
<PARAM NAME="width" VALUE="120">
<PARAM NAME="values" VALUE="1red,5green,7blue">
</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.64 Draw faster rectanglesTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0364.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);

3.64 Draw faster rectanglesTag(s): AWT

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.65 Get a screen capture and save it as a JPEGTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0489.html
The screen capture is done with java.awt.Robot.
import
import
import
import
import
import
import

java.awt.AWTException;
java.awt.Robot;
java.awt.Rectangle;
java.awt.Toolkit;
java.awt.image.BufferedImage;
java.io.*;
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);

3.65 Get a screen capture and save it as a JPEGTag(s): AWT

// 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() ) );

3.66 Detect a double click vs simple clickTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0235.html
[JDK1.02]
import java.applet.*;
import java.awt.*;
public class d extends Applet {
int dClkRes = 300;
// doubleclick 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.whentimeMouseDown) < 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;
}

3.66 Detect a double click vs simple clickTag(s): AWT

[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) {
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.67 Detect the mouse button used when clickingTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0236.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);

3.67 Detect the mouse button used when clickingTag(s): AWT

}
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;
}
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.68 Exit an application from a menuTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0276.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);
}

3.68 Exit an application from a menuTag(s): AWT

}
);
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 'ctrlx'"),"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));
}
static public void main(String[] args) {
new ExitFromMenu();
}
}

3.69 Trigger a click on a ButtonTag(s): AWT Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0468.html
In this example, when we click on a Button, we trigger the action attached to the another Button.
Regular AWT (applet)
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);
}

3.69 Trigger a click on a ButtonTag(s): AWT Swing

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 (japplet)


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, we have visual effect on b1!
b1.doClick();
}
}
}

3.70 Display a TIFTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0605.html

3.70 Display a TIFTag(s): AWT

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
import
import
import
import
import
import
import
import
import

javax.media.jai.PlanarImage;
com.sun.media.jai.codec.ByteArraySeekableStream;
com.sun.media.jai.codec.ImageCodec;
com.sun.media.jai.codec.ImageDecoder;
com.sun.media.jai.codec.SeekableStream;
java.io.FileInputStream;
java.nio.ByteBuffer;
java.nio.channels.FileChannel;
java.awt.Image;
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.70 Display a TIFTag(s): AWT

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.71 Convert a multipage TIF into singlepage TIFTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0535.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 mid1980's to agree on a common scanned image file format, rather than have each
company promulgate its own proprietary format.
This HowTo takes a multipage TIF (from a FAX) and convert it into many singlepages TIF.
This is done with the JAI (Java Advance Image) package.
http://java.sun.com/products/javamedia/jai/index.jsp
>
import java.io.*;
import
import
import
import

com.sun.media.jai.codec.FileSeekableStream;
com.sun.media.jai.codec.ImageDecoder;
com.sun.media.jai.codec.ImageCodec;
com.sun.media.jai.codec.TIFFEncodeParam;

import
import
import
import

java.awt.image.RenderedImage;
javax.media.jai.RenderedOp;
javax.media.jai.JAI;
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

3.71 Convert a multipage TIF into singlepage TIFTag(s): AWT

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());
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) multipurpose 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.
See also : Convert many singlepage TIF into one multipage TIF

3.72 Convert many singlepage TIF into one multipage TIF


Tag(s): AWT

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javaconvertmanysingletifintoonemultiplepageti
This HowTo takes a list of singlepage TIF and convert them into one multipage TIF.
This is done with the JAI (Java Advance Image) package.
import
import
import
import
import

java.io.FileOutputStream;
java.io.OutputStream;
java.util.ArrayList;
java.util.List;
java.awt.image.BufferedImage;

import javax.media.jai.NullOpImage;
import javax.media.jai.OpImage;

3.72 Convert many singlepage TIF into one multipage TIF Tag(s): AWT

import javax.media.jai.PlanarImage;
import
import
import
import
import
import

com.sun.media.jai.codec.ImageEncoder;
com.sun.media.jai.codec.SeekableStream;
com.sun.media.jai.codec.FileSeekableStream;
com.sun.media.jai.codec.ImageDecoder;
com.sun.media.jai.codec.ImageCodec;
com.sun.media.jai.codec.TIFFEncodeParam;

public class TiffUtils {


public static void main(String[] args) throws Exception {
// 2 single page TIF to be in a multipage
String [] tifs = {
"C:/temp/test01.tif",
"C:/temp/test02.tif"
};
int numTifs = tifs.length; // 2 pages
BufferedImage image[] = new BufferedImage[numTifs];
for (int i = 0; i < numTifs; i++) {
SeekableStream ss = new FileSeekableStream(tifs[i]);
ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null);
PlanarImage pi = new NullOpImage
(decoder.decodeAsRenderedImage(0),null,null,OpImage.OP_IO_BOUND);
image[i] = pi.getAsBufferedImage();
ss.close();
}
TIFFEncodeParam params = new TIFFEncodeParam();
params.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
OutputStream out = new FileOutputStream("C:/temp/multipage.tif");
ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params);
List <BufferedImage>list = new ArrayList<BufferedImage>(image.length);
for (int i = 1; i < image.length; i++) {
list.add(image[i]);
}
params.setExtraImages(list.iterator());
encoder.encode(image[0]);
out.close();
System.out.println("Done.");
}
}

See also : Convert a multipage TIF into singlepage TIF

3.73 Convert an Image to a BufferedImageTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0601.html
import java.awt.*;

3.73 Convert an Image to a BufferedImageTag(s): 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);
}
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 backconversion, it's not needed.

3.74 Detect if a TIF is blank Tag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0631.html
import
import
import
import
import
import
import
import
import

javax.media.jai.PlanarImage;
com.sun.media.jai.codec.ByteArraySeekableStream;
com.sun.media.jai.codec.ImageCodec;
com.sun.media.jai.codec.ImageDecoder;
com.sun.media.jai.codec.SeekableStream;
java.io.FileInputStream;
java.nio.ByteBuffer;
java.nio.channels.FileChannel;
java.awt.Color;

3.74 Detect if a TIF is blank Tag(s): AWT

import
import
import
import
import

java.awt.Graphics;
java.awt.Image;
java.awt.image.PixelGrabber;
java.awt.image.BufferedImage;
java.awt.image.RenderedImage;

/**
* This utility loads a given TIF and try to detect if it's
* blank or not.
*
* We create inmemory image and then calculate the standard
* deviation of the color information. If a certain value is not
* reached then we assume that the image is mainly uniform and
* probably blank. The threshold value is an estimate. Depending
* the source of the TIF this value can be higher. For example,
* TIF from a FAX machine or a scanner can be dirty, with hair/dust presence,
* but with no content.
*
* jai_core.jar and jai_codec.jar are required.
* http://java.sun.com/products/javamedia/jai/index.jsp
*
* @author http://www.rgagnon.com/howto.html
*/
public class BlankDetection {
public static final int FAILURE = 2;
public static final int BLANK = 0;
public static final int NOTBLANK = 1;
// value where we can consider that this is a blank image
// can be much higher depending of the TIF source
// (ex. scanner or fax)
public static final int BLANK_THRESHOLD = 1000;
/**
* Creates an Image from a byte array
* @param data
* @return Image
* @throws Exception
*/
public 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();
// scaledown the image , maximum width : 500 px
// to preserve memory
Image imageScaled =
image.getScaledInstance(500, 1, Image.SCALE_SMOOTH);
return imageScaled;
}
/**
* Converts an Image to a BufferedImage
* @param im une Image
* @return BufferedImage
*/
public static BufferedImage imageToBufferedImage(Image im) {
BufferedImage bi = new BufferedImage
(im.getWidth(null),im.getHeight(null),BufferedImage.TYPE_INT_RGB);

3.74 Detect if a TIF is blank Tag(s): AWT

Graphics bg = bi.getGraphics();
bg.drawImage(im, 0, 0, null);
bg.dispose();
return bi;
}
/**
* Check if an Image is blank or not
* Computes the standard deviation based on the color information
* @param bi bufferedimage
* @return true it's blank
*/
public static boolean isBlank(BufferedImage bi) throws Exception {
long count = 0;
long total = 0;
double totalVariance = 0;
double stdDev = 0;
int height = bi.getHeight();
int width = bi.getWidth();
int[] pixels = new int[width * height];
PixelGrabber pg = new PixelGrabber
(bi, 0, 0, width, height, pixels, 0, width);
pg.grabPixels();
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
count++;
int pixel = pixels[j * width + i];
int red = (pixel >> 16) & 0xff;
int green = (pixel >> 8) & 0xff;
int blue = (pixel) & 0xff;
int pixelValue = new Color(red, green,blue,0).getRGB();
total += pixelValue;
double avg = total /count;
totalVariance += Math.pow(pixelValue avg, 2);
stdDev = Math.sqrt(totalVariance / count);
}
}
return (stdDev <BLANK_THRESHOLD);
}
/**
* Accept on the command line the path to a TIF file
*
* Returns an errorlevel based on the analysis
* 0 blank
* 1 not blank
* 2 IO error
*
* @param args path vers complet vers un PROPS
*/
public static void main(String[] args) {
try {
if (args.length==0) {
System.out.println("Missing parameter.");
System.exit(FAILURE);
}
String path = args[0];
FileInputStream in = new FileInputStream(path);
FileChannel channel = in.getChannel();
ByteBuffer buffer = ByteBuffer.allocate((int)channel.size());
channel.read(buffer);

3.74 Detect if a TIF is blank Tag(s): AWT

Image image = load(buffer.array());


BufferedImage bufferedImage = imageToBufferedImage(image);
boolean isBlank = BlankDetection.isBlank(bufferedImage);
System.exit( isBlank ? BLANK : NOTBLANK );
}
catch (Exception e) {
e.printStackTrace();
System.exit(FAILURE);
}
}
}

3.75 Convert TIF to PDFTag(s): AWT IO IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0645.html
This HowTo is based on the iText package. You need a recent version (ex. 2.*)
This a command line utility. You pass one or many tif files as argument and corresponding PDF are
produced. Multipage TIF are supported. TIF are resized to fit a letterpage dimension.
import java.io.FileOutputStream;
import
import
import
import
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.Image;
com.lowagie.text.PageSize;
com.lowagie.text.Rectangle;
com.lowagie.text.pdf.PdfContentByte;
com.lowagie.text.pdf.PdfWriter;
com.lowagie.text.pdf.RandomAccessFileOrArray;
com.lowagie.text.pdf.codec.TiffImage;

public class TiffToPDF {


public static void main(String[] args) {
if (args.length < 1) {
System.out
.println("Usage: Tiff2Pdf file1.tif [file2.tif ... fileN.tif]");
System.exit(1);
}
String tiff;
String pdf;
for (int i = 0; i < args.length; i++) {
tiff = args[i];
pdf = tiff.substring(0, tiff.lastIndexOf('.') + 1) + "pdf";
Document document = new Document(PageSize.LETTER, 0, 0, 0, 0);
try {
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(pdf));
int pages = 0;
document.open();

3.75 Convert TIF to PDFTag(s): AWT IO IO Open Source

PdfContentByte cb = writer.getDirectContent();
RandomAccessFileOrArray ra = null;
int comps = 0;
try {
ra = new RandomAccessFileOrArray(tiff);
comps = TiffImage.getNumberOfPages(ra);
}
catch (Throwable e) {
System.out.println("Exception in " + tiff + " "
+ e.getMessage());
continue;
}
System.out.println("Processing: " + tiff);
for (int c = 0; c < comps; ++c) {
try {
Image img = TiffImage.getTiffImage(ra, c + 1);
if (img != null) {
System.out.println("page " + (c + 1));
img.scalePercent
(7200f / img.getDpiX(), 7200f / img.getDpiY());
document.setPageSize
(new Rectangle(img.getScaledWidth(), img.getScaledHeight()));
img.setAbsolutePosition(0, 0);
cb.addImage(img);
document.newPage();
++pages;
}
}
catch (Throwable e) {
System.out.println("Exception " + tiff + " page "
+ (c + 1) + " " + e.getMessage());
}
}
ra.close();
document.close();
}
catch (Throwable e) {
e.printStackTrace();
}
System.out.println("done");
}
}
}

3.76 Convert a TIF to a JPGTag(s): AWT


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaconverttiftojpg.html
You need the Java Advanced Imaging (JAI) API.
http://java.sun.com/javase/technologies/desktop/media/jai/
import java.io.File;

3.76 Convert a TIF to a JPGTag(s): AWT

import
import
import
import
import
import
import
import
import
import

java.io.FileOutputStream;
java.io.IOException;
java.awt.image.RenderedImage;
com.sun.image.codec.jpeg.JPEGCodec;
com.sun.image.codec.jpeg.JPEGImageEncoder;
com.sun.media.jai.codec.SeekableStream;
com.sun.media.jai.codec.FileSeekableStream;
com.sun.media.jai.codec.TIFFDecodeParam;
com.sun.media.jai.codec.ImageDecoder;
com.sun.media.jai.codec.ImageCodec;

public class TiffUtils {


public static void TiffToJpg(String tiff, String output)
throws IOException
{
File tiffFile = new File(tiff);
SeekableStream s = new FileSeekableStream(tiffFile);
TIFFDecodeParam param = null;
ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
RenderedImage op = dec.decodeAsRenderedImage(0);
FileOutputStream fos = new FileOutputStream(output);
JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
jpeg.encode(op.getData());
fos.close();
}
public static void main(String[] args) throws Exception {
TiffUtils.TiffToJpg("c:/users/public/temp/test.tif",
"c:/users/public/temp/test.jpg");
}
}

Need some TIFFs for testing ? Just ask Google!

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

3.76 Convert a TIF to a JPGTag(s): AWT

4 Environment
4.1 javaenv

4.2 Read environment variables from an applicationTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0150.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 lowtech 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" );
}

4 Environment

else {
// 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, preJDK 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 as a Proprties
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);

4 Environment

Java's System properties contains some useful informations about the environment, for example,
the TEMP and PATH environment variables (on Windows).
public class ShowSome {
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 differentthe 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/linuxbin:/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
\cygwinb20\Hi586cygwin32\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;

4 Environment

d:\OrbixWeb3.2\bin;D:\Program Files\IBM\GSK\lib;
H:\pvcs65\VM\win32\bin;c:\cygnus\cygwinb20\Hi586cygwin32\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;
C:\Program Files\Executive Software\DiskeeperServer\;}

Java is prepending itself! That confused me and broke my exec from ant.
Belorussian translation

4.3 Retrieve environment variables (JDK1.5)Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0466.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

4.4 Retrieve environment variable (JNI)Tag(s): Environment JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0460.html
4.3 Retrieve environment variables (JDK1.5)Tag(s): Environment

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 7bit ASCII characters.
See also this HowTo.

4.5 Use a MAKE fileTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0158.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

4.5 Use a MAKE fileTag(s): Environment

# begin JAR support


JARFILE= theJAR.jar
$(JARFILE): $(CLASSFILES) $(SOURCEFILES)
jar cfm0 $(JARFILE) <<manifest.tmp
$(DATAFILES)
Name: GetImage.class
JavaBean: False

$(CLASSFILES)

Name: myCanvas.class
JavaBean: True
<<
# 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 (deprecated)Tag(s):


Environment DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0160.html
This HowTo is obsolete. Check this one instead : Detect browser type from an Applet
One way is to instanciate a known browserspecific 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;

4.6 Detect the browser/JVM type (deprecated)Tag(s): Environment DEPRECATED

}
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 Microsoftspecific classes,
the other is a JDK1.1 applet and finally a version for JDK102only 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.6 Detect the browser/JVM type (deprecated)Tag(s): Environment DEPRECATED

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.7 Fix the "Wrong magic number" error messageTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0163.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.7 Fix the "Wrong magic number" error messageTag(s): Environment

4.8 Use a precompiler " la C" with JavaTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0164.html

4.9 Open source packages


Check this list of what is available.
Also take a look at JEnable

4.10 Ant
For simple need, Ant can be used to do substitution in your sources.
We insert into the code a special tag to delimit code that need to be stripped by the Ant script. Let's
say we use //@STARTDEBUG@// and //@ENDDEBUG@//.
package com.rgagnon.howto;
import javax.swing.JFrame;
public class Example {
public static void main(String args[]){
JFrame f = new JFrame();
f.setSize(300,200);
f.setVisible(true);
f.setTitle("HowTo");
//@STARTDEBUG@//
f.setTitle(f.getTitle() + " DEBUG version");
//@ENDDEBUG@//
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

If you execute this code, the JFrame title will have the word "DEBUG" appended to it.
The Ant script to remove the debugging code is :
<project default="buildme">
<target name="compileprod">
<copy todir="../out" includeEmptyDirs="false">
<filterchain>
<tokenfilter>
<replacestring from="//@STARTDEBUG@//" to="/*" />
<replacestring from="//@ENDDEBUG@//" to="*/" />
</tokenfilter>
</filterchain>
<fileset dir=".">
<include name="**/*.java" />
</fileset>
</copy>
<javac srcdir="../out" />
</target>

4.8 Use a precompiler " la C" with JavaTag(s): Environment

<target name="compiledebug">
<javac srcdir="." />
</target>

<target name="buildme" depends="compileprod" />


</project>

After running this script, the source (in the ..\out directory)
package com.rgagnon.howto;
import javax.swing.JFrame;
public class Example {
public static void main(String args[]){
JFrame f = new JFrame();
f.setSize(300,200);
f.setVisible(true);
f.setTitle("HowTo");
/*
f.setTitle(f.getTitle() + " DEBUG version");
*/
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

4.11 Simple boolean flag


See this HowTo. This technique relies on the compiler optimization which remove code in the
bytecode generated because it will never be executed.

4.12 Determine what are the classes actually used in a Java


Applet or applicationTag(s): Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0165.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

4.11 Simple boolean flag

NOTE: This can be useful if you want to trim a JAR to include only classes actually used.

4.13 Set the memory available to the JVMTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0131.html
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 :
Xms<size> specifies the initial Java heap size and
Xmx<size> the maximum Java heap size.
To set the minimum at 64Mb and the maximum at 256Mb
java Xms64m Xmx256m ...

The default value for the minimum is 2Mb, for the maximum it's 64Mb.

4.14 Generate the Javadoc "en franais"Tag(s):


Environment Environment Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0437.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

4.13 Set the memory available to the JVMTag(s): Environment

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=Sousinterfaces 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>

4.15 Use JDK1.5 new featuresTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0462.html
Download the JDK1.5 and install it.
From a shell, type
4.15 Use JDK1.5 new featuresTag(s): Environment

java version

The response should be something like


java version "1.5.0beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0betab32c)
JAVA HOTSPOT(TM) CLIENT VM (BUILD 1.5.0BETAB32C, 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!) :
"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

4.16 Check the class versionTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0544.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
45
45
46
47
48
49
50

minor Java platform version


3
1.0
3
1.1
0
1.2
0
1.3
0
1.4
0
1.5
0
1.6

import java.io.*;

4.16 Check the class versionTag(s): Environment

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) {
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.17 Get the system properties or the JVM uptimeTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0549.html

4.17 Get the system properties or the JVM uptimeTag(s): Environment

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());
// 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.18 Detect if running in a 64bit JVMTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0565.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

4.18 Detect if running in a 64bit JVMTag(s): Environment

System.getProperty("java.vm.name")
.toLowerCase().indexOf("64") >= 0;
}
// probably 32bit
return false;
}
}

4.19 Set the default JVM typeTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0566.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.0b64)
Java HotSpot(TM) Client VM (build 1.5.0b64, mixed mode, sharing)

The default JVM with a JIT (JustInTime 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 32bit Solaris and Linux downloads. For
32bit Windows, if you download the JRE, you get only the client, you'll need to download the SDK
to get both systems.
For 64bit, only the server system is included. On Solaris, the 64bit JRE is an overlay on top of the
32bit 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/java1.5.0sun.
4.19 Set the default JVM typeTag(s): Environment

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.20 Select a particular JRE from the command lineTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0634.html
It's possible to have many JRE sidebyside on a computer.
If the JRE is properly installed on Windows, informations about each version are stored in the
registry. The installation process installs a special java.exe in the system PATH. So you don't need
to alter you PATH because this special java.exe will find the current JRE. From a command line,
type java version to display the current jre version installed.
With release 1.6, it's now possible to select a different JRE installation than the last one without any
registry modification.
The JRE installation are listed in the registry in the key
HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
Take this simple test class
public class ShowVersion {
public static void main(String args[]) {
System.out.println(System.getProperty("java.version"));
}
}

On a system, with 1.6 and 1.5 installed. If you type


> java ShowVersion

It's probably the 1.6 JRE that will be used since it's the last installed.

4.20 Select a particular JRE from the command lineTag(s): Environment

To force the 1.5 JRE instead, use this command line.


> java version:"1.5" ShowVersion

If the bytecode is incompatible with the given JRE then .. it won't work, of course.
ref : Java 6 technotes
You can always give the complete path to use a specific installation. Launching the JVM this way
does not use the registry setting at all.
>"C:\Program Files\Java\j2re1.4.1_02\bin\java" version
java version "1.4.1_02"

4.21 Get the PID (pure Java solution)Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0651.html
This solution use the RuntimeMXBean. The name of the bean contains the pid (ex.
12345@localhost).
Warning : The returned name string can be any arbitrary string and a Java virtual machine
implementation can choose to embed platformspecific useful information in the returned name
string.
On the Sun JVM (Windows plateform), the PID is present.
public class SystemUtils {
private SystemUtils() {}
public static long getPID() {
String processName =
java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
return Long.parseLong(processName.split("@")[0]);
}
public static void main(String[] args) {
String msg = "My PID is " + SystemUtils.getPID();
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "SystemUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

The result is

4.21 Get the PID (pure Java solution)Tag(s): Environment

For a JavaJNI solution, see this HowTo.

4.22 Get the PIDTag(s): Environment JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0467.html
class JavaHowTo {
public native long getCurrentProcessId();
static {
System.loadLibrary("jni2");
}
}
public class JNIJavaHowTo {
public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
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.


For a Javaonly solution, see this HowTo

4.22 Get the PIDTag(s): Environment JNI

4.23 Set default value for java property (system wide)Tag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javasetjavapropertiessystemwide.html
If you find yourself using the same options over and over before laucing a java process, you can set
up a special environment variable to contain your default options and the JVM will pick up the the
values.
If the Java process is launch via java.exe then the environment variable is called
_JAVA_OPTIONS,
e.g. In Windows:
set _JAVA_OPTIONS=Xms64m Xmx128m Dawt.useSystemAAFontSettings=lcd

In Linux:
export _JAVA_OPTIONS='Xms64m Xmx128m Dawt.useSystemAAFontSettings=lcd'

ref : http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html
If the Java process is launch via javaw.exe (Applet) then the environment variable is called
_JPI_VM_OPTIONS.
For example :
_JPI_VM_OPTIONS = Dsome.property=true

For a Java Web Start process (javaws.exe), the environment variable is called
JAVAWS_VM_ARGS.
For example :
JAVAWS_VM_ARGS = Dsome.property=true
ref : http://docs.oracle.com/javase/7/docs/webnotes/tsg/TSGDesktop/html/plugin.html#gcexdd

4.23 Set default value for java property (system wide)Tag(s): Environment

4.24 Detect if running in a debug modeTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectifrunningindebugmode.html
If you want to detect if your program is running in debug mode (ex. Eclipse).
public class Test {
public static void main(String args[]) {
boolean isDebug =
java.lang.management.ManagementFactory.getRuntimeMXBean().
getInputArguments().toString().indexOf("agentlib:jdwp") > 0;
System.out.println("In debug : " + isDebug);
}
}

4.25 Capture the output of JAVACTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0147.html
method 1a : redirect to a file
// Win95 (?)
javac JDjavac.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


// 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

4.24 Detect if running in a debug modeTag(s): Environment

( 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.26 Freeze the JVIEW window in MS VJ++Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0148.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 Howto for a better way...

4.27 Wrap a Java beans in a COM objectTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0045.html
The previous Howto was using a Microsoft utility to enable access to Java objects from a
COMaware development tool. Sun provides a similar tool but you must package everything in a jar
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 Plugin 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 :

4.26 Freeze the JVIEW window in MS VJ++Tag(s): Environment

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
JavaBean: 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 hardcoded 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 commandline interface available in the packager if you want to bypass the wizard.

To test it, try this VbScript (TestJavaBeansSays.vbs)


' VBSCRIPT connect to a Java Bean
Dim objJava
Set objJava = WScript.CreateObject("JavaBeanSays.Bean")

4.26 Freeze the JVIEW window in MS VJ++Tag(s): Environment

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 PLUGIN SCRIPTING documentation (jdk1.2) or (jsdk1.4). document for more infos.

4.28 Know details about the JAVA at runtimeTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0149.html
Applets can read certain system properties by invoking System.getProperty(String key)
java.version
java.vendor
java.vendor.url
os.name
os.arch
file.separator
path.separator
line.separator
java.class.version

Java version number


Java vendorspecific string
Java vendor URL
Operating system name
Operating system architecture
File separator (eg, "/")
Path separator (eg, ":")
Line separator
Java class version number

But applets are prevented from reading these system properties (for security reason):
java.home
java.class.path
user.name
user.home
user.dir

Java installation directory


Java classpath
User account name
User home directory
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();

4.28 Know details about the JAVA at runtimeTag(s): Environment

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.29 Detect the Microsoft JVM version installedTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0327.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.29 Detect the Microsoft JVM version installedTag(s): Environment

4.30 Run JAVA as a Windows serviceTag(s): Environment Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0151.html
A solution adapted to Java, is YAJSW( Yet Another Java Service Wrapper ) (
http://yajsw.sourceforge.net/ ) (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 Xtendedswitch) 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.31 Execute a class from Windows ExplorerTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0328.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.
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.
4.30 Run JAVA as a Windows serviceTag(s): Environment Open Source

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
textonly Java program). Called it CRunJava.vbs . Then you will have two choices from the
SendTo menu, one for consolebased program and one for GUIbased (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
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

4.30 Run JAVA as a Windows serviceTag(s): Environment Open Source

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.32 Create an icon to launch java apps for Windows?Tag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0157.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.33 Fix the "out of environment" error when setting a new


CLASSPATHTag(s): Environment
4.32 Create an icon to launch java apps for Windows?Tag(s): Environment

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/java0159.html
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.34 Query Windows registryTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0480.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";

4.34 Query Windows registryTag(s): Environment

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();
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();

4.34 Query Windows registryTag(s): Environment

}
catch (Exception e) {
return null;
}
}
static class StreamReader extends Thread {
private InputStream is;
private StringWriter sw;
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.


For a better way to access the Registry, see Read/Write Windows Registry using JNA.

4.35 Read/Write the Registry (Windows)Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0630.html
The JDK contains the required code (java.util.prefs.WindowsPreferences) to access the Windows
registry but to preserve the "purity" of Java, the code is declared as private so it's not visible. The
trick is to use reflection to access private methods defined in the WindowsPreference class.
This technique was first seen in this post.

4.35 Read/Write the Registry (Windows)Tag(s): Environment

Remember : This code is a hack and may break anytime. A better alternative is to use JNA.
import
import
import
import
import
import
import

java.lang.reflect.InvocationTargetException;
java.lang.reflect.Method;
java.util.HashMap;
java.util.Map;
java.util.ArrayList;
java.util.List;
java.util.prefs.Preferences;

public class WinRegistry {


// inspired by
// http://javabyexample.wisdomplug.com/javaconcepts/34corejava/62javaregistrywrapper.ht
// http://www.snipcode.org/java/1java/23javaclassforaccessingreadingandwritingfromw
// http://snipplr.com/view/6620/accessingwindowsregistryinjava/
public static final int HKEY_CURRENT_USER = 0x80000001;
public static final int HKEY_LOCAL_MACHINE = 0x80000002;
public static final int REG_SUCCESS = 0;
public static final int REG_NOTFOUND = 2;
public static final int REG_ACCESSDENIED = 5;
private
private
private
private
private
private
private
private
private
private
private
private
private
private
private

static
static
static
static
static
static
static
static
static
static
static
static
static
static
static

final int KEY_ALL_ACCESS = 0xf003f;


final int KEY_READ = 0x20019;
Preferences userRoot = Preferences.userRoot();
Preferences systemRoot = Preferences.systemRoot();
Class<? extends Preferences> userClass = userRoot.getClass();
Method regOpenKey = null;
Method regCloseKey = null;
Method regQueryValueEx = null;
Method regEnumValue = null;
Method regQueryInfoKey = null;
Method regEnumKeyEx = null;
Method regCreateKeyEx = null;
Method regSetValueEx = null;
Method regDeleteKey = null;
Method regDeleteValue = null;

static {
try {
regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey",
new Class[] { int.class, byte[].class, int.class });
regOpenKey.setAccessible(true);
regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey",
new Class[] { int.class });
regCloseKey.setAccessible(true);
regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx",
new Class[] { int.class, byte[].class });
regQueryValueEx.setAccessible(true);
regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue",
new Class[] { int.class, int.class, int.class });
regEnumValue.setAccessible(true);
regQueryInfoKey = userClass.getDeclaredMethod("WindowsRegQueryInfoKey1",
new Class[] { int.class });
regQueryInfoKey.setAccessible(true);
regEnumKeyEx = userClass.getDeclaredMethod(
"WindowsRegEnumKeyEx", new Class[] { int.class, int.class,
int.class });
regEnumKeyEx.setAccessible(true);
regCreateKeyEx = userClass.getDeclaredMethod(
"WindowsRegCreateKeyEx", new Class[] { int.class,
byte[].class });
regCreateKeyEx.setAccessible(true);
regSetValueEx = userClass.getDeclaredMethod(

4.35 Read/Write the Registry (Windows)Tag(s): Environment

"WindowsRegSetValueEx", new Class[] { int.class,


byte[].class, byte[].class });
regSetValueEx.setAccessible(true);
regDeleteValue = userClass.getDeclaredMethod(
"WindowsRegDeleteValue", new Class[] { int.class,
byte[].class });
regDeleteValue.setAccessible(true);
regDeleteKey = userClass.getDeclaredMethod(
"WindowsRegDeleteKey", new Class[] { int.class,
byte[].class });
regDeleteKey.setAccessible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
private WinRegistry() {

/**
* Read a value from key and value name
* @param hkey
HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
* @param key
* @param valueName
* @return the value
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static String readString(int hkey, String key, String valueName)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
if (hkey == HKEY_LOCAL_MACHINE) {
return readString(systemRoot, hkey, key, valueName);
}
else if (hkey == HKEY_CURRENT_USER) {
return readString(userRoot, hkey, key, valueName);
}
else {
throw new IllegalArgumentException("hkey=" + hkey);
}
}
/**
* Read value(s) and value name(s) form given key
* @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
* @param key
* @return the value name(s) plus the value(s)
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static Map<String, String> readStringValues(int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
if (hkey == HKEY_LOCAL_MACHINE) {
return readStringValues(systemRoot, hkey, key);
}
else if (hkey == HKEY_CURRENT_USER) {
return readStringValues(userRoot, hkey, key);
}

4.35 Read/Write the Registry (Windows)Tag(s): Environment

else {
throw new IllegalArgumentException("hkey=" + hkey);
}
}
/**
* Read the value name(s) from a given key
* @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
* @param key
* @return the value name(s)
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static List<String> readStringSubKeys(int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
if (hkey == HKEY_LOCAL_MACHINE) {
return readStringSubKeys(systemRoot, hkey, key);
}
else if (hkey == HKEY_CURRENT_USER) {
return readStringSubKeys(userRoot, hkey, key);
}
else {
throw new IllegalArgumentException("hkey=" + hkey);
}
}
/**
* Create a key
* @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
* @param key
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static void createKey(int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int [] ret;
if (hkey == HKEY_LOCAL_MACHINE) {
ret = createKey(systemRoot, hkey, key);
regCloseKey.invoke(systemRoot, new Object[] { new Integer(ret[0]) });
}
else if (hkey == HKEY_CURRENT_USER) {
ret = createKey(userRoot, hkey, key);
regCloseKey.invoke(userRoot, new Object[] { new Integer(ret[0]) });
}
else {
throw new IllegalArgumentException("hkey=" + hkey);
}
if (ret[1] != REG_SUCCESS) {
throw new IllegalArgumentException("rc=" + ret[1] + " key=" + key);
}
}
/**
* Write a value in a given key/value name
* @param hkey
* @param key
* @param valueName

4.35 Read/Write the Registry (Windows)Tag(s): Environment

* @param value
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static void writeStringValue
(int hkey, String key, String valueName, String value)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
if (hkey == HKEY_LOCAL_MACHINE) {
writeStringValue(systemRoot, hkey, key, valueName, value);
}
else if (hkey == HKEY_CURRENT_USER) {
writeStringValue(userRoot, hkey, key, valueName, value);
}
else {
throw new IllegalArgumentException("hkey=" + hkey);
}
}
/**
* Delete a given key
* @param hkey
* @param key
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static void deleteKey(int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int rc = 1;
if (hkey == HKEY_LOCAL_MACHINE) {
rc = deleteKey(systemRoot, hkey, key);
}
else if (hkey == HKEY_CURRENT_USER) {
rc = deleteKey(userRoot, hkey, key);
}
if (rc != REG_SUCCESS) {
throw new IllegalArgumentException("rc=" + rc + " key=" + key);
}
}
/**
* delete a value from a given key/value name
* @param hkey
* @param key
* @param value
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public static void deleteValue(int hkey, String key, String value)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int rc = 1;
if (hkey == HKEY_LOCAL_MACHINE) {
rc = deleteValue(systemRoot, hkey, key, value);
}
else if (hkey == HKEY_CURRENT_USER) {

4.35 Read/Write the Registry (Windows)Tag(s): Environment

rc = deleteValue(userRoot, hkey, key, value);


}
if (rc != REG_SUCCESS) {
throw new IllegalArgumentException("rc=" + rc + "
}

key=" + key + "

value=" + value);

}
// =====================
private static int deleteValue
(Preferences root, int hkey, String key, String value)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS) });
if (handles[1] != REG_SUCCESS) {
return handles[1]; // can be REG_NOTFOUND, REG_ACCESSDENIED
}
int rc =((Integer) regDeleteValue.invoke(root,
new Object[] {
new Integer(handles[0]), toCstr(value)
})).intValue();
regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
return rc;
}
private static int deleteKey(Preferences root, int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int rc =((Integer) regDeleteKey.invoke(root,
new Object[] { new Integer(hkey), toCstr(key) })).intValue();
return rc; // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS
}
private static String readString(Preferences root, int hkey, String key, String value)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
new Integer(hkey), toCstr(key), new Integer(KEY_READ) });
if (handles[1] != REG_SUCCESS) {
return null;
}
byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] {
new Integer(handles[0]), toCstr(value) });
regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
return (valb != null ? new String(valb).trim() : null);
}
private static Map<String,String> readStringValues
(Preferences root, int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
HashMap<String, String> results = new HashMap<String,String>();
int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
new Integer(hkey), toCstr(key), new Integer(KEY_READ) });
if (handles[1] != REG_SUCCESS) {
return null;
}
int[] info = (int[]) regQueryInfoKey.invoke(root,

4.35 Read/Write the Registry (Windows)Tag(s): Environment

new Object[] { new Integer(handles[0]) });


// int count = info[2]; // count
int count = info[0];
// bug fix 20130112
int maxlen = info[3]; // value length max
for(int index=0; index<count; index++) {
byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] {
new Integer
(handles[0]), new Integer(index), new Integer(maxlen + 1)});
String value = readString(hkey, key, new String(name));
results.put(new String(name).trim(), value);
}
regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
return results;
}
private static List<String> readStringSubKeys
(Preferences root, int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
List<String> results = new ArrayList<String>();
int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
new Integer(hkey), toCstr(key), new Integer(KEY_READ)
});
if (handles[1] != REG_SUCCESS) {
return null;
}
int[] info = (int[]) regQueryInfoKey.invoke(root,
new Object[] { new Integer(handles[0]) });
// int count = info[2]; // count
int count = info[0];
// bug fix 20130112
int maxlen = info[3]; // value length max
for(int index=0; index<count; index++) {
byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] {
new Integer
(handles[0]), new Integer(index), new Integer(maxlen + 1)
});
results.add(new String(name).trim());
}
regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
return results;
}
private static int [] createKey(Preferences root, int hkey, String key)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
return (int[]) regCreateKeyEx.invoke(root,
new Object[] { new Integer(hkey), toCstr(key) });
}
private static void writeStringValue
(Preferences root, int hkey, String key, String valueName, String value)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException
{
int[] handles = (int[]) regOpenKey.invoke(root, new Object[] {
new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS) });
regSetValueEx.invoke(root,
new Object[] {

4.35 Read/Write the Registry (Windows)Tag(s): Environment

new Integer(handles[0]), toCstr(valueName), toCstr(value)


});
regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) });
}
// utility
private static byte[] toCstr(String str) {
byte[] result = new byte[str.length() + 1];
for (int i = 0; i < str.length(); i++) {
result[i] = (byte) str.charAt(i);
}
result[str.length()] = 0;
return result;
}
}

How to use it :
package com.rgagnon.howto;
public class WinRegistryTest {
public static void main(String args[]) throws Exception {
String value = "";
// IE Download directory (HKEY_CURRENT_USER)
value = WinRegistry.readString(
WinRegistry.HKEY_CURRENT_USER,
"Software\\Microsoft\\Internet Explorer",
"Download Directory");
System.out.println("IE Download directory = " + value);
// Query for Acrobat Reader installation path (HKEY_LOCAL_MACHINE)
value = WinRegistry.readString(
WinRegistry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\AcroRd32.exe",
"");
System.out.println("Acrobat Reader Path = " + value);

/*
this code is broken under win7 64 :(

20130112

// Loop through installed JRE and print the JAVA_HOME value


// HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
java.util.Map res1 = WinRegistry.readStringValues(
WinRegistry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Wow6432Node\\JavaSoft\\Java Runtime Environment");
System.out.println("1:" + res1.toString());
*/
// on 64bit Windows, you need Wow6432Node to access 32bit related information
//
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion"
java.util.List res2 = WinRegistry.readStringSubKeys(
WinRegistry.HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
System.out.println(res2.toString());
WinRegistry.createKey(
WinRegistry.HKEY_CURRENT_USER, "SOFTWARE\\rgagnon.com");
WinRegistry.writeStringValue(
WinRegistry.HKEY_CURRENT_USER,
"SOFTWARE\\rgagnon.com",

4.35 Read/Write the Registry (Windows)Tag(s): Environment

"HowTo",
"java");
//
//
//
//
//
//

WinRegistry.deleteValue(
WinRegistry.HKEY_CURRENT_USER,
"SOFTWARE\\rgagnon.com", "HowTo");
WinRegistry.deleteKey(
WinRegistry.HKEY_CURRENT_USER,
"SOFTWARE\\rgagnon.com\\");
System.out.println("Done." );
}

The output :
IE Download directory = C:\Documents and Settings\Ral\Bureau
Acrobat Reader Path = C:\Program Files\Adobe\Acrobat 5.0\Reader\AcroRd32.exe
{SubVersionNumber=, CurrentBuild=1.511.1 () (snipped)...
[Accessibility, AeDebug, Asr, Classes, Compatibility, (snipped)...
Done.

4.36 Quickly retrieve available Java JVM on a workstation


(Windows)Tag(s): Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0525.html

4.37 Using regedit


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"
[HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.4.1_02]
"JavaHome"="C:\\Program Files\\Java\\j2re1.4.1_02"

4.36 Quickly retrieve available Java JVM on a workstation (Windows)Tag(s): Environment

"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"

4.38 Using a CMD file


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

Output example :
C:\temp>findjava.cmd
Java Version = 1.6
Java home path (per registry) = C:\\applications\\dev\\jre6

Note :
The above script returns the default JVM if the PATH variable does not override it!
Oracle client installation is famous to force an outdated Java at the beginning of the PATH. This
oneliner displays the java.exe (if any) found in the PATH :
c:\> for %i in (java.exe) do @echo.
C:\WINDOWS\system32\java.exe

%~$PATH:i

The java.exe in the system32 relies on the CurrentVersion registry setting to determine which
registry key to use to look up the location of the Java RE.

4.38 Using a CMD file

4.39 Get a return code from a VBSTag(s): IO Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0575.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 ");
msgBox("Check if service 'foo' is running (should be no)");
result = isServiceRunning("foo") ? "" : " NOT ";
msgBox("service 'foo' is " + result + " running ");
}

4.39 Get a return code from a VBSTag(s): IO Environment

public static void msgBox(String msg) {


javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

4.40 List currently running processes (Windows)Tag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0593.html

4.40.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<String> listRunningProcesses() {
List<String> processes = new ArrayList<String>();
try {
String line;
Process p = Runtime.getRuntime().exec("tasklist.exe /fo csv /nh");
BufferedReader input = new BufferedReader
(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
if (!line.trim().equals("")) {
// keep only the process name
line = line.substring(1);
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();

4.40 List currently running processes (Windows)Tag(s): Environment

String result = "";


// 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);
}
}
Thanks to M. Korbel

4.40.2 Using a VBS


Another technique to build the required VBScript onthefly, execute it and capture its output.
import
import
import
import
import

java.io.BufferedReader;
java.io.File;
java.io.FileWriter;
java.io.InputStreamReader;
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;

4.40.2 Using a VBS

while ((line = input.readLine()) != null) {


processList.add(line);
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return processList;
}
public static void main(String[] args){
List<String> processes = VBSUtils.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);
}
}

See this HowTo to check for a specific application is running or not.

4.41 Check if a program or process is running (Windows)Tag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0610.html
Based on this HowTo which list the currently running processes, we adapt it to check for a specific
program name.
In this example, we check if the text editor TextPad.exe is running.
import
import
import
import

java.io.BufferedReader;
java.io.File;
java.io.FileWriter;
java.io.InputStreamReader;

4.41 Check if a program or process is running (Windows)Tag(s): Environment

public class VBSUtils {


private VBSUtils() { }
public static boolean isRunning(String process) {
boolean found = false;
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 * from Win32_Process where name='" + 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;
line = input.readLine();
if (line != null) {
if (line.equals(process)) {
found = true;
}
}
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return found;
}
public static void main(String[] args){
boolean result = VBSUtils.isRunning("TextPad.exe");
msgBox("Is TextPad running ?

" + (result ? " Yes" : "No"));

}
public static void msgBox(String msg) {
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, msg, "VBSUtils", javax.swing.JOptionPane.DEFAULT_OPTION);
}
}

See also this HowTo

4.41 Check if a program or process is running (Windows)Tag(s): Environment

4.42 Detect if a process is running using WMIC Tag(s): Misc


Prog HowTo Java Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../gp/windowsdetectifaprocessisrunning.html
WMIC is a powerful Windows utility. You can use to know if a particular process is running or not.
This example detects if a Tomcat instance (can be anything, ex: Apache or Excel) is running from a
batch file.
@echo off
wmic process list brief | find /i "tomcat.exe"
set result=%ERRORLEVEL%
if "%result%"=="1" echo "not running"
if "%result%"=="0" echo "running"

/i is to make the find operation caseinsensitive.


For Java code :
import
import
import
import
import
import

java.io.BufferedReader;
java.io.IOException;
java.io.InputStream;
java.io.InputStreamReader;
java.util.ArrayList;
java.util.List;

public class WindowsUtils {


private WindowsUtils() {}
public static boolean isProcessRunning(String processName) throws IOException {
InputStream is = null;
InputStreamReader isr = null;
BufferedReader br = null;
List<String> command = new ArrayList<String>();
command.add("WMIC");
command.add("process");
command.add("list");
command.add("brief");
try {
ProcessBuilder builder = new ProcessBuilder(command);
Process process = builder.start();
is = process.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line;
processName = processName.toUpperCase();
while ((line = br.readLine()) != null) {
if (line.toUpperCase().indexOf(processName) > 1) return true;
}
return false;
}
finally {
if (br != null) br.close();
if (isr != null) isr.close();
if (is != null) is.close();
}

4.42 Detect if a process is running using WMIC Tag(s): Misc Prog HowTo Java Environment

}
public static void main(String[] args) throws IOException {
System.out.println(WindowsUtils2.isProcessRunning("excel.exe"));
}
}

See also this HowTo.

4.43 Windows registry vs. Java JDK/JRE installationTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0604.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
"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 WebStartbased programs, the registry is always used to determine the
current JRE.

4.43 Windows registry vs. Java JDK/JRE installationTag(s): Environment

4.44 Get the current Java version from a BAT fileTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0642.html
[j.cmd]
@echo off
cls
setlocal ENABLEEXTENSIONS
set KEY_NAME="HKLM\SOFTWARE\JavaSoft\Java Runtime Environment"
set VALUE_NAME=CurrentVersion
::
:: get the current version
::
FOR /F "usebackq skip=4 tokens=3" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO (
set ValueValue=%%A
)
if defined ValueValue (
@echo the current Java runtime is %ValueValue%
) else (
@echo %KEY_NAME%\%VALUE_NAME% not found.
goto end
)
set JAVA_CURRENT="HKLM\SOFTWARE\JavaSoft\Java Runtime Environment\%ValueValue%"
set JAVA_HOME=JavaHome

::
:: get the javahome
::
FOR /F "usebackq skip=4 tokens=3,4" %%A IN (`REG QUERY %JAVA_CURRENT% /v %JAVA_HOME% 2^>nul`) D
set JAVA_PATH=%%A %%B
)
echo the path of the current Java JVM according to the registry is
echo %JAVA_PATH%
echo.
echo now if we try it :
"%JAVA_PATH%\bin\java.exe" version
:end
>j.cmd
the current Java runtime is 1.6
the path of the current Java JVM according to the registry is
C:\Program Files\Java\jre1.6.0_06
now if we try it :
java version "1.6.0_06"
Java(TM) SE Runtime Environment (build 1.6.0_06b02)

4.44 Get the current Java version from a BAT fileTag(s): Environment

Java HotSpot(TM) Client VM (build 10.0b22, mixed mode, sharing)

4.45 Get the Windows "My Documents" pathTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0572.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.
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());
}
}

See also Get Windows Special Folders (JNA)

4.46 Get the Windows Desktop pathTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0652.html
import java.io.*;
public class WindowsUtils {
private static final String REGQUERY_UTIL = "reg query ";
private static final String REGSTR_TOKEN = "REG_SZ";
private static final String DESKTOP_FOLDER_CMD = REGQUERY_UTIL +
"\"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\"
+ "Explorer\\Shell Folders\" /v DESKTOP";
private WindowsUtils() {}
public static String getCurrentUserDesktopPath() {
try {

4.45 Get the Windows "My Documents" pathTag(s): Environment

Process process = Runtime.getRuntime().exec(DESKTOP_FOLDER_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;
}
}

/**
* @param args
*/
public static void main(String[] args) {
System.out.println("Desktop directory : "
+ getCurrentUserDesktopPath());
}
static class StreamReader extends Thread {
private InputStream is;
private StringWriter sw;
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();
}
}
}

See also Get Windows Special Folders (JNA)

4.45 Get the Windows "My Documents" pathTag(s): Environment

4.47 Get the Windows Special FoldersTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0653.html
import
import
import
import

java.io.BufferedReader;
java.io.File;
java.io.FileWriter;
java.io.InputStreamReader;

public class VBSUtils {


public
public
public
public
public
public
public
public
public
public
public
public

static
static
static
static
static
static
static
static
static
static
static
static

String
String
String
String
String
String
String
String
String
String
String
String

private VBSUtils() {

SF_ALLUSERSDESKTOP
SF_ALLUSERSSTARTMENU
SF_ALLUSERSPROGRAMS
SF_ALLUSERSSTARTUP
SF_DESKTOP
SF_FAVORITES
SF_MYDOCUMENT
SF_PROGRAMS
SF_RECENT
SF_SENDTO
SF_STARTMENU
SF_STARTUP

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

"AllUsersDesktop";
"AllUsersStartMenu";
"AllUsersPrograms";
"AllUsersStartup";
"Desktop";
"Favorites";
"MyDocuments";
"Programs";
"Recent";
"SendTo";
"StartMenu";
"Startup";

public static String getSpecialFolder(String folder) {


String result = "";
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"
+ "wscript.echo WshShell.SpecialFolders(\"" + folder + "\")\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()));
result = input.readLine();
input.close();
}
catch(Exception e){
e.printStackTrace();
}
return result;
}
public static void main(String[] args){
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_ALLUSERSDESKTOP));
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_DESKTOP));
System.out.println(VBSUtils.getSpecialFolder(VBSUtils.SF_PROGRAMS));
}
}

4.47 Get the Windows Special FoldersTag(s): Environment

See also :
Get Windows Desktop path using the registry
Get Windows "My Documents" path using FileSystemView.getDefaultDirectory()
See also Get Windows Special Folders (JNA)

4.48 Create an Internet Shortcut (Windows)Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0660.html
import java.io.*;
public class WindowsUtils {
private WindowsUtils() {

// see note
private static final String WINDOWS_DESKTOP = "Desktop";
/**
* the current user desktop path
* @return the current user desktop path
*/
public static String getWindowsCurrentUserDesktopPath() {
return System.getenv("userprofile") + "/" + WINDOWS_DESKTOP ;
}
/**
* Create an Internet shortcut on User's Desktop no icon specified
* @param name
name of the shortcut
* @param target URL
* @throws IOException
*/
public static void createInternetShortcutOnDesktop(String name, String target)
throws IOException
{
String path = getWindowsCurrentUserDesktopPath() + "/"+ name + ".URL";
createInternetShortcut(name, path, target, "");
}
/**
* Create an Internet shortcut on User's Desktop, icon specified
* @param name
name of the shortcut
* @param target URL
* @param icon
URL (ex. http://www.server.com/favicon.ico)
* @throws IOException
*/
public static void createInternetShortcutOnDesktop
(String name, String target, String icon)
throws IOException
{
String path = getWindowsCurrentUserDesktopPath() + "/"+ name + ".URL";

4.48 Create an Internet Shortcut (Windows)Tag(s): Environment

createInternetShortcut(name, path, target, icon);


}
/**
* Create an Internet shortcut
* @param name
name of the shortcut
* @param where
location of the shortcut
* @param target
URL
* @param icon
URL (ex. http://www.server.com/favicon.ico)
* @throws IOException
*/
public static void createInternetShortcut
(String name, String where, String target, String icon)
throws IOException
{
FileWriter fw = new FileWriter(where);
fw.write("[InternetShortcut]\n");
fw.write("URL=" + target + "\n");
if (!icon.equals("")) {
fw.write("IconFile=" + icon + "\n");
}
fw.flush();
fw.close();
}
/**
* @param args
*/
public static void main(String[] args) throws IOException {
WindowsUtils.createInternetShortcutOnDesktop
("GOOGLE", "http://www.google.com");
}
}

NOTE:
Prior Vista, the desktop path for a localized Windows can be different. With an english version, it's
Desktop while for a french version, it's called Bureau.
The only way to get the right name is to ask the Registry, see this HowTo.

4.49 Detect if running in remote session (Windows)Tag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectremotesession.html
[Windows only]
To decect if an application is running in a Remote Desktop session, you can call the Windows API
GetSystemMetrics. The GetSystemMetrics() function will return a nonzero value with a
SM_REMOTESESSION parameter value if the application is associated with a client terminal
session.
4.49 Detect if running in remote session (Windows)Tag(s): Environment

It is useful to detect if running in a remote session to optimize visual effects or colors.


In Java, you need to use JNI (Java Native Interface) to call this Windows native API. Native Call is
an Open Source project which provide an easy way to that.
http://johannburkard.de/software/nativecall/
All you need is 2 jars (nativecall0,4,1.jar and nativeloader200505172341.jar) plus 1 DLL
(NativeCall.dll) in your classpath.
When running from Eclipse, the DLL should be in the bin directory of your application.
import java.io.IOException;
import com.eaio.nativecall.IntCall;
import com.eaio.nativecall.NativeCall;
public class WindowsUtils {
public static final int SM_REMOTESESSION = 4096;

// remote session

private WindowsUtils() {}
public static boolean isRemote() throws SecurityException, UnsatisfiedLinkError,
UnsupportedOperationException, IOException
{
NativeCall.init();
IntCall ic = null;
try {
ic = new IntCall("user32", "GetSystemMetrics");
int rc = ic.executeCall(new Integer(SM_REMOTESESSION));
return (rc gt; 0);
}
finally {
if (ic != null) ic.destroy();
}
}
public static void main(String ... args) throws Exception {
System.out.println(WindowsUtils.isRemote());
}
}

An easy way is to check the Windows environment variable sessionname. The value of this
environment variable will be 'Console' for a normal, local session. For an Remote Desktop session it
will contain the phrase 'RDP'.
public static boolean isRemoteDesktopSession() {
System.getenv("sessionname").toLowerCase().startsWith("rdp");
}

Note that environment varialbe values are read at the JVM startup. So if the JVM process was
started by a console session, but then accessed by an RDP session, further calls to
System.getenv("sessionname") still return 'Console'
See this HowTo to detect a Citrix session.

4.49 Detect if running in remote session (Windows)Tag(s): Environment

4.50 Detect if running a Citrix session (Windows)Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectifrunningincitrixsession.html
The easiest way is to query the environment variable SESSIONNAME. The value starts with ICA...
in a Citrix session, RDP if in remote desktop session or Console if directly on a workstation.
public static boolean isRemoteDesktopSession() {
System.getenv("sessionname").toLowerCase().startsWith("rdp");
}
public static boolean isCitrixSession() {
System.getenv("sessionname").toLowerCase().startsWith("ica");
}
public static boolean isConsoleSession() {
System.getenv("sessionname").toLowerCase().startsWith("console");
}

4.51 Create a Taglet to document database access


(Javadoc)Tag(s): Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0473.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

4.50 Detect if running a Citrix session (Windows)Tag(s): IO

4.51.1 newMethod
public java.lang.String newMethod()

Returns:
value
Table(s):
firstname
lastname

city
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 Ral Gagnon
*/
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;
}

4.51.1 newMethod

/**
* 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.
*/
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) {

4.51.1 newMethod

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=\"borderstyle:solid;"
+ " borderwidth:thin\">";
output +=
"<TH ALIGN=\"center\" STYLE=\"borderstyle:solid;"
+ " borderwidth:thin\">"
+ current[0] + "</TH>";
if (current.length > 1) {
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 :
4.51.1 newMethod

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.

4.52 Generate the Javadoc "en franais"Tag(s):


Environment Environment Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0437.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=Sousinterfaces de {0} dans {1}
doclet.Frame_Version=Version avec cadres

4.52 Generate the Javadoc "en franais"Tag(s): Environment Environment Internationalization

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>

4.53 Document a package using Javadoc Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0502.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.
4.53 Document a package using Javadoc Tag(s): Environment

\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:
packageinfo.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

4.54 Display a comment in a JavadocTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0615.html
Use the numerical identity to represent the / in the javadoc section to avoid any conflict with a real
comment.
import java.awt.*;
public class Example {
/**
* Simple Frame
* <pre>
* &#47;* create a frame *&#47;
* Frame f = new Frame()
* </pre>
* @param args
*/
public static void main(String args[]){
Frame f = new Frame();
f.setSize(200,200);
f.setVisible(true);
}
}

and the javadoc output is :

You can represent any character with a numerical identity, the syntax is &#nnn; where nnn is the
Unicode code (decimal value) of the character.

4.54 Display a comment in a JavadocTag(s): Environment

4.55 Display XML in a javadocTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0623.html
Let's say you have a comment like this
/**
* To use this class use this XML
*
* <xml>
*
<parameter>foo</parameter>
*
<value>bar</value>
* </xml>
*
*/

The XML will not be visible since it will embedded in the HTML as tag and not as text.
With Javadoc 1.5, you can use the {@code ... } command. :
/**
* To use this class use this XML
* <pre>
* {@code
* <xml>
*
<parameter>foo</parameter>
*
<value>bar</value>
* </xml>
* }
* </pre>
*/

With the previous versions, one way was to add a space after the <.
/**
* To use this class use this XML
* <pre>
* < xml>
*
< parameter>foo< /parameter>
*
< value>bar< /value>
* < /xml>
* }
* </pre>
*/

4.55 Display XML in a javadocTag(s): Environment

4.56 Add a copyright notice to a JavadocTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0626.html
Use the bottom parameter to the javadoc command line.
bottom '<font size="1"><a href="http://www.rgagnon.com">Reals HowTo</a>
<br>&copy; 2008 rgagnon.com</font>'

The result looks like this :

4.57 Use a Log fileTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0501.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


20050228 21:19:28 TestLog main

4.56 Add a copyright notice to a JavadocTag(s): Environment

GRAVE: my severe message


20050228 21:19:28 TestLog main
ATTENTION: my warning message
20050228 21:19:28 TestLog main
INFO: my info message

if the XMLFormatter is in use then the output is


<?xml version="1.0" encoding="windows1252" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>20050228T21: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>
<record>
<date>20050228T21: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>20050228T21: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);

4.56 Add a copyright notice to a JavadocTag(s): Environment

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");
}
}

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

4.56 Add a copyright notice to a JavadocTag(s): Environment

4.58 Trace the executionTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0301.html
Generate a StackTrace and then parse the StackTraceElements.
[LogUtils.java]
public class LogUtils {
private static final String NEWLINE = System.getProperty("line.separator");
private LogUtils (){

public static String getStack(int deep) {


// deep = 0 no level, only current calling method
//
n
from "n" levels
StringBuilder sb = new StringBuilder();
StackTraceElement ste [] = Thread.currentThread().getStackTrace();
int k = 2; // startingpoint 0:getstacktrace() 1: getStack()
int j = ste.length 1;
// process the stack
if (deep > j) deep = j;
else deep = deep + k;
while (k <= deep) {
String line = ste[k].toString();
sb.append(line + NEWLINE);
k++;
}
return sb.toString();
}
public static void main(String args[]){
Test test = new Test();
test.doit();
}
}
class Test {
public void doit() {
System.out.println("*Howto Trace only 1 level\n" + LogUtils.getStack(1));
System.out.println("*Howto Trace only 10 levels\n" + LogUtils.getStack(10));
System.out.println("*Howto Trace no level (current)\n" + LogUtils.getStack(0));
}
}

And the output should be


*Howto Trace only 1 level
Test.doit(LogUtils.java:35)
LogUtils.main(LogUtils.java:29)

4.58 Trace the executionTag(s): Environment

*Howto Trace only 10 levels


Test.doit(LogUtils.java:36)
LogUtils.main(LogUtils.java:29)
*Howto Trace no level (current)
Test.doit(LogUtils.java:37)

4.59 Time the executionTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0132.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(){
return (endstart);
}
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".

4.59 Time the executionTag(s): Environment

4.60 Log information efficiently (with Log4J)Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0527.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);

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());
}

4.60 Log information efficiently (with Log4J)Tag(s): Environment

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

4.61 Change the logging level onthefly (Log4J)Tag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0621.html
While you can set the logging level through the configuration properties file
; can be OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL
log4j.threshold=WARN

It may be useful to change it onthefly for debugging purpose. You need to get the Log4J "root"
Logger and then change its "level".
...
setLogLevel("DEBUG");
...
setLogLevel("INFO");
...
private void setLogLevel(String level) {
Logger root = Logger.getRootLogger();
if ("DEBUG".equals(level)) {
root.setLevel(org.apache.log4j.Level.DEBUG);
}
else {
root.setLevel(org.apache.log4j.Level.INFO);
}
}

4.61 Change the logging level onthefly (Log4J)Tag(s): Environment

4.62 Enable debug log level on OpenSource package(Apache


Commons Logging)Tag(s): Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaenabledebuglogging.html
Typically, Apache products are using the Apache Commons Logging.
You can enable the logging at the DEBUG level by simply setting 2 environment variable.
For example, if you have something using the Axis library to do a Web Service call, then
java.exe Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
Dorg.apache.commons.logging.simplelog.defaultlog=debug
MyClassUsingAxis

will launch the program and output to stdout the debugging information.

[DEBUG] ProjectResourceBundle getBundle(org.apache.axis,org.apache.axis.i18n,resource,null,.


[DEBUG] ProjectResourceBundle loadBundle: Ignoring MissingResourceException: Can't find bund
[DEBUG] ProjectResourceBundle Created org.apache.axis.i18n.resource, linked to parent null
[DEBUG] ProjectResourceBundle getBundle(org.apache.axis,org.apache.axis.utils,resource,null,
[DEBUG] ProjectResourceBundle loadBundle: Ignoring MissingResourceException: Can't find bund
[DEBUG] ProjectResourceBundle org.apache.axis.i18n.resource::handleGetObject(setMsgForm)
[DEBUG] SOAPPart Setting current message form to: FORM_STRING (currentMessage is now <?xml v
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://w
<soapenv:Header>
<ns1:biBusHeader soapenv:mustUnderstand="0" xmlns:ns1="http://developer.cognos.com/schemas/bi
</soapenv:Header>
<soapenv:Body>
<ns2:logon soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http:
...
[DEBUG]
[DEBUG]
[DEBUG]
[DEBUG]
[DEBUG]

HTTPSender
HTTPSender
HTTPSender
HTTPSender
HTTPSender

HTTP/1.1 405 Method Not Allowed


Allow OPTIONS, TRACE, GET, HEAD
ContentLength 1564
ContentType text/html
Server MicrosoftIIS/6.0

...

It's possible to enable only the logging for HTTP activities.


Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
Dorg.apache.commons.logging.simplelog.showdatetime=true
Dorg.apache.commons.logging.simplelog.log.httpclient.wire=debug
Dorg.apache.commons.logging.simplelog.log.org.apache.commons.httpclient=debug
2009/08/21 12:15:56:109 EDT [DEBUG] header >> "SOAPAction: urn:GeteBayOfficialTime[\r][\n]"
2009/08/21 12:15:56:109 EDT [DEBUG] header >> "UserAgent: Axis2[\r][\n]"

4.62 Enable debug log level on OpenSource package(Apache Commons Logging)Tag(s): Environment

2009/08/21
2009/08/21
2009/08/21
2009/08/21

12:15:56:109
12:15:56:109
12:15:56:109
12:15:56:109

EDT
EDT
EDT
EDT

[DEBUG]
[DEBUG]
[DEBUG]
[DEBUG]

header
header
header
header

>>
>>
>>
>>

"Host: api.sandbox.ebay.com[\r][\n]"
"ContentLength: 1546[\r][\n]"
"ContentType: text/xml; charset=UTF8[\r][\n]"
"[\r][\n]"

Apache PDFBox emits a lot of infos in debug mode.


To remove the debug mode for PDFBox :
if (logger.isDebugEnabled()) {
Logger logpdfengine = Logger.getLogger("org.apache.pdfbox.util.PDFStreamEngine");
logpdfengine.setLevel(org.apache.log4j.Level.OFF);
}

4.63 Use a JAR/ZIP/CAB file with an AppletTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0153.html
[JAR format]
JAR (Java ARchive) is a platformindependent 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 "realworld" 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 Howto.
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 :
4.63 Use a JAR/ZIP/CAB file with an AppletTag(s): Environment

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:

jar cvfO myArchive.jar *.class

[ZIP format]
JDK1.0.2 introduces the ZIP "uncompressed" 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 uncompressed). 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, nonMS 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

4.63 Use a JAR/ZIP/CAB file with an AppletTag(s): Environment

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.64 Make ZIP/JAR file always accessible from appletTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0154.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.65 Make a JAR executableTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0166.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.*;

4.64 Make ZIP/JAR file always accessible from appletTag(s): Environment

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.
ManifestVersion: 1.0
MainClass: MyClass
Classpath: .

MainClass specifies the entry point with the main(String args[]) method.
The Classpath 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 doubleclicking 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.

4.64 Make ZIP/JAR file always accessible from appletTag(s): Environment

On Windows (NT or better), you can also make JARs run from the commandline 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.66 Accessing jars from within a jarTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0319.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 ClassPath setting :
ManifestVersion: 1.0
MainClass: MyClass
ClassPath: Second.jar Third.jar

The value of the ClassPath 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 METAINF directory which will enable the application
class loader to download the right jar files when it is searching for classes or resources.

4.67 Access a JAR outside the CLASSPATHTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0409.html
import java.net.*;
import java.io.*;
public class ExtraLoader {
public static void main(String[] args) {
try {
URL urlA =

4.66 Accessing jars from within a jarTag(s): Environment

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.68 Extract a file from a JarTag(s): IO Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0429.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();
}

4.68 Extract a file from a JarTag(s): IO Environment

catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String args []){
new ExtractFromJAR().extractMyMDBFromJAR(".");
}
}

Grab this autorun Jar if you want to try it.


To create an autorun JAR, first create a manifest.mft
ManifestVersion: 1.0
Classpath: .\mydb.jar
MainClass: 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
String home = getClass().getProtectionDomain()
.getCodeSource().getLocation()
.getPath().replaceAll("%20", " ");

4.69 Determine if running from JARTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0391.html
package com.rgagnon;
public class HelloClass {
public static void main(String[] args) {
new HelloClass().say();
}

4.69 Determine if running from JARTag(s): Environment

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

Here a variation on this subject, a method to return the name of the current running jar.
package com.rgagnon.howto;
public class RunningJar {
public static void main(String[] args) {
String runningJarName = new RunningJar().getRunningJarName();
if (runningJarName != null) {
System.out.println("Running from " + runningJarName);
}
else {
System.out.println("Not running from a jar");
}
}
public String getRunningJarName() {
String className = this.getClass().getName().replace('.', '/');
String classJar =
this.getClass().getResource("/" + className + ".class").toString();
if (classJar.startsWith("jar:")) {
String vals[] = classJar.split("/");
for (String val: vals) {
if (val.contains("!")) {
return val.substring(0, val.length() 1);
}
}
}
return null;
}
}
/*
output :
>java jar yop.jar
Running from yop.jar
>ren yop.jar yip.jar

4.69 Determine if running from JARTag(s): Environment

>java jar yip.jar


Running from yip.jar
*/

See these related HowTo's : 1 2

4.70 Get list of classes in package (in a Jar)Tag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0513.html
import java.util.jar.*;
import java.util.*;
import java.io.*;
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;
}
/**

4.70 Get list of classes in package (in a Jar)Tag(s): Environment

*
*/
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.71 Add version to Jar packagingTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0388.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 :


ManifestVersion: 1.0
MainClass: com.rgagnon.Hello

Then build the executable Jar and run it.


>jar cvfm hello.jar MANIFEST.MF com\rgagnon\Hello.class

4.71 Add version to Jar packagingTag(s): Environment

>java jar hello.jar


Hello World!

Now modify the manifest to include versioning information.


ManifestVersion: 1.0
MainClass: com.rgagnon.Hello
SpecificationVersion: 2.1
ImplementationVersion: 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 : "
+ 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("ImplementationVersion");
}

4.71 Add version to Jar packagingTag(s): Environment

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("SpecificationVersion");
}
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("SpecificationVersion: "
+ JarUtils.getJarSpecificationVersion(javaMailJar));
System.out.println("ImplementationVersion: "
+ JarUtils.getJarImplementationVersion(javaMailJar));
/*
* output :
*
SpecificationVersion: 1.3
*
ImplementationVersion: 1.3.1
*/
}
}

4.72 Use ANT to Build a JAR with version/build numberTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0532.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 ...


4.72 Use ANT to Build a JAR with version/build numberTag(s): Environment

... and load it into your favorite editor. Type the following ant script and save it.
<project default="buildHello">
<target name="compile">
<javac srcdir="." />
</target>
<target name="buildHello" depends="compile" />
</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>
<target name="buildHello" depends="compile,jar" />
</project>

Execute your Ant script :


> ant jar
Buildfile: build.xml
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
55 Wed May 03 17:06:32
55 Wed May 03 17:06:32
335 Wed May 03 16:36:16

EST
EST
EST
EST

2006
2006
2006
2006

METAINF/
METAINF/MANIFEST.MF
howto/
howto/Hello.class

Try your new Jar file


> java cp Hello.jar howto.Hello
Hello World

Make your Jar autoexecutable 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"/>

4.72 Use ANT to Build a JAR with version/build numberTag(s): Environment

<delete file="MANIFEST.MF"/>
<manifest file="MANIFEST.MF">
<attribute name="BuiltBy" value="${user.name}"/>
<attribute name="MainClass" value="howto.Hello"/>
</manifest>
<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>
<target name="buildHello" depends="compile,jar" />
</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 hardcoded 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="BuiltBy" value="${user.name}"/>
<attribute name="MainClass" value="howto.Hello"/>
<attribute name="ImplementationVersion"
value="${version.num}b${build.number}"/>
</manifest>
<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>
<target name="buildHello" depends="compile,jar" />
</project>

If you examine the MANIFEST.MF, you now see a new entry


ImplementationVersion: 1.00b1

and after the next build operation, the entry will be


ImplementationVersion: 1.00b2

Modify the Hello class to read the ImplementationVersion information and display it.
package howto;
public class Hello {
public static void main( String[] args ){
System.out.println( "Hello World ");
System.out.println("version : " +

4.72 Use ANT to Build a JAR with version/build numberTag(s): Environment

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="BuiltBy" value="${user.name}"/>
<attribute name="MainClass" value="howto.Hello"/>
<attribute name="ImplementationVersion"
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
...
> java jar hello.jar
Hello World
version : 1.00b3

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="yyyyMMdd HH:mm:ss" />
</tstamp>
<manifest file="MANIFEST.MF">
<attribute name="BuiltBy" value="${user.name}"/>
<attribute name="MainClass" value="howto.Hello"/>
<attribute name="ImplementationVersion"
value="${version.num}b${build.number}"/>

4.72 Use ANT to Build a JAR with version/build numberTag(s): Environment

<attribute name="BuiltDate" value="${TODAY}"/>


</manifest>
<jar destfile="hello.jar"
basedir="."
includes="**/*.class"
manifest="MANIFEST.MF"
/>
</target>
See also this Howto .

4.73 Include all jars in the classpath definitionTag(s):


Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0587.html
Specifying all the required jar in the classpath can be a pain. Here some techniques to set the
classpath definition automatically.

4.74 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
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

4.73 Include all jars in the classpath definitionTag(s): Environment

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.75 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.76 JAR (and ANT)


The best solution when you have a jar is to try to include the required jars into the manifest
declaration.
ManifestVersion: 1.0
ClassPath:
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 ClassPath: 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
4.75 JDK6

java jar myjar.jar

the CLASSPATH definition (as defined by the environment variable) is overriden by the
"classpath" 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 classpath definition.
<target name="MyJar" depends="dist, compile" description="generate jar" >
<jar destfile="${dist}/${jar}">
<manifest>
<attribute name="MainClass" value="${Main_Class}"/>
<attribute name="ClassPath" 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>
<target depends="compile" name="buildjar">
<jar jarfile="${basedir}/${test.jar}">
<fileset dir="${build}" />
<manifest>
<attribute name="MainClass" value="com.mycompany.TestMain"/>
<attribute name="ClassPath" value="${manifest.classpath}"/>
</manifest>
</jar>
</target>

Latest Ant version (1.7) includes a task called ManifestClassPath which converts a classpath into
a spaceseparated list of items used to set the Manifest ClassPath attribute. See
http://ant.apache.org/manual/CoreTasks/manifestclasspath.html

<path id="buildclasspath">
<fileset dir="${build.dir}">
<include name="*.jar"/>
</fileset>
</path>
<manifestclasspath property="lib.list" jarfile="${build.dir}/${jar.file}">
<classpath refid="buildclasspath" />
</manifestclasspath>

4.75 JDK6

<jar>
...
<manifest>
<attribute name="MainClass" value="com.mycompany.TestMain"/>
<attribute name="ClassPath" value=". ${lib.list}"/>
</manifest>
...
</jar>

4.77 Detect browser type from an AppletTag(s):


Applet Environment Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectbrowsertypefromanapplet.html

4.78 Call a Javascript from the Applet


With LiveConnect, we call a javascript to return the "UserAgent".
To compile, make sure that you have the plugin.jar in the classpath (or Eclipse Build Path). This
jar is usually located in [JRE]/lib folder. During runtime, it's already included by the Java plugin so
you don't have to worry about that.
The Java class
import
import
import
import

java.applet.*;
java.awt.event.*;
java.awt.*;
netscape.javascript.*;

public class GetUserAgent extends Applet


implements ActionListener {
private static final long serialVersionUID = 1L;
TextField tf;
Button b1;
JSObject win;
public void init(){
setLayout(new FlowLayout());
tf = new TextField(35);
b1 = new Button("get useragent from javascript");
b1.addActionListener(this);
add(tf);add(b1);
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == b1) {

4.77 Detect browser type from an AppletTag(s): Applet Environment Javascript interaction

JSObject win = (JSObject)JSObject.getWindow(this);


tf.setText((String)win.eval("getUserAgent();"));
}
}
}

Don't forget the MAYSCRIPT parameter in the APPLET tag, it's required since the Applet is using
the JSObject to interact with the Javascript.
<html>
<head>
<script>
function getUserAgent() {
return navigator.userAgent;
}
</script>
</head><body>
<applet code="GetUserAgent.class" MAYSCRIPT height=100 width=500></Applet>
</body>
</html>

Try it here
You need to parse the returned value to detect browser type. Look at this utility,
http://code.google.com/p/useragentutils/ or at this code :
http://nerds.palmdrive.net/useragent/code.html to get the idea.

4.79 Get the value from the serverside


When serving the HTML containing the Applet, you add the UserAgent as parameter for the
Applet.
In a JSP/EL
<applet ... >
<param ... >
<param name="userAgent" value="${header['useragent']}" />
</applet>

and in the Applet


String userAgent = getParameter("userAgent");

and parse the returned value...

4.80 Detect if Java is enabled from HTMLTag(s): Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0161.html
4.79 Get the value from the serverside

For a Javascript solution, check this Howto

<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.81 See the Java Console Window Log (Java plugin)Tag(s):


Applet Environment
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0533.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

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

4.81 See the Java Console Window Log (Java plugin)Tag(s): Applet Environment

5 Internationalization
5.1 javainter

5.2 Load resources based upon client environment at


startupTag(s): Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0133.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
import
import
import
import

javax.swing.*;
java.awt.*;
java.awt.event.*;
java.util.*;
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 }));

5 Internationalization

add(aButton);
// 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");

5 Internationalization

public Object [][] getContents() {


return contents;
}
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 Howto.

5.3 Load resources dynamicallyTag(s): Internationalization


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0134.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
import
import
import
import

java.util.*;
java.text.*;
java.awt.*;
java.awt.event.*;
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);

5.3 Load resources dynamicallyTag(s): Internationalization

}
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();
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);

5.3 Load resources dynamicallyTag(s): Internationalization

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());
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" },

5.3 Load resources dynamicallyTag(s): Internationalization

{
{
{
{
{
{
};

"r0" , "United States" } ,


"r1", "France" } ,
"r2" , "Germany"},
"rDefault" , "r0" },
"btnQuit" , "Quit"},
"today" , " (en) {0,date,long}"},

[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" , "EtatsUnis" } ,
{ "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}"},
};
}

5.4 Load resources via a resources fileTag(s):


Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0135.html
5.4 Load resources via a resources fileTag(s): Internationalization

With the previous JAVA Howto, 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
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
import
import
import
import

java.util.*;
java.text.*;
java.awt.*;
java.awt.event.*;
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();

5.4 Load resources via a resources fileTag(s): Internationalization

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.4 Load resources via a resources fileTag(s): Internationalization

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);
}
}

[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=EtatsUnis
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

5.4 Load resources via a resources fileTag(s): Internationalization

today=(de) {0,date,dd.MM.yyyy}

5.5 Display "special character" using UnicodeTag(s):


Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0136.html
The copyright symbol :
String COPYRIGHT = "\u00a9";

The registered symbol :


String REGISTERED = "\u00ae";

The eurocurrency 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 accented letters :
\u00e0 \u00c0
\u00e1 \u00c1

5.5 Display "special character" using UnicodeTag(s): Internationalization

\u00e2
\u00e9
\u00e8
\u00ea
\u00ee
\u00e7

\u00c2
\u00c9
\u00c8
\u00ca
\u00ce
\u00c7

5.6 Display chinese/japanese charactersTag(s):


Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0137.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 dialogTag(s):


Internationalization Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0138.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

5.6 Display chinese/japanese charactersTag(s): Internationalization

SaveMsg=Voulezvous sauvegarder vos donnees

Then
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);
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);

5.6 Display chinese/japanese charactersTag(s): Internationalization

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.8 Validate/Convert a number using the current Locale()Tag(s):


Internationalization String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0139.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().
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class NumberUtils {
public static double getDoubleValue(String value) throws ParseException {
// use the default locale
return NumberUtils.getDoubleValue(Locale.getDefault(), value);
}
public static double getDoubleValue(Locale loc, String value)
throws ParseException
{
// use the default locale
return NumberFormat.getInstance(loc).parse(value).doubleValue();
}
public static String convertStringAsStringNumberUnLocalized(String value)
throws ParseException

5.8 Validate/Convert a number using the current Locale()Tag(s): Internationalization String/Number

{
// use the default locale
return convertStringAsStringNumberUnLocalized(Locale.getDefault(), value);
}
public static String convertStringAsStringNumberUnLocalized
(Locale loc, String value)
throws ParseException
{
double d = NumberUtils.getDoubleValue(loc, value);
return NumberFormat.getInstance(new Locale("us")).format(d);
}

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


System.out.println(Locale.getDefault());
System.out.println(NumberUtils.getDoubleValue("42,24"));
System.out.println(NumberUtils.getDoubleValue("42.24"));
System.out.println(NumberUtils.convertStringAsStringNumberUnLocalized
(new Locale("fr"), "42,24"));
/*
* output
* fr_CA
* 42.24
* 42.0
* 42.24
*/
}
}

5.9 Localize a JFileChooserTag(s): Internationalization Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0299.html
Modern Swing release have now builtin readytouse 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
5.9 Localize a JFileChooserTag(s): Internationalization Swing

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]
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);

5.9 Localize a JFileChooserTag(s): Internationalization Swing

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
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;

5.9 Localize a JFileChooserTag(s): Internationalization Swing

}
}
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.10 Disable localizationTag(s): Internationalization


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0418.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

5.11 Generate the Javadoc "en franais"Tag(s):


Environment Environment Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0437.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.
5.10 Disable localizationTag(s): Internationalization

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=Sousinterfaces 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>

5.10 Disable localizationTag(s): Internationalization

5.12 Sort a String arrayTag(s): Internationalization Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0343.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 {
static String [] words = { "Ral", "Real", "Raoul", "Rico" };
public static void main(String args[]) throws Exception {
try {
Writer w = getWriter();
w.write("Before :\n");
for (String s : words) {
w.write(s + " ");
}
java.util.Arrays.sort(words);
w.write("\nAfter :\n");
for (String s : words) {
w.write(s + " ");
}
w.flush();
w.close();
}
catch(Exception e){
e.printStackTrace();
}
}

// useful to output accentued characters to the console


public static Writer getWriter() throws UnsupportedEncodingException {
if (System.console() == null) {
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
return w;
}

5.12 Sort a String arrayTag(s): Internationalization Varia

else {
return System.console().writer();
}
}
}

The output is :
Before :
Ral Real Raoul Rico
After :
Raoul Real Rico Ral

which is wrong since we expect to find "Ral" after "Real".


To solve the problem , replace
java.util.Arrays.sort(words);

by
java.util.Arrays.sort(words, java.text.Collator.getInstance(java.util.Locale.FRENCH));
// or
// java.util.Arrays.sort(words, java.text.Collator.getInstance());

and the output will be :


Before :
Ral Real Raoul Rico
After :
Raoul Real Ral Rico

Or you can do it the long way :


import java.util.Locale;
import java.text.Collator;
...
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;
}
}
}
}

See this HowTo

5.12 Sort a String arrayTag(s): Internationalization Varia

5.13 Accentuated characters in Properties/ResourceBundle


fileTag(s): Internationalization Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0492.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).

5.14 Compare accentuated lettersTag(s):


Internationalization String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0496.html
From the 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.

In this code, we have 2 strings, "tat" and "famille". We expect that "tat" is before "famille". But
String.compareTo() will return that "famille" is before "tat".
class Test {
public static void main(String args[]) {
String s1 = "tat";
String s2 = "famille";
// here we are expecting "" < "f"
if (s1.compareTo(s2) > 0) {
if (s1.compareTo(s2) > 0) {
// s1 lexicographically follows s2 which is not true!

5.13 Accentuated characters in Properties/ResourceBundle fileTag(s): Internationalization Language

System.out.println("not ok " + s1 + " > " + s2 );


}
}
/*
output :
not ok tat > famille
*/
}

The fix is to use java.text.Collator.compareTo(). From the 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.
import java.text.Collator;
public class Test {
public static void main(String args[]) {
String s1 = "tat";
String s2 = "famille";
// Collator c = Collator.getInstance(java.util.Locale.FRANCE);
Collator c = Collator.getInstance();
c.setStrength(Collator.PRIMARY);
if (c.compare(s1, s2) < 0) {
// s2 lexicographically follows s1
System.out.println("ok " + s1 + " < " + s2);
}
}
/*
output :
ok tat < famille
*/
}

Equality
To compare without taking into account the presence of accentued so that "" == "e", we use a
Collator.
import java.text.Collator;
// import java.util.Locale;
public class TextTest {
public static void main(String ... args) {
String a = "Real";
String b = "Ral";
System.out.println(a + " and " + b + " equals? " +
check(a,b));
/*
* output :
* Real and Ral equals? true
*/
}

5.13 Accentuated characters in Properties/ResourceBundle fileTag(s): Internationalization Language

public static boolean check(String a, String b) {


// Collator c = Collator.getInstance(Locale.US);
//
// accent and upper/lowercase not taken into account
Collator c = Collator.getInstance();
c.setStrength(Collator.PRIMARY);
return (c.compare(a,b) == 0 );
}
}

See this HowTo.

5.15 Unaccent lettersTag(s): Internationalization String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0456.html
The following snippets remove from a String accented letters and replace them by their regular
ASCII equivalent.
These can be useful before inserting data into a database to made sorting easier.

5.15.1 Using java.text.Normalizer


It's a simple using the java.text.Normalizer class.
We are calling the normalize(). If we pass , the method returns a + ` . Then using a regular
expression, we clean up the string to keep only valid USASCII characters.
import java.text.Normalizer;
import java.util.regex.Pattern;
public class StringUtils {
private StringUtils() {}
public static String unAccent(String s) {
//
// JDK1.5
//
use sun.text.Normalizer.normalize(s, Normalizer.DECOMP, 0);
//
String temp = Normalizer.normalize(s, Normalizer.Form.NFD);
Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
return pattern.matcher(temp).replaceAll("");
}
public static void main(String args[]) throws Exception{
String value = " _ @";
System.out.println(StringUtils.unAccent(value));
// output : e a i _ @

5.15 Unaccent lettersTag(s): Internationalization String/Number

}
}

5.15.2 Using String.replaceAll()


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
s
s
s

=
=
=
=
=

s.replaceAll("[]","e");
s.replaceAll("[]","u");
s.replaceAll("[]","i");
s.replaceAll("[]","a");
s.replaceAll("","o");

s
s
s
s
s

=
=
=
=
=

s.replaceAll("[]","E");
s.replaceAll("[]","U");
s.replaceAll("[]","I");
s.replaceAll("[]","A");
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
}
}

5.15.3 The String.indexOf()


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
+ "AaOoNn"
// tilde
+ "AaEeIiOoUuYy" // umlaut
+ "Aa"
// ring
+ "Cc"
// cedilla
+ "OoUu"
// double acute
;
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\u00D1\u00F1"
+ "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF"
+ "\u00C5\u00E5"
+ "\u00C7\u00E7"
+ "\u0150\u0151\u0170\u0171"
;

5.15.2 Using String.replaceAll()

// private constructor, can't be instanciated!


private AsciiUtils() { }
// remove accentued from a string and replace with ascii equivalent
public static String convertNonAscii(String s) {
if (s == null) return null;
StringBuilder sb = new StringBuilder();
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
}
}
Thanks to MV Bastos for the "tilde" bug fix
Thanks to L.. Tama for the missing !
Thanks to T. Hague for the missing "double acute";

As a bonus, here a method to convert a given string to uppercase with no accent. This can be
useful in a database field to simplify name searching with accent or not.

public class StringUtils {


private StringUtils() {}
private static final String UPPERCASE_ASCII =
"AEIOU" // grave
+ "AEIOUY" // acute
+ "AEIOUY" // circumflex
+ "AON" // tilde
+ "AEIOUY" // umlaut
+ "A" // ring
+ "C" // cedilla
+ "OU" // double acute
;
private static final String UPPERCASE_UNICODE =
"\u00C0\u00C8\u00CC\u00D2\u00D9"
+ "\u00C1\u00C9\u00CD\u00D3\u00DA\u00DD"
+ "\u00C2\u00CA\u00CE\u00D4\u00DB\u0176"
+ "\u00C3\u00D5\u00D1"
+ "\u00C4\u00CB\u00CF\u00D6\u00DC\u0178"
+ "\u00C5"
+ "\u00C7"
+ "\u0150\u0170"
;

5.15.2 Using String.replaceAll()

public static String toUpperCaseSansAccent(String txt) {


if (txt == null) {
return null;
}
String txtUpper = txt.toUpperCase();
StringBuilder sb = new StringBuilder();
int n = txtUpper.length();
for (int i = 0; i < n; i++) {
char c = txtUpper.charAt(i);
int pos = UPPERCASE_UNICODE.indexOf(c);
if (pos > 1){
sb.append(UPPERCASE_ASCII.charAt(pos));
}
else {
sb.append(c);
}
}
return sb.toString();
}

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


String s =
"The result : ,,,,,,,,,,,,,,,,,,,,,,";
System.out.println(
StringUtils.toUpperCaseSansAccent(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.16 Output accentuated characters to the consoleTag(s):


IO Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0046.html

5.17 Java 1.6 or more


In Java 1.6 you can use System.console() instead of System.out.println() to display accentuated
characters to console.
public class Test2 {
public static void main(String args[]){
String s = "caractres franais : \u00e9"; // Unicode for ""
System.out.println(s);
System.console().writer().println(s);
}
}

anf the output is


5.16 Output accentuated characters to the consoleTag(s): IO Internationalization

C:\temp>java Test
caractres franais :
caractres franais :

5.18 Java 1.5 or less


When starting 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

Another way is to specify in the code the encoding to be used.


import java.io.*;
public class Test {
public static void main(String[] args) {
PrintStream ps = null;
String javaString =
"caractres franais : \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.19 Get the default character set of the JVMTag(s):


IO Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0505.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());

5.18 Java 1.5 or less

}
}

Output example (winXP)


>java Hello
Cp1252
Cp1252
windows1252

See also java encoding table for the encoding sets supported.

5.20 Convert OEM (DOS) file to Ansi (Windows)Tag(s):


IO Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0524.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 =
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();

5.20 Convert OEM (DOS) file to Ansi (Windows)Tag(s): IO Internationalization

r.close();
System.exit(0);
}
}

See also this related HowTo

5.21 Detect nonASCII character in a StringTag(s):


Internationalization String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0536.html
import
import
import
import
import

java.nio.ByteBuffer;
java.nio.CharBuffer;
java.nio.charset.Charset;
java.nio.charset.CharsetDecoder;
java.nio.charset.CharacterCodingException;

public class StringUtils {


public static boolean isPureAscii(String v) {
byte bytearray [] = v.getBytes();
CharsetDecoder d = Charset.forName("USASCII").newDecoder();
try {
CharBuffer r = d.decode(ByteBuffer.wrap(bytearray));
r.toString();
}
catch(CharacterCodingException e) {
return false;
}
return true;
}
public static void main (String args[])
throws Exception {
String test = "Ral";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
/*
* output :
*
Ral isPureAscii() : false
*
Real isPureAscii() : true
*/
}
}

A different (and simpler) approach is to take a given string and check if it's possible to encode it into
ASCII.
5.21 Detect nonASCII character in a StringTag(s): Internationalization String/Number

import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
public class StringUtils {
static CharsetEncoder asciiEncoder =
Charset.forName("USASCII").newEncoder(); // or "ISO88591" for ISO Latin 1
public static boolean isPureAscii(String v) {
return asciiEncoder.canEncode(v);
}
public static void main (String args[])
throws Exception {
String test = "Ral";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
/*
* output :
*
Ral isPureAscii() : false
*
Real isPureAscii() : true
*/
}
}

Another way is to use a regular expression, see this Javascript HowTo for a hint!
To simply strip any nonascii characters form a string
public class Test {
public static void main(String args[]){
String input = "ea";
String output = input.replaceAll("[^\\p{ASCII}]", "");
System.out.println(output);
/*
* output : ea
*/
}
}

See also Unaccent letters.

5.22 Get the month (or day) name (localized)Tag(s): Date and
Time Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0650.html
import java.text.DateFormatSymbols;
import java.util.Locale;

5.22 Get the month (or day) name (localized)Tag(s): Date and Time Internationalization

public class DateUtils {


private DateUtils() { }
public static String getMonthName(int month) {
return getMonthName(month, Locale.getDefault());
}
public static String getMonthName(int month, Locale locale) {
DateFormatSymbols symbols = new DateFormatSymbols(locale);
String[] monthNames = symbols.getMonths();
return monthNames[month 1];
}

public static String getDayName(int day, Locale locale) {


DateFormatSymbols symbols = new DateFormatSymbols(locale);
String[] dayNames = symbols.getWeekdays();
return dayNames[day];
}

public static void main(String[] args) {


System.out.println(DateUtils.getMonthName(1));
System.out.println(DateUtils.getMonthName(1, new Locale("it")));
System.out.println(DateUtils.getDayName(java.util.Calendar.SUNDAY, Locale.getDefault()));
/*
* output :
*
january
*
gennaio
*
sunday
*/
}
}

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

5.22 Get the month (or day) name (localized)Tag(s): Date and Time Internationalization

6 IO
6.1 javaio

6.2 Redirect output(stdout/stderr) to a frameTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0028.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 StringTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0029.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) {

6.3 Redirect printStackTrace() to a StringTag(s): IO

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";
}
}
}

6.4 Redirect to a NULL deviceTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0453.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);

//Oneliner style : subclass OutputStream to override the write method ...


System.setOut(new java.io.PrintStream(
new java.io.OutputStream() {
public void write(int b){}
}
));

You may want to suppress output done with the regular System.out but maintain the ability to write
to the original streams directly when necessary.
// Keep a copy of the original out stream.
PrintStream original = new PrintStream(System.out);
// replace the System.out, here I redirect to NUL (for demonstration)
System.setOut(new PrintStream(new FileOutputStream("NUL:")));
System.out.println("bar"); // no output
// The original stream is still available
original.println("foo"); // output to stdout

See also Get faster console output (System.out.println() replacement).

6.4 Redirect to a NULL deviceTag(s): IO

6.5 Print a text file using the javax.print APITag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaprintatextfilewithjavax.printapi.html
This example will print a given text file using the javax.print API.
With cheap personal printer (at least with mine!), you cannot select many options... more than
one copy and page orientation (portrait or landscape) won't work.
You need to set the "flavor" as AUTOSENSE so the content is sent as "OCTETSTREAM" even
if it's possible, according to the Javadoc, to set the "flavor" as UTF8 or US_ASCII. I believe this is
a limitation of the Windows platform implementation.
You need to send a FORMFEED between each print job to eject the last page.
A special class, PrintJobWatcher, is used to wait for the completion of a print job.
import
import
import
import
import

java.io.ByteArrayInputStream;
java.io.IOException;
java.io.InputStream;
java.io.File;
java.io.FileInputStream;

import
import
import
import
import
import
import

javax.print.Doc;
javax.print.DocFlavor;
javax.print.DocPrintJob;
javax.print.PrintException;
javax.print.PrintService;
javax.print.PrintServiceLookup;
javax.print.SimpleDoc;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;
public class PrintTextFile {
public static void main(String[] args) throws PrintException, IOException {
String defaultPrinter =
PrintServiceLookup.lookupDefaultPrintService().getName();
System.out.println("Default printer: " + defaultPrinter);
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
FileInputStream in = new FileInputStream(new File("c:/temp/foo.txt"));
PrintRequestAttributeSet
pras.add(new Copies(1));

pras = new HashPrintRequestAttributeSet();

DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;


Doc doc = new SimpleDoc(in, flavor, null);
DocPrintJob job = service.createPrintJob();

6.5 Print a text file using the javax.print APITag(s): IO

PrintJobWatcher pjw = new PrintJobWatcher(job);


job.print(doc, pras);
pjw.waitForDone();
in.close();
// send FF to eject the page
InputStream ff = new ByteArrayInputStream("\f".getBytes());
Doc docff = new SimpleDoc(ff, flavor, null);
DocPrintJob jobff = service.createPrintJob();
pjw = new PrintJobWatcher(jobff);
jobff.print(docff, null);
pjw.waitForDone();
}
}
class PrintJobWatcher {
boolean done = false;
PrintJobWatcher(DocPrintJob job) {
job.addPrintJobListener(new PrintJobAdapter() {
public void printJobCanceled(PrintJobEvent pje) {
allDone();
}
public void printJobCompleted(PrintJobEvent pje) {
allDone();
}
public void printJobFailed(PrintJobEvent pje) {
allDone();
}
public void printJobNoMoreEvents(PrintJobEvent pje) {
allDone();
}
void allDone() {
synchronized (PrintJobWatcher.this) {
done = true;
System.out.println("Printing done ...");
PrintJobWatcher.this.notify();
}
}
});
}
public synchronized void waitForDone() {
try {
while (!done) {
wait();
}
} catch (InterruptedException e) {
}
}
}

To print a String, see this HowTo

6.5 Print a text file using the javax.print APITag(s): IO

6.6 Print a String to a printer Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaprintastringusingjavaxprintapi.html
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import
import
import
import
import
import
import

javax.print.Doc;
javax.print.DocFlavor;
javax.print.DocPrintJob;
javax.print.PrintException;
javax.print.PrintService;
javax.print.PrintServiceLookup;
javax.print.SimpleDoc;

import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Copies;
import javax.print.event.PrintJobAdapter;
import javax.print.event.PrintJobEvent;
public class PrintText {
public static void main(String[] args) throws PrintException, IOException {
String defaultPrinter =
PrintServiceLookup.lookupDefaultPrintService().getName();
System.out.println("Default printer: " + defaultPrinter);
PrintService service = PrintServiceLookup.lookupDefaultPrintService();
// prints the famous hello world! plus a form feed
InputStream is = new ByteArrayInputStream("hello world!\f".getBytes("UTF8"));
PrintRequestAttributeSet
pras.add(new Copies(1));

pras = new HashPrintRequestAttributeSet();

DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;


Doc doc = new SimpleDoc(is, flavor, null);
DocPrintJob job = service.createPrintJob();
PrintJobWatcher pjw = new PrintJobWatcher(job);
job.print(doc, pras);
pjw.waitForDone();
is.close();
}
}
class PrintJobWatcher {
boolean done = false;
PrintJobWatcher(DocPrintJob job) {
job.addPrintJobListener(new PrintJobAdapter() {
public void printJobCanceled(PrintJobEvent pje) {
allDone();
}
public void printJobCompleted(PrintJobEvent pje) {
allDone();
}
public void printJobFailed(PrintJobEvent pje) {

6.6 Print a String to a printer Tag(s): IO

allDone();
}
public void printJobNoMoreEvents(PrintJobEvent pje) {
allDone();
}
void allDone() {
synchronized (PrintJobWatcher.this) {
done = true;
System.out.println("Printing done ...");
PrintJobWatcher.this.notify();
}
}
});
}
public synchronized void waitForDone() {
try {
while (!done) {
wait();
}
} catch (InterruptedException e) {
}
}
}

To print a text file, see this HowTo

6.7 Print text to a printer easilyTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0051.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 text to a printer easilyTag(s): IO

6.8 Print without a DialogTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0350.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.9 Initialize and write to a serial portTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0062.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",
};

6.8 Print without a DialogTag(s): IO

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.10 Open or close a CD/DVD driveTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0574.html
Java provides no way to interact with a cd drive.
One easy way on the Windows plateform is to call a VBS script.
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);

6.10 Open or close a CD/DVD driveTag(s): IO

}
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);
CDUtils.close("D:\\");
}
}
NOTE : Windows Media Player version 7 or later is required

6.11 Get the volume labelTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0455.html
This will retrieve the hard disk volume label :
import java.io.*;
import javax.swing.filechooser.*;
public class VolumeLabel {

6.11 Get the volume labelTag(s): IO

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);
}
return name;
}
}

The output
Running from c:\temp
>java VolumeLabel c:
"temp"
>java VolumeLabel c:\
"HARDDISK1"

6.12 Detect the storage device typeTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0635.html
javax.swing.filechooser.FileSystemView provides a way to detect the type of a particular device.
import
import
import
import

java.io.File;
java.util.Arrays;
java.util.List;
javax.swing.filechooser.FileSystemView;

public class Test2 {


public static void main(String args[]){
List <File>files = Arrays.asList(File.listRoots());
for (File f : files) {
String s = FileSystemView.getFileSystemView().getSystemTypeDescription(f);
System.out.println("*" + s);
}

6.12 Detect the storage device typeTag(s): IO

/* output (French WinXP)


*Disquette 3 pouces
*Disque local
*Lecteur CD
*Disque local
*/
}
}

As you can see the output is localized (from the OS).


The following output the name or label of the storage device :
import
import
import
import

java.io.File;
java.util.Arrays;
java.util.List;
javax.swing.filechooser.FileSystemView;

public class Test2 {


public static void main(String args[]){
List <File>files = Arrays.asList(File.listRoots());
for (File f : files) {
String s = FileSystemView.getFileSystemView().getSystemDisplayName(f);
System.out.println("*" + s);
}
/* output (French WinXP)
*
*REGA1 (C:)
*
*My Book (F:)
*/
}
}

6.13 Turn on MQ Debug mode Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaturnonmqdebugmode.html
Websphere MQ exposes many properties to control debugging inforation output. See this
document.
When starting the JRE, set the properties on the command line. For example :
Dcom.ibm.msg.client.commonservices.trace.status=ON
Dcom.ibm.msg.client.commonservices.trace.outputName=C:\myapps\logs\mq.log

will make the MQ client to produce a log with a lot of information.


6.13 Turn on MQ Debug mode Tag(s): IO

Version information in main body of trace


TimeStamp
TID
ObjectId
Class
=============================================================================================
15:04:32.833.00 0001
static c.i.m.c.commonservices.trace.Trace
15:04:32.833.01 0001
static c.i.m.c.commonservices.componentmanager.ComponentManager
15:04:32.833.02 0001 @14a18d
c.i.m.c.commonservices.componentmanager.ComponentManager(Co
...

6.14 Get faster console output (System.out.println()


replacement)Tag(s): IO
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0603.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 linebuffered 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
ASCIIbased then by removing the Unicoderelated activities, the overall execution time will be
better.
Consider this program :
import
import
import
import

java.io.BufferedWriter;
java.io.FileDescriptor;
java.io.FileOutputStream;
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 512bytes buffer and specify the ASCII as
characterencoding to be used.
6.14 Get faster console output (System.out.println() replacement)Tag(s): IO

import
import
import
import

java.io.BufferedWriter;
java.io.FileDescriptor;
java.io.FileOutputStream;
java.io.OutputStreamWriter;

public class Test {


public static void main(String...args) throws Exception {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new
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 Simple input from the keyboardTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0053.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();
}
}
}

6.15 Simple input from the keyboardTag(s): IO

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;
}
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.15 Simple input from the keyboardTag(s): IO

6.16 Output accentuated characters to the consoleTag(s):


IO Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0046.html

6.17 Java 1.6 or more


In Java 1.6 you can use System.console() instead of System.out.println() to display accentuated
characters to console.
public class Test2 {
public static void main(String args[]){
String s = "caractres franais : \u00e9"; // Unicode for ""
System.out.println(s);
System.console().writer().println(s);
}
}

anf the output is


C:\temp>java Test
caractres franais :
caractres franais :

6.18 Java 1.5 or less


When starting 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

Another way is to specify in the code the encoding to be used.


import java.io.*;
public class Test {
public static void main(String[] args) {
PrintStream ps = null;
String javaString =
"caractres franais : \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

6.16 Output accentuated characters to the consoleTag(s): IO Internationalization

6.19 Clear the console and control attributesTag(s): IO Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0047.html
There is no builtin way to really control characterbased application in Java.
To clear the screen, you can use many System.out.println();, that's about it!
for (int i=0; i<25; i++)
System.out.println();

... Or use some JNI functions, see this HowTo.


While it is possible to use the DOS ANSI.SYS driver with Windows 9x and make old JVM use it ...
it won't work with modern Windows installations. Windows NT (or better) CMD.EXE does not
support ANSI escape sequences at all.
Fortunately many Open Source solutions are coming to the rescue and Jansi and JCurses are
two of them.

6.20 Jansi
Jansi is a small java library that allows you to use ANSI escape sequences to format your console
output which works even on Windows.
import org.fusesource.jansi.AnsiConsole;
public class Test {
public static final
public static final
public static final
public static final
public static final
public static final
public static final

String
String
String
String
String
String
String

ANSI_CLS = "\u001b[2J";
ANSI_HOME = "\u001b[H";
ANSI_BOLD = "\u001b[1m";
ANSI_AT55 = "\u001b[10;10H";
ANSI_REVERSEON = "\u001b[7m";
ANSI_NORMAL = "\u001b[0m";
ANSI_WHITEONBLUE = "\u001b[37;44m";

public static void main(String args[]){


AnsiConsole.systemInstall();
AnsiConsole.out.println(ANSI_CLS);
AnsiConsole.out.println
(ANSI_AT55 + ANSI_REVERSEON + "Hello world" + ANSI_NORMAL);
AnsiConsole.out.println
(ANSI_HOME + ANSI_WHITEONBLUE + "Hello world" + ANSI_NORMAL);
AnsiConsole.out.print
(ANSI_BOLD + "Press a key..." + ANSI_NORMAL);
try {System.in.read();}catch(Exception e){}
AnsiConsole.out.println(ANSI_CLS);
AnsiConsole.systemInstall();

6.19 Clear the console and control attributesTag(s): IO Open Source

}
}
NOTE: Check this "old" text file to have an overview of ANSI Escape Sequences.

The above example shows that it's possible to use ANSI codes directly but Jansi provides a neat
mechanism to help building the required ANSI sequence.
import static org.fusesource.jansi.Ansi.*;
import static org.fusesource.jansi.Ansi.Color.*;
...
System.out.println( ansi().eraseScreen().fg(RED).a("Hello").fg.(GREEN).a(" World").reset()

Jansi works on Linux32/64, Windows 32/64 and OS/X.

6.21 JCurses
The Java Curses Library (JCurses) is a library for developing text terminal based applications
using Java programming language. It is implemented as a Windowing toolkit similar to AWT, but
built upon the UNIX "curses" windowing system.
JCurses works on Unix and Windows (32 bit only, on a 64bit OS you need to use JCurses with a
32bit JVM).
This example will display a characterbased window with a label, a textfield and a button (don't
click with you mouse, use the keyboard!).
import
import
import
import

jcurses.system.*;
jcurses.widgets.*;
jcurses.util.*;
jcurses.event.*;

public class Test2 extends Window implements ItemListener, ActionListener,


ValueChangedListener, WindowListener, WidgetsConstants {
static Test2 window = null;
static TextField textfield = null;
static Button button = null;
public Test2(int width, int height) {
super(width, height, true, "JCurses Test");
}
public static void main(String[] args) throws Exception {
window = new Test2(30, 20);
window.init();
}
public void init() {
DefaultLayoutManager mgr = new DefaultLayoutManager();
mgr.bindToContainer(window.getRootPanel());
mgr.addWidget(
new Label("Hello World!",
new CharColor(CharColor.WHITE, CharColor.GREEN)),
0, 0, 20, 10,
WidgetsConstants.ALIGNMENT_CENTER,
WidgetsConstants.ALIGNMENT_CENTER);
textfield = new TextField(10);

6.21 JCurses

mgr.addWidget(textfield, 0, 0, 20, 20,


WidgetsConstants.ALIGNMENT_CENTER,
WidgetsConstants.ALIGNMENT_CENTER);
button = new Button("Quit");
mgr.addWidget(button, 0, 0, 20, 30,
WidgetsConstants.ALIGNMENT_CENTER,
WidgetsConstants.ALIGNMENT_CENTER);
button.setShortCut('q');
button.addListener(this);
window.addListener((WindowListener) this);
window.show();
}
public void actionPerformed(ActionEvent event) {
Widget w = event.getSource();
if (w == button) {
new Message("HowTo", "You are about to quit", "OK").show();
window.close();
}
}
public void stateChanged(ItemEvent e) {

public void valueChanged(ValueChangedEvent e) {

public void windowChanged(WindowEvent event) {


if (event.getType() == WindowEvent.CLOSING) {
event.getSourceWindow().close();
// Toolkit.clearScreen(new CharColor(CharColor.WHITE, CharColor.BLACK));
}
}
}

6.22 Easy keyboard input (JDK1.5)Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0491.html
import java.util.Scanner;
class TestScanner {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
System.out.println(sc.nextLine());
System.out.println("Done");
}
}

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.
6.22 Easy keyboard input (JDK1.5)Tag(s): IO

import java.util.Scanner;
class TestScanner {
public static void main(String args[]) {
// if input is
//
10,12
// then the output is
// 10
// 12
//
// we use a regex as delimiter to combine "," and
// whitespace (in this case the ENTER key)
Scanner sc = new Scanner(System.in).useDelimiter("[,\\s]");
while (sc.hasNextInt()) {
int i = sc.nextInt();
System.out.println(i);
}
System.out.println("Done");
}
}

Scanner can be used with String or Stream. For exemple, the above HowTo can be written like
this :
import java.util.Scanner;
class TestScanner {
public static void main(String args[]) {
String input = "10,12"
Scanner sc = new Scanner(System.in).useDelimiter(",");
while (sc.hasNextInt()) {
int i = sc.nextInt();
System.out.println(i);
}
System.out.println("Done");
}
}

6.23 Force keyboard input in CAPS LOCK onTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0643.html
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Test {
private JFrame myFrame;

6.23 Force keyboard input in CAPS LOCK onTag(s): IO

private JTextField myTextField;


public void doit() {
myFrame = new JFrame();
myFrame.setSize(400, 200);
myFrame.setLocation(100, 100);
myFrame.setLayout(new java.awt.FlowLayout());
myTextField = new JTextField(20);
// Keyboard is CAPSLOCK ON
java.awt.Toolkit.getDefaultToolkit()
.setLockingKeyState(KeyEvent.VK_CAPS_LOCK, true);
myFrame.add(myTextField);
myFrame.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
myTextField.requestFocus();
}
public void windowActivated( WindowEvent e ){
boolean focus = myTextField.requestFocusInWindow();
if(focus){
System.out.println("Focus successful");
}
else{
System.out.println("Focus unsuccessful");
}
}
}
);
myFrame.setVisible(true);
}
public static void main(String args[]) {
new Test().doit();
}
}

NOTE : This technique changes the keyboard state so the effect is also seen outside the Java
program.
See also this related Howto.

6.24 Automatic conversion of System.out output Tag(s): IO

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javaautomaticconversionofSystem.outoutput.html
Convert System.out output to uppercase.
import java.io.PrintStream;
public class Test {
public static void main(String[] args) throws Exception {
System.setOut(new PrintStream(System.out) {
public void println(String s) {

6.24 Automatic conversion of System.out output Tag(s): IO

super.println(s.toUpperCase());
}
});
System.out.println("hello world"); // output :

HELLO WORLD

}
}

Replace the regular output stream of System.out to do useful thing like implementing a Tee
mechanism to output to the console and to file.
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
public class TeeOutputStream extends OutputStream {
private OutputStream os1;
private OutputStream os2;
public TeeOutputStream(OutputStream os1, OutputStream os2) {
this.os1 = os1;
this.os2 = os2;
}
public void write(int i) throws IOException {
os1.write(i);
os2.write(i);
}
public void flush() throws IOException {
os1.flush();
os2.flush();
}
public void close() throws IOException {
os1.close();
os2.close();
}
public static void main(String[] args) throws IOException {
System.out.println("Starting...");
// keep the original
PrintStream originalOutStream = System.out;
System.setOut(
new PrintStream(
new TeeOutputStream(
System.out,
new PrintStream("C:/temp/howto.out"))));
// restore the original
System.out.println("*");
for (int i = 1; i<= 10; i++) {
System.out.println(i);
}
System.out.println("*");
System.setOut(originalOutStream);
System.out.println("Done. Check the log");
}
}

6.24 Automatic conversion of System.out output Tag(s): IO

6.25 Execute an external programTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0014.html
Be sure to read this Javaworld article. It describes the various pitfalls related to the
Runtime.exec() method.

6.26 Using Runtime.exec()


This example will capture the output (from stdio) of an external program.
package com.rgagnon.howto;
import java.io.*;
public class Exec {
public static void main(String args[]) {
try {
String line;
Process p = Runtime.getRuntime().exec("cmd /c dir");
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
while ((line = bri.readLine()) != null) {
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception err) {
err.printStackTrace();
}
}
}

The next example, launch CMD.EXE, grab stdin/stdout and push to stdin command to be
interpreted by the shell.
String line;
OutputStream stdin = null;
InputStream stderr = null;
InputStream stdout = null;
// launch EXE and grab stdin/stdout and stderr
Process process = Runtime.getRuntime ().exec ("/folder/exec.exe");
stdin = process.getOutputStream ();
stderr = process.getErrorStream ();
stdout = process.getInputStream ();

6.25 Execute an external programTag(s): IO

// "write" the parms into stdin


line = "param1" + "\n";
stdin.write(line.getBytes() );
stdin.flush();
line = "param2" + "\n";
stdin.write(line.getBytes() );
stdin.flush();
line = "param3" + "\n";
stdin.write(line.getBytes() );
stdin.flush();
stdin.close();
// clean up if any output in stdout
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();

6.27 Launch a 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

6.27 Launch a Windows CMD (or BAT) file and retrieve the errorlevel or exitcode

test.cmd (set the errorlevel 0 (execution Ok)


@java version

6.28 Launch a Unix script


String[] cmd = {"/bin/sh", "c", "ls > hello"};
Runtime.getRuntime().exec(cmd);

6.29 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")));
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.30 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.
6.28 Launch a Unix script

The following example start a Dialup 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.31 PDF (Windows only)


public class ShowPDF {
public static void main(String[] args) throws Exception {
Process p =
Runtime.getRuntime()
.exec("rundll32 url.dll,FileProtocolHandler c:/pdf/mypdf.pdf");
p.waitFor();
System.out.println("Done.");
}
}

6.32 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.33 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();
}
}

6.31 PDF (Windows only)

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.34 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.35 HTML Help (Windows only)


Runtime.getRuntime().exec("hh.exe myhelpfile.chm");

6.36 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);
}
}

6.34 VBSCRIPT

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.37 Start a Windows application under another account


You use the RUNAS command from the command line to start an application under another
account (not available with XP Home edition). There are many switches that can enhance the
behaviour of RUNAS. Typing "runas /?" from the command prompt gets you all the options.
String commands [] = new String [] {
"CMD.EXE",
"/C",
"RUNAS /profile /savecred /user:"
+ "administrator"
+ " " + "regedit.exe"
};
Runtime.getRuntime().exec(commands);

/SaveCred option allows you to save a password for that account and then reuse it later. For
example, The command runas /savecred /user:administrator regedit.exe prompts
for the password, and then Regedit runs. Next time you use the same command, there is no
password prompt.
One potential problem is that when /SaveCred saves the credentials it saves it for whenever
RUNAS invokes that user account. This can be a huge security risk so be careful using it!
RUNAS capability can be disabled by editing the Registry or by disabling the RUNAS or
Secondary Logon Services. The appropriate registry key is
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer, create a
new DWORD value named HideRunAsVerb and assign it a value of 1 to disable Run as.
RUNAS doesn't work when used from a Windows service.

6.38 Windows : execute something in Program Files


We want to execute the textpad editor located in C:\Program Files\TextPad 4 but without hard
coding the path since it can be different for a localized version of Windows.
We simply extract to environnment variable called %programfiles% and build the complete path
from there.
[JDK1.5]
public class Exec {
static String WIN_PROGRAMFILES = System.getenv("programfiles");
static String FILE_SEPARATOR
= System.getProperty("file.separator");
public static void main(String[] args) throws Exception {
String[] commands =
{"cmd.exe",
"/c",
WIN_PROGRAMFILES
+ FILE_SEPARATOR
+ "textpad 4"

6.37 Start a Windows application under another account

+ FILE_SEPARATOR + "textpad.exe"};
Runtime.getRuntime().exec(commands);
}
}

NOTE : Prior Vista, System folders were localized on disk like C:\Program Files > C:\Archivos de
programa on the Windows with the Spanish localization. Since Vista, System Folders always
exists with the english name BUT when viewed through Explorer, the localized name is shown.
See
http://msmvps.com/blogs/carlosq/archive/2007/02/12/windowsvistajunctionspointsmuiandlocalized

6.39 Launch the application associated with a file


extensionTag(s): IO
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0579.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));
}
}

The possible actions are


BROWSE. launching the userdefault browser to show a specified URI
MAIL. launching the userdefault 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);
}

6.39 Launch the application associated with a file extensionTag(s): IO

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.40 Launch an application from another applicationTag(s):


IO Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0394.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();
}

6.40 Launch an application from another applicationTag(s): IO Language

The above example is used when the class is hardcoded.


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");
}
}

The output :
C:\>java Program1a
Hello from Program1a
Hello from Program2
Hello from Program2
Hello from Program2
Hello from Program2

6.40 Launch an application from another applicationTag(s): IO Language

Hello from Program1a

6.41 Start the default browser from an applicationTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0071.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/java0001.html|JAVA
http://www.rgagnon.com/javadetails/java0002.html|JAVA
http://www.rgagnon.com/javadetails/java0003.html|JAVA
http://www.rgagnon.com/javadetails/java0004.html|JAVA
http://www.rgagnon.com/javadetails/java0005.htmL|JAVA

[StartBrowser.java]

Howto
Howto
Howto
Howto
Howto

import
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
java.net.*;
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) {
System.exit(0);
}
}

6.41 Start the default browser from an applicationTag(s): IO

1
2
3
4
5

);
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)


See http://java.sun.com/javase/6/docs/api/java/awt/Desktop.html

6.41 Start the default browser from an applicationTag(s): IO

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.42 Execute a Windows Shortcut (.lnk)Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0571.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.43 Create a file association with a Java programTag(s):


IO Misc Prog HowTo
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0592.html

6.42 Execute a Windows Shortcut (.lnk)Tag(s): IO

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{
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 doubleclick 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%

6.42 Execute a Windows Shortcut (.lnk)Tag(s): IO

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.44 Capture the output from a VBSTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0576.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
import
import
import

java.io.BufferedReader;
java.io.File;
java.io.FileWriter;
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){

6.44 Capture the output from a VBSTag(s): IO

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\\");
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.45 Get a return code from a VBSTag(s): IO Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0575.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";

6.45 Get a return code from a VBSTag(s): IO Environment

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 ");
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.46 Execute a CMD file stored in a JARTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0600.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 Howto, 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{

6.46 Execute a CMD file stored in a JARTag(s): IO

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
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.46 Execute a CMD file stored in a JARTag(s): IO

6.47 Open the default file explorerTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaopendefaultosfileexplorer.html
JDK1.6
Open the default file explorer.
import java.io.File;
import java.io.IOException;
import java.awt.Desktop;
public class Test {
public static void main(String s[]) {
Desktop desktop = null;
// on Windows, retrieve the path of the "Program Files" folder
File file = new File(System.getenv("programfiles"));
if (Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
}
try {
desktop.open(file);
}
catch (IOException e){ }
}
}

6.48 Read the content of a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0052.html

6.49 From a Java application


This following example is for an application.
On the command line, give the filename to be displayed, ex: java.exe Cat c:/temp/text.txt
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);
}

6.47 Open the default file explorerTag(s): IO

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

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();
}

JDK1.5 provides the java.util.Scanner class which can be used to quickly read a file.
The delimeter "\Z" represents the endoffile marker.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class QuickFileRead {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner =
new Scanner(new File("c:/temp/text.txt")).useDelimiter("\\Z");
String contents = scanner.next();
System.out.println(contents);
scanner.close();
}
}

6.50 From a Java applet


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 {

6.50 From a Java applet

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
import
import
import

java.applet.*;
java.awt.*;
java.net.*;
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();
}
}
}

[dataforchoice.txt]
item
item
item
item
item
ITEM

1
2
3
4
5
6

Try it here.

See this HowTo to read a File stored in a JAR.


6.50 From a Java applet

6.51 Read a text file from a jarTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0077.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();
}
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());
}
}
}

6.51 Read a text file from a jarTag(s): IO

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
datafile1
datafile1
datafile1
datafile1

line
line
line
line
line

1
2
3
4
5

[/test/datafile2.txt]
datafile2
datafile2
datafile2
datafile2
datafile2

line
line
line
line
line

1
2
3
4
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 :


datafile1
datafile1
datafile1
datafile1
datafile1
datafile2
datafile2
datafile2
datafile2
datafile2

line
line
line
line
line
line
line
line
line
line

1
2
3
4
5
1
2
3
4
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) {

6.51 Read a text file from a jarTag(s): IO

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.52 Read a file from the internet Tag(s): Networking IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javareadafilefromtheinternet.html
import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
public class NetUtils {
private NetUtils() {}
public static String getTextContent(URL url) throws IOException {
Scanner s = new Scanner(url.openStream()).useDelimiter("\\Z");;
String content = s.next();
return content;
}
public static void main(String[] args) throws IOException {
URL url = new URL("http://www.rgagnon.com/varia/copyrightnotice.txt");
System.out.println(NetUtils.getTextContent(url));
}
}

6.52 Read a file from the internet Tag(s): Networking IO

6.53 Extract a file from a JarTag(s): IO Environment


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0429.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 autorun Jar if you want to try it.


To create an autorun JAR, first create a manifest.mft

6.53 Extract a file from a JarTag(s): IO Environment

ManifestVersion: 1.0
Classpath: .\mydb.jar
MainClass: 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
String home = getClass().getProtectionDomain()
.getCodeSource().getLocation()
.getPath().replaceAll("%20", " ");

6.54 Read a data file with floatsTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0078.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;

6.54 Read a data file with floatsTag(s): IO

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();
}
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.55 Write to the end of a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0054.html
[JDK1.0.2]
import java.io.*;

6.55 Write to the end of a fileTag(s): 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());
}
}
}
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.56 Write "real" ascii fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0058.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 ISOLatin 1(or Codepage 850) to represent french
characters like or .

6.56 Write "real" ascii fileTag(s): IO

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 (MSDOS Latin1)
FileOutputStream fos = new FileOutputStream("out.dat");
Writer w =
new BufferedWriter(new OutputStreamWriter(fos, "Cp850"));
w.write(JavaString);
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.57 Copy a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0064.html
[Java 7]
import static java.nio.file.StandardCopyOption.*;
import java.io.IOException;

6.57 Copy a fileTag(s): IO

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Test {
public static void main(String[] args) throws IOException {
Path source = Paths.get("c:/temp/0multipage.tif");
Path target = Paths.get("c:/temp/1multipage.tif");
Files.copy(source, target, REPLACE_EXISTING); // Files.move(...) is also possible
// see http://docs.oracle.com/javase/tutorial/essential/io/copy.html
}
}

[JDK1.4 using the java.nio package]


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^311 bytes. it throws an exception of "java.io.IOException: The parameter is
incorrect"
In solaris8 , Bytes transfered to Target channel are 2^311 even if the source channel file is greater than 2^311
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
6.57 Copy a fileTag(s): IO

...
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;
while (position < size) {
position +=
inChannel.transferTo(position, maxCount, outChannel);
}
...

[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]));
}
}

6.58 Use a "log file"Tag(s): IO


Current version of this HowTo :
6.58 Use a "log file"Tag(s): IO

http://www.rgagnon.com/javadetails/../javadetails/java0063.html
/**
* Utilities log
*/
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
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 = SimpleLog.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) {
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";
}

6.58 Use a "log file"Tag(s): IO

hh:mm:ss ");

}
}

and then to use it


SimpleLog.write("i am here");

See also this HowTo and this one

6.59 Delete files with a certain extensionTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0072.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);
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.59 Delete files with a certain extensionTag(s): IO

}
}
}

6.60 Insert a line in a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0073.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));
// output
FileOutputStream fos = new FileOutputStream(outFile);
PrintWriter out = new PrintWriter(fos);

6.60 Insert a line in a fileTag(s): IO

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.61 Read a file into a variable in one shotTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0074.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.62 Serialize an object to a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0075.html
6.61 Read a file into a variable in one shotTag(s): IO

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
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;

6.61 Read a file into a variable in one shotTag(s): IO

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());
}

6.63 Redirect stdout to a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0061.html
[JDK1.1] application only
System.setOut(
new PrintStream(
new BufferedOutputStream(
new FileOutputStream("OUTPUT.DAT"))));
You may want to look at this Howto to redirect exception output to a Frame.

6.64 Get the "last modified" date from a fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0068.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);

6.63 Redirect stdout to a fileTag(s): IO

if (f1.lastModified() < f2.lastModified())


System.out.println((s1 + " IS OLDER THAN " + S2);

To display the value of lastModified(), you need to create a Date object and then use
SimpleDateFormat to get the String representation.
String

lasmod = new SimpleDateFormat("yyyyMMdd").format(new Date(lastmodified));

6.65 Check if a file existsTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0070.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.66 Detect file modificationTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0490.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() {

6.65 Check if a file existsTag(s): IO

long timeStamp = file.lastModified();


if( this.timeStamp != timeStamp ) {
this.timeStamp = timeStamp;
onChange(file);
}
}
protected abstract void onChange( File file );
}
import java.util.*;
import java.io.*;
public 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);

6.65 Check if a file existsTag(s): IO

// 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()){
// 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 );
}

import java.io.*;
public 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));
}
}

The example watches the c:/temp folder for any activities on any *.txt files.
import java.util.*;
import java.io.*;
public class DirWatcherTest {
public static void main(String args[]) {

6.65 Check if a file existsTag(s): IO

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, this one and finally this one too.

6.67 File/directory polling to detect changeTag(s): IO Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0617.html

6.68 jpoller (directory poller)


http://jpoller.sourceforge.net/
A general purpose Java component to enable polling on directories and aysnchronously notify
client code of incoming files. It's instrumented via JMX and controllable (also) via a JMX agent,
like JBoss' JMX console.

6.69 JNotify
http://jnotify.sourceforge.net/
JNotify is a java library that allow java application to listen to file system events. JNotify works on
both Windows (Windows 2000, XP, Vista) and Linux with INotify support (Kernel 2.6.14 and
above).

6.70 Java Native Access (JNA)


https://jna.dev.java.net/
The goal of the JNA project is to let you access native code from Java while avoiding C and the
Java Native Interface.
One example provides notification of file system changes using the mechanism provided by the
OS. FileMonitor.java
6.67 File/directory polling to detect changeTag(s): IO Open Source

Javaworld article about JNA

6.71 Call native methods in a DLL from Java (NativeCall)

http://johannburkard.de/blog/programming/java/CallnativemethodsinaDLLfromJavawithoutJNI.
In this blog entry, the package NativeCall is used to call the Windows API to get notification about
modification in given folder.

6.72 Java 7
Java 7 provides a mechanism to get notificaton on file change without polling (JSR 203).
http://blogs.sun.com/thejavatutorials/entry/watching_a_directory_for_changes

6.73 The simple (and naive!) approach


Detect file modification
Using Threads and file lookup at regular interval.

6.74 Get the current directoryTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0076.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.71 Call native methods in a DLL from Java (NativeCall)

6.75 Get the "root" of an applicationTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0581.html
By root, we mean the starting directory.
import
import
import
import
import

java.io.File;
java.io.IOException;
java.net.URI;
java.net.URISyntaxException;
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


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.76 Get the content of a directory with a FilterTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0055.html
First you create a class that implements java.io.FilenameFilter and then code the accept()
method. You 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;

6.75 Get the "root" of an applicationTag(s): IO

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>
return;
}

ex. java Filter java");

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
import
import
import
import

java.io.File;
java.io.FilenameFilter;
java.util.Arrays;
java.util.Iterator;
java.util.TreeSet;

/**
* <CODE>
* GenericFileFilter xml = new GenericFileFilter ("xml");
* // GenericFileFilter xmlandpdf = new GenericFileFilter (new String [] { "xml", "pdf" });
* File dir = new File (".");
* String[] strs = dir.list(xml);
* for (int i = 0; i < strs.length; i++) {
* // strs[i]
* }
* </CODE>
*/
public class GenericFileFilter implements FilenameFilter {
private TreeSet<String> exts = new TreeSet<String>() ;
public GenericFileFilter(String ext) {
exts.add("." + ext.toLowerCase().trim());
}

public GenericFileFilter(String[] extensions) {


Iterator<String> extList = Arrays.asList(extensions).iterator();
while (extList.hasNext()) {
exts.add("." + extList.next().toLowerCase().trim());
}
exts.remove("");

6.75 Get the "root" of an applicationTag(s): IO

}
public boolean accept(File dir, String name) {
final Iterator<String> extList = exts.iterator();
while (extList.hasNext()) {
if (name.toLowerCase().endsWith(extList.next())) {
return true;
}
}
return false;
}
}

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]);
}
}
}

If your need is simple then you don't need a complete class to implement a FilenameFilter. You
can declare an anonymous class with this simple onleliner.
import java.io.File;
import java.io.FilenameFilter;
...
files = dir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".txt");
}
}
);

To retrieve only directories, a simple filter can be made.


import java.io.File;
import java.io.FileFilter;
public class Test {
public static void main(String[] args) throws Exception {

6.75 Get the "root" of an applicationTag(s): IO

File [] foldersToBeChecked =
new File("J:\\").listFiles
(new FileFilter() {
public boolean accept(File pathname) {
return (pathname.isDirectory());
}
}
);
for(File f : foldersToBeChecked) {
System.out.println(f);
}
}
}

6.77 Get the content of a directory with subdirectoriesTag(s):


IO
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0056.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]));
}

6.77 Get the content of a directory with subdirectoriesTag(s): IO

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\httrack3.23.exe, c:\
zip\mass20.zip, c:\zip\mp3,c:\zip\mp3\BonkEnc1.0beta1.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\htmldoc1.8.23winfree.exe, c:\zip\ok\j2sdk1_4_1_02windowsi58
6.exe, c:\zip\ok\jdk141hh.zip, c:\zip\ok\jsref13.zip, c:\zip\ok\T
weakUiPowertoySetup.exe, c:\zip\quickmail2_1.zip, c:\zip\RealOneP
layerV2GOLD.exe, c:\zip\RESTorefile2514.EXE,c:\zip\Shockwave_Insta
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_14_final.zip, c:\zip\xpAntiSpy.zip]
*/
}
}

6.78 Get directory content faster with many files Tag(s): IO

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javagetdirectorycontentfasterwithmanyfiles.htm
With Java 7, there is a new possibility to handle directory with a large amount of file (say more
than 10 000 files). With the previous JDK versions, File.listFiles() returns a File array. The
performance is not so good since you have to wait for the array to be completed before starting
the processing. This is especially bad if you need to work only on subset of the content. With Java
7, java.nio offers an alternative with a huge gain in performance.
In this HowTo, we want to process only the 10 first files of directory with more than 60 000 files.
The classical approach gets an array with all the files and then loop to process the first 10 files.
With the java.nio approach, a stream is opened and the files are processed as needed, the
stream is closed after the 10th file.
package misc;
import
import
import
import
import

java.io.File;
java.io.IOException;
java.nio.file.DirectoryStream;
java.nio.file.FileSystems;
java.nio.file.Files;

6.78 Get directory content faster with many files Tag(s): IO

import java.nio.file.Path;
public class TestDir {
public static void main( String[] args ) throws IOException {
int maxFiles = 10;
System.out.println( "TEST BIG DIR" );
nioRun( "\\\\server.local\\files\\20130220", maxFiles );
ioRun( "\\\\server.local\\files\\20130220", maxFiles );
}
// the classical way
private static void ioRun( String filePath, int maxFiles )
throws IOException {
int i = 1;
System.out.println( "IO run" );
long start = System.currentTimeMillis();
File folder = new File( filePath );
File[] listOfFiles = folder.listFiles();
// System.out.println("Total : " + listOfFiles.length);
for (File file : listOfFiles) {
System.out.println( "" + i + ": " + file.getName() );
if (++i > maxFiles) break;
}
long stop = System.currentTimeMillis();
System.out.println( "Elapsed: " + (stop start) + " ms" );
}
// the new way
private static void nioRun( String filePath, int maxFiles )
throws IOException {
int i = 1;
System.out.println( "NIO run" );
long start = System.currentTimeMillis();
Path dir = FileSystems.getDefault().getPath( filePath );
DirectoryStream stream = Files.newDirectoryStream( dir );
for (Path path : stream) {
System.out.println( "" + i + ": " + path.getFileName() );
if (++i > maxFiles) break;
}
stream.close();
long stop = System.currentTimeMillis();
System.out.println( "Elapsed: " + (stop start) + " ms" );
}
}

the result is :
TEST BIG DIR
NIO run
1: 1355970441334_000000_AA000000.PDF
2: 1355970441334_000000_AA000000.props
3: 1355970441335_530025_AA000000.PDF
4: 1355970441335_530025_AA000000.props
5: 1355970441336_832300_AA000000.PDF
6: 1355970441336_832300_AA000000.props
7: 1355970441337_877400_AA000000.PDF
8: 1355970441337_877400_AA000000.props
9: 1355970441338_879900_AA000000.PDF
10: 1355970441338_879900_AA000000.props
Elapsed: 158 ms
IO run
1: 1355970441334_000000_AA000000.PDF

6.78 Get directory content faster with many files Tag(s): IO

2: 1355970441334_000000_AA000000.props
3: 1355970441335_530025_AA000000.PDF
4: 1355970441335_530025_AA000000.props
5: 1355970441336_832300_AA000000.PDF
6: 1355970441336_832300_AA000000.props
7: 1355970441337_877400_AA000000.PDF
8: 1355970441337_877400_AA000000.props
9: 1355970441338_879900_AA000000.PDF
10: 1355970441338_879900_AA000000.props
Elapsed: 73455 ms

6.79 Make a directoryTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0057.html
For application only, not Applet!
File td = new File("NewDirName");
td.mkdir();

6.80 Create a fixedlength fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0461.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();
}
}

6.79 Make a directoryTag(s): IO

6.81 Delete a nonempty directoryTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0483.html
Use the following recursive method.
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() );
}
}

6.82 Create a temporary fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0484.html
import java.io.File;
...
File temp = File.createTempFile("real",".howto");
temp.deleteOnExit();

Creates an empty file in the default temporaryfile directory, using the given prefix ("real") and
suffix (".howto"). Plus, the temporary file will be deleted when the virtual machine terminates.
6.81 Delete a nonempty directoryTag(s): IO

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 internallygenerated 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 :
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
Win XP
Solaris
Linux

>
>
>
>

C:\TEMP\
C:\TEMP
/var/tmp/
/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");

6.83 Get the default character set of the JVMTag(s):


IO Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0505.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

6.83 Get the default character set of the JVMTag(s): IO Internationalization

System.out.println(java.nio.charset.Charset.defaultCharset().name());
}
}

Output example (winXP)


>java Hello
Cp1252
Cp1252
windows1252

See also java encoding table for the encoding sets supported.

6.84 Parse a pathnameTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0514.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()));
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;
}
}

6.84 Parse a pathnameTag(s): IO

6.85 Handle CSV fileTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0591.html

6.86 com.Ostermiller.util CSV Utils


CSVPrinter/CSVParser/ExcelCSVPrinter/ExcelCSVParser
http://ostermiller.org/utils/CSV.html

6.87 opencsv
A simple csv parser library for Java
http://opencsv.sourceforge.net/

6.88 ServingXML
Framework for flat/XML data transformations. Supported transformations : flatXML, XMLflat,
flatflat, and XMLXML
http://servingxml.sourceforge.net/

6.89 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.90 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.91 CSVFile
A simple set of Java classes used to handle CSV
http://sourceforge.net/projects/csvfile

6.92 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.85 Handle CSV fileTag(s): IO Open Source

6.93 CSVJDBC
CsvJdbc is a simple readonly JDBC driver that uses Comma Separated Value (CSV) files as
database tables.
http://csvjdbc.sourceforge.net/

6.94 FFP
FFP Flat file parsing library, is used to parse text files where lines can be interpreted according
to positional patterns. The library can handle both multiline formats and files containing lines
have different known formats ("mixed format" files).
http://jffp.sourceforge.net/

6.95 Convert OEM (DOS) file to Ansi (Windows)Tag(s):


IO Internationalization
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0524.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 =
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) {

6.93 CSVJDBC

w.write(oemString);
w.flush();
}
w.close();
r.close();
System.exit(0);
}
}

See also this related HowTo

6.96 Close a stream in a try/catch blockTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0539.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;
}
private static void close( InputStream is ) {
if ( is != null ) {
try {
is.close();
}

6.96 Close a stream in a try/catch blockTag(s): IO

catch ( IOException ioe ) {


ioe.printStackTrace();
}
}
}

6.97 Rename a file extensionTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0541.html
The first version
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;
}

Comments from R.Millington (thanks to him!)


This code very very seriously flawed (the first version ed.).
The toLowerCase() can cause this to fail on OS that have case sensitive file names. It
should be removed.
The replaceAll() call is flawed since
the '.' in the pattern is not taken literally but is interpreted as any character.
the regex has no endofline anchor so if the extracted extension occurs more
than once in the filename then all occurrences will be changed.
if the extracted extension contains any regex meta characters then they will be
interpreted as part of the regex and the replaceAll() will probably fail. This can
even cause an exception.

6.97 Rename a file extensionTag(s): IO

If the replacement extension contains any of the replacement meta characters then
at best one will get the wrong extension and it can cause an exception.
This is fixed by changing the replaceAll() line to
target = source.replaceFirst(Pattern.quote("." +
currentExtension) + "$", Matcher.quoteReplacement("." + newExtension));
A revised version
import java.io.File;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FileUtils {
public static boolean renameFileExtension
(String source, String newExtension)
{
String target;
String currentExtension = getFileExtension(source);
if (currentExtension.equals("")){
target = source + "." + newExtension;
}
else {
target = source.replaceFirst(Pattern.quote("." +
currentExtension) + "$", Matcher.quoteReplacement("." + 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);
}
return ext;
}
public static void main(String args[]) throws Exception {
System.out.println(
FileUtils.renameFileExtension("C:/temp/capture.pdf", "pdfa")
);
}
}

To simply remove an extension, see this HowTo

6.97 Rename a file extensionTag(s): IO

6.98 Remove file extension Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaremovefileextension.html
public static String removeExtension(String fileName) {
int extPos = fileName.lastIndexOf(".");
if(extPos == 1) {
return fileName;
}
else {
return fileName.substring(0, extPos);
}
}

To rename an extension see this HowTo.

6.99 Remove HTML tags from a file to extract only the


TEXTTag(s): IO String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0424.html

6.100 Using regular expression


A special regular expression is used to strip out anything between a < and > .
import java.io.*;
public class Html2TextWithRegExp {
private Html2TextWithRegExp() {}
public static void main (String[] args) throws Exception{
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader("javanew.html"));
String line;
while ( (line=br.readLine()) != null) {
sb.append(line);
// or
// sb.append(line).append(System.getProperty("line.separator"));
}
String nohtml = sb.toString().replaceAll("\\<.*?>","");
System.out.println(nohtml);
}
}

However if any Javascript is present, the script will be seen as text. Also you may need to add
some logic during the reading to take into account only what is inside the <BODY> tag.

6.98 Remove file extension Tag(s): IO

6.101 Using javax.swing.text.html.HTMLEditorKit


In most cases, the HTMLEditorKit is used with a JEditorPane text component but it can be also
used directly to extract text from an HTML page.
import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.util.List;
java.util.ArrayList;

import
import
import
import

javax.swing.text.html.parser.ParserDelegator;
javax.swing.text.html.HTMLEditorKit.ParserCallback;
javax.swing.text.html.HTML.Tag;
javax.swing.text.MutableAttributeSet;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String> extractText(Reader reader) throws IOException {
final ArrayList<String> list = new ArrayList<String>();
ParserDelegator parserDelegator = new ParserDelegator();
ParserCallback parserCallback = new ParserCallback() {
public void handleText(final char[] data, final int pos) {
list.add(new String(data));
}
public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos) { }
public void handleEndTag(Tag t, final int pos) { }
public void handleSimpleTag(Tag t, MutableAttributeSet a, final int pos) { }
public void handleComment(final char[] data, final int pos) { }
public void handleError(final java.lang.String errMsg, final int pos) { }
};
parserDelegator.parse(reader, parserCallback, true);
return list;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader("javanew.html");
List<String> lines = HTMLUtils.extractText(reader);
for (String line : lines) {
System.out.println(line);
}
}
}

Note that the HTMLEditorKit can be easily confused if the HTML to be parsed is not wellformed.

6.102 Using an HTML parser


This is maybe the best solution (if the choosen parser is good !).
There are many parsers available on the net. In this HowTo, I will use the OpenSource package
Jsoup.
Jsoup is entirely self contained and has no dependencies which is a good thing.
import java.io.IOException;
import java.io.FileReader;

6.101 Using javax.swing.text.html.HTMLEditorKit

import java.io.Reader;
import java.io.BufferedReader;
import org.jsoup.Jsoup;
public class HTMLUtils {
private HTMLUtils() {}
public static String extractText(Reader reader) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(reader);
String line;
while ( (line=br.readLine()) != null) {
sb.append(line);
}
String textOnly = Jsoup.parse(sb.toString()).text();
return textOnly;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader
("C:/RealHowTo/topics/javalanguage.html");
System.out.println(HTMLUtils.extractText(reader));
}
}

6.103 Using Apache Tika


Apache Tika
import java.io.FileInputStream;
import java.io.InputStream;
import
import
import
import
import
import

org.apache.tika.metadata.Metadata;
org.apache.tika.parser.AutoDetectParser;
org.apache.tika.parser.ParseContext;
org.apache.tika.parser.Parser;
org.apache.tika.sax.BodyContentHandler;
org.xml.sax.ContentHandler;

public class ParseHTMLWithTika {


public static void main(String args[]) throws Exception {
InputStream is = null;
try {
is = new FileInputStream("C:/Temp/javax.html");
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
Parser parser = new AutoDetectParser();
parser.parse(is, contenthandler, metadata, new ParseContext());
System.out.println(contenthandler.toString());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (is != null) is.close();
}
}
}

6.103 Using Apache Tika

See Extract text from a PDF using Apache Tika, Get Mime Type from a file.
See also Extract links from an HTML page

6.104 Get the Mime Type from a FileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0487.html

6.104.1 Using Java 7


Files.html#probeContentType
import
import
import
import

java.io.IOException;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;

public class Test {


public static void main(String[] args) throws IOException {
Path source = Paths.get("c:/temp/0multipage.tif");
System.out.println(Files.probeContentType(source));
// output : image/tiff
}
}

The default implementation is OSspecific and not very complete. It's possible to register a better
detector, like for example Apache Tika, see Transparently improve Java 7 mimetype recognition
with Apache Tika.

6.104.2 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.104 Get the Mime Type from a FileTag(s): IO

The builtin mimetype 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 METAINF/mime.types.
5. The file or resource named METAINF/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.104.3 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 mimetype is defined in the file [jre_home]\lib\contenttypes.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
}
}

A note from R. Lovelock :


I was trying to find the best way of getting the mime type of a file
and found your sight very useful. However I have now found a way of
getting the mime type using URLConnection that isn't as slow as the
way you describe.
import java.net.FileNameMap;
import java.net.URLConnection;
public class FileUtils {

6.104.3 Using java.net.URL

public static String getMimeType(String fileUrl)


throws java.io.IOException
{
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String type = fileNameMap.getContentTypeFor(fileUrl);
return type;
}
public static void main(String args[]) throws Exception {
System.out.println(FileUtils.getMimeType("file://c:/temp/test.TXT"));
// output : text/plain
}
}

6.104.4 Using Apache Tika


Tika is subproject of Lucene, a search engine. It is a toolkit for detecting and extracting
metadata and structured text content from various documents using existing parser libraries.
This package is very uptodate regarding the filetypes supported, Office 2007 formats are
supported (docs/pptx/xlsx/etc...).
Apache Tika
Tika has a lot of dependencies ... almost 20 jars ! But it can do a lot more than detecting filetype.
For example, you can parse a PDF or DOC to extract the text and the metadata very easily.
import java.io.File;
import java.io.FileInputStream;
import
import
import
import
import

org.apache.tika.metadata.Metadata;
org.apache.tika.parser.AutoDetectParser;
org.apache.tika.parser.Parser;
org.apache.tika.sax.BodyContentHandler;
org.xml.sax.ContentHandler;

public class Main {


public static void main(String args[]) throws Exception {
FileInputStream is = null;
try {
File f = new File("C:/Temp/mime/test.docx");
is = new FileInputStream(f);
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
metadata.set(Metadata.RESOURCE_NAME_KEY, f.getName());
Parser parser = new AutoDetectParser();
// OOXMLParser parser = new OOXMLParser();
parser.parse(is, contenthandler, metadata);
System.out.println("Mime: " + metadata.get(Metadata.CONTENT_TYPE));
System.out.println("Title: " + metadata.get(Metadata.TITLE));
System.out.println("Author: " + metadata.get(Metadata.AUTHOR));
System.out.println("content: " + contenthandler.toString());
}
catch (Exception e) {
e.printStackTrace();
}

6.104.4 Using Apache Tika

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

You can download here a ZIP containing the required jars if you want to check it out.

6.104.5 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() ;
// 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 JeanMarc Autexier and sygsix for the tip!

6.104.6 Using mimeutil


Another tool is mimeutil. This tool can detect using the file extension or the magic header
technique.
import eu.medsea.mimeutil.MimeUtil;
public class Main {
public static void main(String[] args) {
MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
File f = new File ("c:/temp/mime/test.doc");
Collection<?> mimeTypes = MimeUtil.getMimeTypes(f);
System.out.println(mimeTypes);
// output : application/msword
}
}

The nice thing about mimeutil is that it is very lightweight. Only 1 dependency with slf4j

6.104.7 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.
6.104.5 Using JMimeMagic

http://droid.sourceforge.net/wiki/index.php/Introduction

6.104.8 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
Fulltext 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.105 Sort a directory listing (based on the last modified


timestamp)Tag(s): IO
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0606.html
This HowTo sorts a directory listing in ascending or descending order (based on the last modified
timestamp).
import
import
import
import

java.io.*;
java.util.Arrays;
java.util.Comparator;
java.util.Date;

public class FileUtils{


public static void main(String args[]) throws Exception {
File files[] = FileUtils.dirListByAscendingDate
(new File("C:/Applications/folder"));
for (File file : files) {
System.out.println(file.getName() + " "
+ new Date(file.lastModified()));
}
System.out.println("*********");
files = FileUtils.dirListByDescendingDate
(new File("C:/Applications/folder"));
for (File file : files) {
System.out.println(file.getName() + " "
+ new Date(file.lastModified()));
}

6.104.8 Aperture framework

}
@SuppressWarnings("unchecked")
public static File[] dirListByAscendingDate(File folder) {
if (!folder.isDirectory()) {
return null;
}
File files[] = folder.listFiles();
Arrays.sort( files, new Comparator()
{
public int compare(final Object o1, final Object o2) {
return new Long(((File)o1).lastModified()).compareTo
(new Long(((File) o2).lastModified()));
}
});
return files;
}
@SuppressWarnings("unchecked")
public static File[] dirListByDescendingDate(File folder) {
if (!folder.isDirectory()) {
return null;
}
File files[] = folder.listFiles();
Arrays.sort( files, new Comparator()
{
public int compare(final Object o1, final Object o2) {
return new Long(((File)o2).lastModified()).compareTo
(new Long(((File) o1).lastModified()));
}
});
return files;
}
}

Take a look at this HowTo to filter by a date interval.


Take a look at this HowTo to sort the filenames based on the extension.

6.106 Sort files by the extensionTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0641.html
import
import
import
import
import

java.io.*;
java.util.Arrays;
java.util.ArrayList;
java.util.List;
java.util.Comparator;

public class FileUtils{


/**

6.106 Sort files by the extensionTag(s): IO

* returns a folder content sorted by extension


* caseinsensitive ,ascending order
* subfolders are not included
* @param folder folder name
* @return
* @throws IOException if not a folder or not found
*/
@SuppressWarnings("unchecked")
public static File[] dirListByExtension(File folder) throws IOException {
if (!folder.isDirectory() || !folder.exists()) {
throw new IOException( folder.getName() + " : Not a folder or not exist");
}
File files[] = FileUtils.list(folder, false); // don't include subfolder
Arrays.sort(files, new Comparator() {
public int compare(final Object o1, final Object o2) {
String s1 = ((File) o1).getName().toLowerCase();
String s2 = ((File) o2).getName().toLowerCase();
final int s1Dot = s1.lastIndexOf('.');
final int s2Dot = s2.lastIndexOf('.');
//
if ((s1Dot == 1) == (s2Dot == 1)) { // both or neither
s1 = s1.substring(s1Dot + 1);
s2 = s2.substring(s2Dot + 1);
return s1.compareTo(s2);
} else if (s1Dot == 1) { // only s2 has an extension, so s1 goes first
return 1;
} else { // only s1 has an extension, so s1 goes second
return 1;
}
}
});
return files;
}
/**
* returns the content of a folder with subfolders included or not
* @param folder
folder name
* @param includeSubFolder true/false
* @return array of files
*/
public static File[] list(File folder, boolean includeSubFolder) {
if (!folder.isDirectory()) {
return null;
}
File files[] = folder.listFiles();
List<File> list = new ArrayList<File>();
for (File file : files) {
if (file.isDirectory()) {
if (includeSubFolder) {
list.add(file);
}
}
else {
list.add(file);
}
}
if (list.isEmpty()) {
return null;
}
return list.toArray(new File[]{});
}
/*

6.106 Sort files by the extensionTag(s): IO

* TEST
*/
public static void main(String args[]) throws Exception {
File files[] = FileUtils.dirListByExtension(new File("C:/temp"));
for (File file : files) {
System.out.println(file.getName());
}
// to reverse
//
List<File> temp = Arrays.asList(files);
//
java.util.Collections.reverse(temp);
//
files = temp.toArray(new File[]{});
//
for (File file : files) {
///
System.out.println(file.getName());
//
}
}
}

Take a look at this HowTo to filter by a date interval.


Take a look at this HowTo to sort the filenames in ascending/descending order (based on the last
modified timestamp).

6.107 Filter a directory listing by dateTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0607.html
This HowTo filters a directory listing based on a date interval.
import java.io.*;
import java.text.*;
import java.util.*;
public class FileFilterDateIntervalUtils implements FilenameFilter {
String dateStart;
String dateEnd;
SimpleDateFormat sdf;
public FileFilterDateIntervalUtils(String dateStart, String dateEnd) {
this.dateStart = dateStart;
this.dateEnd = dateEnd;
sdf = new SimpleDateFormat("yyyyMMdd");
}
public boolean accept(File dir, String name) {
Date d = new Date(new File(dir, name).lastModified());
String current = sdf.format(d);
return ((dateStart.compareTo(current) < 0
&& (dateEnd.compareTo(current) >= 0)));
}
}

6.107 Filter a directory listing by dateTag(s): IO

Then
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
FileFilterDateIntervalUtils filter =
new FileFilterDateIntervalUtils("20040101", "20041231");
File folder = new File("C:/temp");
File files[] = folder.listFiles(filter);
for (File f : files) {
System.out.println(f.getName() + " "
+ sdf.format(new Date(f.lastModified())));
}
}
}

Take a look at this HowTo to sort the filenames in ascending/descending order.


Take a look at this HowTo to sort the filenames based on the extension.

6.108 Convert wildcard to a regex expressionTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0515.html
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

6.108 Convert wildcard to a regex expressionTag(s): IO

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 regexpcharacters
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());
}
}

6.109 Shorten a long pathTag(s): IO String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0661.html
It can be useful to have a short version of a long path only for display purpose.
I propose 2 versions to shorten a given path depending of your need.
The first version makes a path shorter according to a limit. If the limit is 4, the returned path will
contain 4 parts (directories) then ellipse and finally the filename.
ex :
6.109 Shorten a long pathTag(s): IO String/Number

C:\1\2\3\4\5\test.txt == C:\1\2\3\4\...\test.txt
\\server\p1\p2\p3\p4\p5\p6 == \\server\p1\p2\p3\p4\...\p6
http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html == http://p1/p2/p3/p4/.../pb.html

The second accepts a limit corresponding to the total length of the path. If the limit is 20, the path
beginning will be truncated then ellipse and finally the filename. The result is similar to the Win32
API PathCompactPathExA.
ex :
C:\1\2\3\4\5\test.txt
== C:\1\2\3\...test.txt
\\server\p1\p2\p3\p4\p5\p6
== \\server\p1\p2...p6
http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html == http://www...pb.html
public class FileUtils {
public
public
public
public
public
public

static
static
static
static
static
static

final
final
final
final
final
final

int DEFAULT_SHORTENER_THRESHOLD = 4;
String SHORTENER_BACKSLASH_REGEX = "\\\\";
String SHORTENER_SLASH_REGEX = "/";
String SHORTENER_BACKSLASH = "\\";
String SHORTENER_SLASH = "/";
String SHORTENER_ELLIPSE = "...";

public static String pathShortener(String path) {


return pathShortener(path, FileUtils.DEFAULT_SHORTENER_THRESHOLD);
}

/**
* Return shorter path based on the limited threshold
* ex. C:/1/2/test.txt return C:/1/.../test.txt if threshold is 1
* @param path
* @param threshold
* @return
*/
public static String pathShortener(String path, int threshold) {
String regex = SHORTENER_BACKSLASH_REGEX;
String sep = SHORTENER_BACKSLASH;
if (path.indexOf("/") > 0) {
regex = SHORTENER_SLASH_REGEX;
sep = SHORTENER_SLASH;
}
String pathtemp[] = path.split(regex);
// remove empty elements
int elem = 0;
{
String newtemp [] = new String [pathtemp.length];
int j = 0;
for (int i=0; i < pathtemp.length; i++) {
if (!pathtemp[i].equals("")) {
newtemp [j++] = pathtemp[i];
elem++;
}
}
pathtemp = newtemp;
}

6.109 Shorten a long pathTag(s): IO String/Number

if (elem > threshold) {


StringBuilder sb = new StringBuilder();
int index = 0;
// drive or protocol
int pos2dots = path.indexOf(":");
if (pos2dots > 0) {
// case c:\ c:/ etc.
sb.append(path.substring(0, pos2dots + 2));
index++;
// case http:// ftp:// etc.
if (path.indexOf(":/") > 0 && pathtemp[0].length() > 2) {
sb.append(SHORTENER_SLASH);
}
}
else {
boolean isUNC = path.substring(0,2).equals(SHORTENER_BACKSLASH_REGEX);
if (isUNC) {
sb.append(SHORTENER_BACKSLASH).append(SHORTENER_BACKSLASH);
}
}
for (; index <= threshold; index++) {
sb.append(pathtemp[index]).append(sep);
}
if (index == (elem 1)) {
sb.append(pathtemp[elem 1]);
}
else {
sb.append(SHORTENER_ELLIPSE)
.append(sep)
.append(pathtemp[elem 1]);
}
return sb.toString();
}
return path;
}
/**
* Compact a path into a given number of characters. Similar to the
* Win32 API PathCompactPathExA
* @param path
* @param limit
* @return
*/
public static String pathLengthShortener(String path, int limit) {
if (path.length() <= limit) {
return path;
}
char shortPathArray[] = new char [limit];
char pathArray [] = path.toCharArray();
char ellipseArray [] = SHORTENER_ELLIPSE.toCharArray();
int pathindex = pathArray.length 1 ;
int shortpathindex = limit 1;

// fill the array from the end


int i = 0;

6.109 Shorten a long pathTag(s): IO String/Number

for (; i < limit ; i++) {


if (pathArray[pathindex i] != '/' &pathArray[pathindex i] != '\\') {
shortPathArray[shortpathindex i] = pathArray[pathindex i] ;
}
else {
break;
}
}
// check how much space is left
int free = limit i;
if (free < SHORTENER_ELLIPSE.length()) {
// fill the beginning with ellipse
for(int j = 0; j < ellipseArray.length; j++) {
shortPathArray[j] = ellipseArray[j] ;
}
}
else {
// fill the beginning with path and leave room for the ellipse
int j = 0;
for(; j + ellipseArray.length < free; j++) {
shortPathArray[j] = pathArray[j] ;
}
// ... add the ellipse
for(int k = 0; j + k < free;k++) {
shortPathArray[j + k] = ellipseArray[k] ;
}
}
return new String(shortPathArray);
}

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

String t = "C:\\Documents and Settings\\All Users\\Application Data\\Apple Computer\\iTun


System.out.println(pathShortener(t));
System.out.println(pathShortener(t, 5));
System.out.println(pathShortener("C:\\temp"));
System.out.println(pathShortener("C:\\1\\2\\3\\4\\5\\test.txt"));
System.out.println(pathShortener("C:/1/2/test.txt"));
System.out.println(pathShortener("C:/1/2/3/4/5/test.txt"));
System.out.println(pathShortener("\\\\server\\p1\\p2\\p3\\p4\\p5\\p6"));
System.out.println(pathShortener("\\\\server\\p1\\p2\\p3"));
System.out
.println(pathShortener("http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html"));
System.out.println("");
System.out.println(pathLengthShortener(t,20));
System.out.println(pathLengthShortener("C:\\temp", 20));
System.out.println(pathLengthShortener("C:\\1\\2\\3\\4\\5\\test.txt", 20));
System.out.println(pathLengthShortener("C:/1/2/testfile.txt", 15));
System.out.println(pathLengthShortener("C:/1/2/3/4/5/test.txt", 15));
System.out.println(pathLengthShortener("\\\\server\\p1\\p2\\p3\\p4\\p5\\p6", 20));
System.out
.println(pathLengthShortener("http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html", 20));
/*
output :

6.109 Shorten a long pathTag(s): IO String/Number

C:\Documents and Settings\All Users\Application Data\Apple Computer\iTunes\...\SC Info.


C:\temp
C:\1\2\3\4\...\test.txt
C:/1/2/test.txt
C:/1/2/3/4/.../test.txt
\\server\p1\p2\p3\p4\...\p6
\\server\p1\p2\p3
http://www.rgagnon.com/p1/p2/p3/.../pb.html

C:\Doc...SC Info.txt
C:\temp
C:\1\2\3\...test.txt
...testfile.txt
C:/1...test.txt
\\server\p1\p2\...p6
http://www...pb.html
*/
}
}

See also this HowTo : Ellipse a String.

6.110 Force a valid Windows filenameTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0662.html
public class FileUtils {
/**
* replace illegal characters in a filename with "_"
* illegal characters :
*
: \ / * ? | < >
* @param name
* @return
*/
public static String sanitizeFilename(String name) {
return name.replaceAll("[:\\\\/*?|<>]", "_");
}
public static void main(String args[]) throws Exception {
String test = "invalid : file ? name.txt";
System.out.println(test + " > " + FileUtils.sanitizeFilename(test));
/* output :
*
*
invalid : file ? name. > invalid _ file _ name.txt
*
*/
}
}

6.110 Force a valid Windows filenameTag(s): IO

Related HowTo : Check if filename is valid

6.111 Check if filename is validTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javacheckifafilenameisvalid.html
This HowTo will only check if a given filename is valid according to the OS rules.
You still need to handle other failures when actually creating the file (e.g. insufficient permissions,
lack of drive space, security restrictions).
import java.io.File;
import java.io.IOException;
public class FileUtils {
public static boolean isFilenameValid(String file) {
File f = new File(file);
try {
f.getCanonicalPath();
return true;
}
catch (IOException e) {
return false;
}
}
public static void main(String args[]) throws Exception {
// true
System.out.println(FileUtils.isFilenameValid("well.txt"));
System.out.println(FileUtils.isFilenameValid("well well.txt"));
System.out.println(FileUtils.isFilenameValid(""));
//false
System.out.println(FileUtils.isFilenameValid("test.T*T"));
System.out.println(FileUtils.isFilenameValid("test|.TXT"));
System.out.println(FileUtils.isFilenameValid("te?st.TXT"));
System.out.println(FileUtils.isFilenameValid("con.TXT")); // windows
System.out.println(FileUtils.isFilenameValid("prn.TXT")); // windows
}
}

Related HowTo : Sanitize a valid Windows filename.

6.111 Check if filename is validTag(s): IO

6.112 Dump a file to a HEX fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0667.html
import
import
import
import
import

java.io.File;
java.io.FileInputStream;
java.io.InputStream;
java.io.IOException;
java.io.PrintStream;

public class FileUtils {


public static void hexDump(PrintStream out, File file) throws IOException {
InputStream is = new FileInputStream(file);
int i = 0;
while (is.available() > 0) {
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder("
");
out.printf("%04X ", i * 16);
for (int j = 0; j < 16; j++) {
if (is.available() > 0) {
int value = (int) is.read();
sb1.append(String.format("%02X ", value));
if (!Character.isISOControl(value)) {
sb2.append((char)value);
}
else {
sb2.append(".");
}
}
else {
for (;j < 16;j++) {
sb1.append("
");
}
}
}
out.print(sb1);
out.println(sb2);
i++;
}
is.close();
}

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


// dump to the console
FileUtils.hexDump(System.out, new File("c:/temp/nvir.log"));
// dump to a file
FileUtils.hexDump(new java.io.PrintStream("c:/temp/nvir.hex"), new File("c:/temp/nvir.log
System.out.println("Done.");
}
}

The output looks like this :


...
343E0
343F0
34400

43 41 54 49 4F 4E 20 44 41 54 41 5C 4D 4F 5A 49
4C 4C 41 5C 50 52 4F 46 49 4C 45 53 5C 44 45 46
41 55 4C 54 5C 43 42 50 4D 53 35 4E 38 2E 53 4C

6.112 Dump a file to a HEX fileTag(s): IO

CATION DATA\MOZI
LLA\PROFILES\DEF
AULT\CBPMS5N8.SL

34410
34420
34430
34440
...

54
48
6C
20

5C
0D
65
54

4D
0A
20
6F

41
20
69
20

49
20
73
61

4C
20
20
76

5C
20
61
6F

4D
20
20
69

41
20
6D
64

49
54
61
20

4C
68
69
69

5C
69
6C
6D

54
73
62
70

52
20
6F
61

41
66
78
63

53
69
2E
74

T\MAIL\MAIL\TRAS
H..
This fi
le is a mailbox.
To avoid impact

6.113 List all files in the classpath or in a JarTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0665.html
List the files found in the classpath, the bootclasspath, the extension directory and in a Jar.
import
import
import
import
import
import
import

java.io.File;
java.io.IOException;
java.util.ArrayList;
java.util.Enumeration;
java.util.List;
java.util.jar.JarEntry;
java.util.jar.JarFile;

public class FileUtils {


/**
* list files in the given directory and subdirs (with recursion)
* @param paths
* @return
*/
public static List<File> getFiles(String paths) {
List<File> filesList = new ArrayList<File>();
for (final String path : paths.split(File.pathSeparator)) {
final File file = new File(path);
if( file.isDirectory()) {
recurse(filesList, file);
}
else {
filesList.add(file);
}
}
return filesList;
}
private static void recurse(List<File> filesList, File f) {
File list[] = f.listFiles();
for (File file : list) {
if (file.isDirectory()) {
recurse(filesList, file);
}
else {
filesList.add(file);
}
}
}

6.113 List all files in the classpath or in a JarTag(s): IO

/**
* List the content of the given jar
* @param jarPath
* @return
* @throws IOException
*/
public static List<String> getJarContent(String jarPath) throws IOException{
List<String> content = new ArrayList<String>();
JarFile jarFile = new JarFile(jarPath);
Enumeration<JarEntry> e = jarFile.entries();
while (e.hasMoreElements()) {
JarEntry entry = (JarEntry)e.nextElement();
String name = entry.getName();
content.add(name);
}
return content;
}

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


List<File> list = FileUtils.getFiles(System.getProperty("java.class.path"));
for (File file: list) {
System.out.println(file.getPath());
}
list = FileUtils.getFiles(System.getProperty("sun.boot.class.path"));
for (File file: list) {
System.out.println(file.getPath());
}
list = FileUtils.getFiles(System.getProperty("java.ext.dirs"));
for (File file: list) {
System.out.println(file.getPath());
}
List<String> content = FileUtils.getJarContent("c:/temp/DirWatch.jar");
for (String file: content) {
System.out.println(file);
}
}
}

6.114 Handle UTF8 file with BOMTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javahandleutf8filewithbom.html
From Wikipedia, the byte order mark (BOM) is a Unicode character used to signal the endianness
(byte order) of a text file or stream. Its code point is U+FEFF. BOM use is optional, and, if used,
should appear at the start of the text stream. Beyond its specific use as a byteorder indicator,
the BOM character may also indicate which of the several Unicode representations the text is
encoded in.
6.114 Handle UTF8 file with BOMTag(s): IO

The common BOMs are :


Encoding
UTF8
UTF16 (BE)
UTF16 (LE)
UTF32 (BE)
UTF32 (LE)

Representation (hexadecimal)
EF BB BF
FE FF
FF FE
00 00 FE FF
FF FE 00 00

Representation (decimal)
239 187 191
254 255
255 254
0 0 254 255
255 254 0 0

UTF8 file are a special case because it is not recommended to add a BOM to them because it
can break other tools like Java. In fact, Java assumes the UTF8 don't have a BOM so if the BOM
is present it won't be discarded and it will be seen as data.
To create an UTF8 file with a BOM, open the Windows create a simple text file and save it as
utf8.txt with the encoding UTF8.
Now if you examine the file content as binary, you see the BOM at the beginning.
If we read it with Java.
import java.io.*;
public class x {
public static void main(String args[]) {
try {
FileInputStream fis = new FileInputStream("c:/temp/utf8.txt");
BufferedReader r = new BufferedReader(new InputStreamReader(fis,
"UTF8"));
for (String s = ""; (s = r.readLine()) != null;) {
System.out.println(s);
}
r.close();
System.exit(0);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

The output contains a strange character at the beginning because the BOM is not discarded :
?helloworld

This behaviour is documented in the Java bug database, here and here. There will be no fix for
now because it will break existing tools like javadoc ou xml parsers.
The Apache IO Commons provides some tools to handle this situation. The BOMInputStream
class detects the BOM and, if required, can automatically skip it and return the subsequent byte
as the first byte in the stream.

6.114 Handle UTF8 file with BOMTag(s): IO

Or you can do it manually. The next example converts an UTF8 file to ANSI. We check the first
line for the presence of the BOM and if present, we simply discard it.
import java.io.*;
public class UTF8ToAnsiUtils {
// FEFF because this is the Unicode char represented by the UTF8 byte order mark (EF BB
public static final String UTF8_BOM = "\uFEFF";
public static void main(String args[]) {
try {
if (args.length != 2) {
System.out
.println("Usage : java UTF8ToAnsiUtils utf8file ansifile");
System.exit(1);
}
boolean firstLine = true;
FileInputStream fis = new FileInputStream(args[0]);
BufferedReader r = new BufferedReader(new InputStreamReader(fis,
"UTF8"));
FileOutputStream fos = new FileOutputStream(args[1]);
Writer w = new BufferedWriter(new OutputStreamWriter(fos, "Cp1252"));
for (String s = ""; (s = r.readLine()) != null;) {
if (firstLine) {
s = UTF8ToAnsiUtils.removeUTF8BOM(s);
firstLine = false;
}
w.write(s + System.getProperty("line.separator"));
w.flush();
}
w.close();
r.close();
System.exit(0);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
private static String removeUTF8BOM(String s) {
if (s.startsWith(UTF8_BOM)) {
s = s.substring(1);
}
return s;
}
}

6.114 Handle UTF8 file with BOMTag(s): IO

6.115 Touch a file Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javatouchafile.html
import java.io.File;
public class FileUtils {
private FileUtils () {}
public static boolean touch(String file) {
return touch(new File(file));
}
public static boolean touch(File file) {
if (file.exists()) {
return file.setLastModified(System.currentTimeMillis());
}
return false;
}
public static void main(String args[]) throws Exception {
System.out.println(FileUtils.touch("C:/temp/javax.pdf"));
System.out.println(FileUtils.touch(new File("C:/temp/Hello.class")));
System.out.println(FileUtils.touch(new File("C:/temp/missingfile.pdf")));
}
}

Another solution is to use Apache Commons IO


import org.apache.commons.io.FileUtils;
...
FileUtils.touch(myFile)

Note that if the given file doesn't exist then it a new empty file is created.
For a Windows batch solution see this HowTo

6.116 Handle Excel filesTag(s): IO JDBC Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0516.html
There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only
about OpenSource (and free) solutions.

6.115 Touch a file Tag(s): IO

6.117 JDBCODBC 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 JDBCODBC bridge is used to
access the Excel DSN.
See this HowTo for an example.

6.118 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
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import
import
import
import

jxl.Workbook;
jxl.write.Label;
jxl.write.WritableSheet;
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.msexcel");
response.setHeader
("ContentDisposition", "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.117 JDBCODBC Excel driver

6.119 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. Latest
POI version seems to support the .XLSX format.
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/

6.120 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
${employee.name}

Age
Payment
Bonus
${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);

6.119 POI

gives the result


Employees
Name
Age
Derek
35
Else
28

Payment Bonus
3000
30,00%
1500
15,00%
4500

Reading values from an XLS with jXLS is very simple. Suppose we have a worksheet with policy
numbers in the first column. We read and process them one by one.
import java.io.File;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

public void doit() throws Exception {


Workbook workbook = Workbook.getWorkbook(new File("policies.xls"));
Sheet sheet = workbook.getSheet(0);
Cell policies[] = sheet.getColumn(0);
for (Cell policy : policies) {
String nopolicy = policy.getContents();
// do something : process(nopolicy);
}
}

See http://jxls.sourceforge.net/

6.121 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 "zeroadmin"
mySQL database. The documentation is minimal at this time.
See http://xlsql.sourceforge.net/

6.122 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
import
import
import

jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
jp.ne.so_net.ga2.no_ji.jcom.*;
java.io.File;
java.util.Date;

class TestExcel {
public static void main(String[] args) throws Exception {
ReleaseManager rm = new ReleaseManager();

6.121 xlSQL

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);
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();

6.121 xlSQL

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.123 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());
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

6.123 OpenXLS Java Spreadsheet SDK

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);
}
}

See also this HowTo for a way to create a simple XLS without any additional library.

6.123 OpenXLS Java Spreadsheet SDK

6.124 Create an Excel fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0586.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.125 Detect if a XLS Excel file contains a macro (using


POI)Tag(s): IO
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectifxlsexcelfilecontainsamacro.html
The Apache POI library is required.
FIrst, we define a POIFSReaderListener, called MacroListener, to analyze a given XLS and
record if a macro is found.
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
public class MacroListener implements POIFSReaderListener {
boolean macroDetected;
public boolean isMacroDetected() {
return macroDetected;
}

6.124 Create an Excel fileTag(s): IO

public void processPOIFSReaderEvent(POIFSReaderEvent event) {


if(event.getPath().toString().startsWith("\\Macros")
|| event.getPath().toString().startsWith("\\_VBA")) {
macroDetected = true;
}
}
}

To use it, create a POIFSReader and register our MacroListener.


import java.io.FileInputStream;
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
public class DetectXLSMacro {
private DetectXLSMacro () {}
public static void main(String[] args) throws Exception{
System.out.println ("Checking " + args[0]);
POIFSReader r = new POIFSReader();
MacroListener ml = new MacroListener();
r.registerListener(ml);
FileInputStream fis = new FileInputStream(args[0]);
r.read(fis);
System.out.println (ml.isMacroDetected());
System.out.println ("Done ");
System.exit(ml.isMacroDetected()? 1 : 0);
}
}
/*
output
>java DetectXLSMacro womacro.xls
Checking womacro.xls
false
Done
>java DetectXLSMacro wmacro.xls
Checking womacro.xls
true
Done
*/

Two test files : XLS with macro and XLS without macro

6.126 Create or process a PDF fileTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0523.html

6.126 Create or process a PDF fileTag(s): IO Open Source

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");
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
import
import
import
import
import
import

com.lowagie.text.Element;
com.lowagie.text.Image;
com.lowagie.text.PageSize;
com.lowagie.text.pdf.BaseFont;
com.lowagie.text.pdf.PdfContentByte;
com.lowagie.text.pdf.PdfReader;
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

6.126 Create or process a PDF fileTag(s): IO Open Source

(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
(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();
}
}
}

See also this HowTo

6.127 Create a PDFTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0618.html

6.128 iText
http://www.lowagie.com/iText/
iText is a very simple to use package to create and manipulate PDF file.
6.127 Create a PDFTag(s): IO Open Source

For the simple need, only 1 jar is required (ex. itext2.1.3.jar, download at
http://www.lowagie.com/iText/download.html)
In this example, you pass on the command line a filename (plain text file args[0]) to convert to a
PDF file (args[1]).
import java.io.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
public class TextFileToPDF {
/*
ex. java TextFileToPDF c:\temp\text.txt c:\temp\text.pdf
*/
public static void main (String [] args){
BufferedReader input = null;
Document output = null;
System.out.println("Convert text file to pdf");
System.out.println("input : " + args[0]);
System.out.println("output : " + args[1]);
try {
// text file to convert to pdf as args[0]
input =
new BufferedReader (new FileReader(args[0]));
// letter 8.5x11
//
see com.lowagie.text.PageSize for a complete list of pagesize constants.
output = new Document(PageSize.LETTER, 40, 40, 40, 40);
// pdf file as args[1]
PdfWriter.getInstance(output, new FileOutputStream (args[1]));
output.open();
output.addAuthor("RealHowTo");
output.addSubject(args[0]);
output.addTitle(args[0]);
String line = "";
while(null != (line = input.readLine())) {
System.out.println(line);
Paragraph p = new Paragraph(line);
p.setAlignment(Element.ALIGN_JUSTIFIED);
output.add(p);
}
System.out.println("Done.");
output.close();
input.close();
System.exit(0);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

See also this HowTo


A good introduction to iText : http://www.informit.com/articles/printerfriendly.aspx?p=420686

6.127 Create a PDFTag(s): IO Open Source

6.129 Split a PDF file (using iText)Tag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0647.html
This HowTo is based on the iText package. You need a recent version (ex. 2.*)
This a command line utility. You specify the pdf file to be split. Each page is extracted to its own
pdf file.
/*
* java SplitPDFFile file.pdf
*
*
gives
file001.pdf ... filennn.pdf
*
* itext2.1.5.jar
*/
import java.io.FileOutputStream;
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.pdf.PdfCopy;
com.lowagie.text.pdf.PdfImportedPage;
com.lowagie.text.pdf.PdfReader;

public class SplitPDFFile {


/**
* @param args
*/
public static void main(String[] args) {
try {
String inFile = args[0].toLowerCase();
System.out.println ("Reading " + inFile);
PdfReader reader = new PdfReader(inFile);
int n = reader.getNumberOfPages();
System.out.println ("Number of pages : " + n);
int i = 0;
while ( i < n ) {
String outFile = inFile.substring(0, inFile.indexOf(".pdf"))
+ "" + String.format("%03d", i + 1) + ".pdf";
System.out.println ("Writing " + outFile);
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, new FileOutputStream(outFile));
document.open();
PdfImportedPage page = writer.getImportedPage(reader, ++i);
writer.addPage(page);
document.close();
writer.close();
}
}
catch (Exception e) {
e.printStackTrace();

6.129 Split a PDF file (using iText)Tag(s): IO Open Source

}
/* example :
java SplitPDFFile d:\temp\x\tx.pdf
Reading d:\temp\x\tx.pdf
Number of pages : 3
Writing d:\temp\x\tx001.pdf
Writing d:\temp\x\tx002.pdf
Writing d:\temp\x\tx003.pdf
*/
}
}

6.130 Concatenate PDF files (using iText)Tag(s): IO Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0646.html
This HowTo is based on the iText package. You need a recent version (ex. 2.*)
This a command line utility. You specify the pdf files to be merge into one.
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import
import
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.pdf.PRAcroForm;
com.lowagie.text.pdf.PdfCopy;
com.lowagie.text.pdf.PdfImportedPage;
com.lowagie.text.pdf.PdfReader;
com.lowagie.text.pdf.SimpleBookmark;

public class ConcatPDFFiles {


@SuppressWarnings("unchecked")
public static void main(String[] args) {
try {
if (args.length < 2) {
System.out.println
("Usage: ConcatPDFFiles file1.pdf [file2.pdf... fileN.pdf] out.pdf");
System.exit(1);
}
int pageOffset = 0;
ArrayList master = new ArrayList();
int f = 0;
String outFile = args[args.length 1];

6.130 Concatenate PDF files (using iText)Tag(s): IO Open Source

Document document = null;


PdfCopy writer = null;
while (f < args.length 1) {
PdfReader reader = new PdfReader(args[f]);
reader.consolidateNamedDestinations();
int n = reader.getNumberOfPages();
List bookmarks = SimpleBookmark.getBookmark(reader);
if (bookmarks != null) {
if (pageOffset != 0) {
SimpleBookmark.shiftPageNumbers(bookmarks, pageOffset,
null);
}
master.addAll(bookmarks);
}
pageOffset += n;
if (f == 0) {
document = new Document(reader.getPageSizeWithRotation(1));
writer = new PdfCopy(document,
new FileOutputStream(outFile));
document.open();
}
PdfImportedPage page;
for (int i = 0; i < n;) {
++i;
page = writer.getImportedPage(reader, i);
writer.addPage(page);
}
PRAcroForm form = reader.getAcroForm();
if (form != null) {
writer.copyAcroForm(reader);
}
f++;
}
if (!master.isEmpty()) {
writer.setOutlines(master);
}
document.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

ref : iText example


See also this HowTo.

6.131 Convert TIF to PDFTag(s): AWT IO IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0645.html
6.131 Convert TIF to PDFTag(s): AWT IO IO Open Source

This HowTo is based on the iText package. You need a recent version (ex. 2.*)
This a command line utility. You pass one or many tif files as argument and corresponding PDF
are produced. Multipage TIF are supported. TIF are resized to fit a letterpage dimension.
import java.io.FileOutputStream;
import
import
import
import
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.Image;
com.lowagie.text.PageSize;
com.lowagie.text.Rectangle;
com.lowagie.text.pdf.PdfContentByte;
com.lowagie.text.pdf.PdfWriter;
com.lowagie.text.pdf.RandomAccessFileOrArray;
com.lowagie.text.pdf.codec.TiffImage;

public class TiffToPDF {


public static void main(String[] args) {
if (args.length < 1) {
System.out
.println("Usage: Tiff2Pdf file1.tif [file2.tif ... fileN.tif]");
System.exit(1);
}
String tiff;
String pdf;
for (int i = 0; i < args.length; i++) {
tiff = args[i];
pdf = tiff.substring(0, tiff.lastIndexOf('.') + 1) + "pdf";
Document document = new Document(PageSize.LETTER, 0, 0, 0, 0);
try {
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(pdf));
int pages = 0;
document.open();
PdfContentByte cb = writer.getDirectContent();
RandomAccessFileOrArray ra = null;
int comps = 0;
try {
ra = new RandomAccessFileOrArray(tiff);
comps = TiffImage.getNumberOfPages(ra);
}
catch (Throwable e) {
System.out.println("Exception in " + tiff + " "
+ e.getMessage());
continue;
}
System.out.println("Processing: " + tiff);
for (int c = 0; c < comps; ++c) {
try {
Image img = TiffImage.getTiffImage(ra, c + 1);
if (img != null) {
System.out.println("page " + (c + 1));
img.scalePercent
(7200f / img.getDpiX(), 7200f / img.getDpiY());
document.setPageSize
(new Rectangle(img.getScaledWidth(), img.getScaledHeight()));
img.setAbsolutePosition(0, 0);
cb.addImage(img);
document.newPage();
++pages;
}
}

6.131 Convert TIF to PDFTag(s): AWT IO IO Open Source

catch (Throwable e) {
System.out.println("Exception " + tiff + " page "
+ (c + 1) + " " + e.getMessage());
}
}
ra.close();
document.close();
}
catch (Throwable e) {
e.printStackTrace();
}
System.out.println("done");
}
}
}

6.132 Convert HTML to PDF using iTextTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javahtmltopdfusingitext.html
iText
Using iText HTMLWorker, you can produce PDF version of an HTML document. The document
must be simple. Many things like FORM elements or external images are not supported.
Done with iText 5.4.1.

import java.io.FileOutputStream;
import java.io.StringReader;
import
import
import
import

com.itextpdf.text.Document;
com.itextpdf.text.PageSize;
com.itextpdf.text.html.simpleparser.HTMLWorker; // deprecated
com.itextpdf.text.pdf.PdfWriter;

public class HtmlToPDF1 {


// itextpdf5.4.1.jar http://sourceforge.net/projects/itext/files/iText/
public static void main(String ... args ) {
try {
Document document = new Document(PageSize.LETTER);
PdfWriter.getInstance(document, new FileOutputStream("c://temp//testpdf1.pdf"));
document.open();
document.addAuthor("Real Gagnon");
document.addCreator("Real's HowTo");
document.addSubject("Thanks for your support");
document.addCreationDate();
document.addTitle("Please read this");
HTMLWorker htmlWorker = new HTMLWorker(document);
String str = "<html><head></head><body>"+
"<a href='http://www.rgagnon.com/howto.html'><b>Real's HowTo</b></a>" +
"<h1>Show your support</h1>" +

6.132 Convert HTML to PDF using iTextTag(s): IO Open Source

"<p>It DOES cost a lot to produce this site in ISP storage and transfer fees, " +
"in personal hardware and software costs to set up test environments, and above all,"
"the huge amounts of time it takes for one person to design and write the actual cont
"<p>If you feel that effort has been useful to you, perhaps you will consider giving
"<p>Donate using PayPal to real@rgagnon.com." +
"<p>Contributions via PayPal are accepted in any amount " +
"<P><br><table border='1'><tr><td>Java HowTo<tr>" +
"<td bgcolor='red'>Javascript HowTo<tr><td>Powerbuilder HowTo</table>" +
"</body></html>";
htmlWorker.parse(new StringReader(str));
document.close();
System.out.println("Done");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

As you can see, the validity of the parsed HTML (using HTMLWorker) is very relax. Closing tags
are not required : <BR> is ok (<BR/> is not mandatory).
HTMLWorker is ok with older iText version but the recommended approach with new iText
(HTMLWorker is now deprecated) is to use the XMLWorker. XMLWorker is stricter since you
must send XHTML document to it.
import java.io.FileOutputStream;
import java.io.StringReader;
import
import
import
import
public

com.itextpdf.text.Document;
com.itextpdf.text.PageSize;
com.itextpdf.text.pdf.PdfWriter;
com.itextpdf.tool.xml.XMLWorkerHelper;
class HtmlToPDF2 {
// itextpdf5.4.1.jar http://sourceforge.net/projects/itext/files/iText/
// xmlworker5.4.1.jar http://sourceforge.net/projects/xmlworker/files/
public static void main(String ... args ) {
try {
Document document = new Document(PageSize.LETTER);
PdfWriter pdfWriter = PdfWriter.getInstance
(document, new FileOutputStream("c://temp//testpdf.pdf"));
document.open();
document.addAuthor("Real Gagnon");
document.addCreator("Real's HowTo");
document.addSubject("Thanks for your support");
document.addCreationDate();
document.addTitle("Please read this");
XMLWorkerHelper worker = XMLWorkerHelper.getInstance();

String str = "<html><head></head><body>"+


"<a href='http://www.rgagnon.com/howto.html'><b>Real's HowTo</b></a>"
"<h1>Show your support</h1>" +
"<p>It DOES cost a lot to produce this site in ISP storage and tran
"in personal hardware and software costs to set up test environments,
"the huge amounts of time it takes for one person to design and write
"<p>If you feel that effort has been useful to you, perhaps you will
"<p>Donate using PayPal to real@rgagnon.com.</p>" +
"<p>Contributions via PayPal are accepted in any amount</p>" +
"<P><br/><table border='1'><tr><td>Java HowTo</td></tr><tr>" +
"<td style='backgroundcolor:red;'>Javascript HowTo</td></tr>" +

6.132 Convert HTML to PDF using iTextTag(s): IO Open Source

"<tr><td>Powerbuilder HowTo</td></tr></table></p>" +
"</body></html>";
worker.parseXHtml(pdfWriter, document, new StringReader(str));
document.close();
System.out.println("Done.");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

Note : To get the color on a table cell, you need to use a style because the bgcolor attribute is not
supported. By default, FORM elements are not rendered. Review this document to see what is
supported : http://demo.itextsupport.com/xmlworker/doc.html
See also Convert HTML to PDF using YAHP

6.133 Convert HTML to PDF using YAHP Tag(s):


IO OpenSource
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaconverthtmltopdfusingyahp.html
As seen in this HowTo, iText can be used to transform an HTML document to PDF. The result is
good with simple HTML but if you get fancy then the result is not so good.
For better result, the Open Source package YAHP (Yet another Html to Pdf converter) is a good
choice. YAHP is based on iText, FlyingSaucer and JTidy.
import
import
import
import
import
import

java.io.File;
java.io.FileOutputStream;
java.util.ArrayList;
java.util.HashMap;
java.util.List;
java.util.Map;

// http://www.allcolor.org/YaHPConverter/
import org.allcolor.yahp.converter.CYaHPConverter;
import org.allcolor.yahp.converter.IHtmlToPdfTransformer;
public class HtmlToPdf_yahp {
public static void main(String ... args ) throws Exception {
htmlToPdfFile();
}
public static void htmlToPdfFile() throws Exception {
CYaHPConverter converter = new CYaHPConverter();
File fout = new File("c:/temp/x.pdf");

6.133 Convert HTML to PDF using YAHP Tag(s): IO OpenSource

FileOutputStream out = new FileOutputStream(fout);


Map properties = new HashMap();
List headerFooterList = new ArrayList();
String str = "<HTML><HEAD></HEAD><BODY><H1>Testing</H1><FORM>" +
"check : <INPUT TYPE='checkbox' checked=checked/><br/>"
"</FORM></BODY></HTML>";

properties.put(IHtmlToPdfTransformer.PDF_RENDERER_CLASS,
IHtmlToPdfTransformer.FLYINGSAUCER_PDF_RENDERER);
//properties.put(IHtmlToPdfTransformer.FOP_TTF_FONT_PATH, fontPath);
converter.convertToPdf(str,
IHtmlToPdfTransformer.A4P,
headerFooterList,
"file:///temp/", // root for relative external CSS and IMAGE
out,
properties);
out.flush();
out.close();
}
}

In the next example, we read an existing HTML file and convert it to a PDF file.
import
import
import
import
import
import
import

java.io.File;
java.io.FileOutputStream;
java.util.ArrayList;
java.util.HashMap;
java.util.List;
java.util.Map;
java.util.Scanner;

// http://www.allcolor.org/YaHPConverter/
import org.allcolor.yahp.converter.CYaHPConverter;
import org.allcolor.yahp.converter.IHtmlToPdfTransformer;
public class HtmlToPdf_yahp_2 {
public static void main(String ... args ) throws Exception {
String root = "c:/temp/html";
String input = "file_1659686.htm"; // need to be charset utf8
htmlToPdfFile(new File(root, input),
new File(root, input + ".pdf"));
System.out.println("Done");
}
public static void htmlToPdfFile(File htmlIn, File pdfOut) throws Exception {
Scanner scanner =
new Scanner(htmlIn).useDelimiter("\\Z");
String htmlContents = scanner.next();
CYaHPConverter converter = new CYaHPConverter();
FileOutputStream out = new FileOutputStream(pdfOut);
Map properties = new HashMap();
List headerFooterList = new ArrayList();
properties.put(IHtmlToPdfTransformer.PDF_RENDERER_CLASS,
IHtmlToPdfTransformer.FLYINGSAUCER_PDF_RENDERER);
//properties.put(IHtmlToPdfTransformer.FOP_TTF_FONT_PATH, fontPath);
converter.convertToPdf(htmlContents,
IHtmlToPdfTransformer.A4P,
headerFooterList,
"file:///temp/html/",

6.133 Convert HTML to PDF using YAHP Tag(s): IO OpenSource

out,
properties);
out.flush();
out.close();
}
}
NOTE : After downloading YAHP (and its dependencies), you still need to build a YAHP.JAR, it's done easily with Eclipse... but you can get it
here.

6.134 Convert a png/jpg/gif file to PDF using iTextTag(s):


IO Open Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaimagetopdfusingitext.html
iText

import java.io.FileOutputStream;
//com.lowagie...
old version
//com.itextpdf... recent version
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.Image;

public class ImageToPDF {


public static void main(String ... args) {
Document document = new Document();
String input = "c:/temp/capture.png"; // .gif and .jpg are ok too!
String output = "c:/temp/capture.pdf";
try {
FileOutputStream fos = new FileOutputStream(output);
PdfWriter writer = PdfWriter.getInstance(document, fos);
writer.open();
document.open();
document.add(Image.getInstance(input));
document.close();
writer.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

You can get the image from an URL :


document.add(Image.getInstance
(new java.net.URL("http://www.rgagnon.com/images/javahowto.jpg")));

6.134 Convert a png/jpg/gif file to PDF using iTextTag(s): IO Open Source

And you can resize it :


Image img = Image.getInstance
(new java.net.URL("http://www.rgagnon.com/images/javahowto.jpg"));
img.scalePercent(50);
document.add(img);

6.135 Print a PDFTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaprintapdf.html
[Windows only]
You can launch the Acrobat Reader to print a PDF to the default printer.
More infos the "unsupported" commandline switches for the Acrobat reader :
http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/intro_to_sdk/DeveloperFAQ.pdf
(page 27).
import java.io.IOException;
public class PdfUtils {
static final String WIN_COMSPEC = System.getenv("comspec");
static final String WIN_ACROBAT = "acrord32.exe";
public static void print(String pdf) throws IOException
{
String[] commands =
{WIN_COMSPEC,
"/c",
"start",
WIN_ACROBAT,
"/t",
"/h",
pdf };
Runtime.getRuntime().exec(commands);
}
public static void main(String[] args) throws IOException {
PdfUtils.print("c:/users/public/temp/test.pdf");
}
}

Unfortunately, Acrobat Reader stays opened (but minimized because of the /h switch) after the
printing operation :(
You can use a special wrapper to force the closing the Acrobat Reader after the print operation.
See http://www.biopdf.com/acrowrap/close_adobe_reader.php (acrowrap.exe).

6.135 Print a PDFTag(s): IO Open Source

6.136 Extract text from a PDF (with Apache Tika) Tag(s): IO


OpenSource
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaextracttextfromapdf.html
You can do it with Apache Tika
import java.io.FileInputStream;
import java.io.InputStream;
import
import
import
import
import

org.apache.tika.parser.pdf.PDFParser;
org.apache.tika.metadata.Metadata;
org.apache.tika.parser.ParseContext;
org.apache.tika.sax.BodyContentHandler;
org.xml.sax.ContentHandler;

public class ParsePDFWithTika {


public static void main(String args[]) throws Exception {
InputStream is = null;
try {
is = new FileInputStream("C:/Temp/realhowtovbs20121221.pdf");
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
PDFParser pdfparser = new PDFParser();
pdfparser.parse(is, contenthandler, metadata, new ParseContext());
System.out.println(contenthandler.toString());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (is != null) is.close();
}
}
}

See also Extract text from HTML, Get Mime Type from a file.

6.137 Create a compressed (ZIP) fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0065.html

6.136 Extract text from a PDF (with Apache Tika) Tag(s): IO OpenSource

/*
** 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 = ((sizecsize)*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.138 Display compressed (ZIP) file contentTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0066.html
6.138 Display compressed (ZIP) file contentTag(s): IO

/*
** 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
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 = ((sizecsize)*100) / size;
if (ratio < 10) {
err.write(' ');
}
err.print(ratio + "%
");
}
else {
err.print(" 0%
");
}
}
else {
err.println(" (stored
0 %");
}
err.println(e.getName());
}
}

6.138 Display compressed (ZIP) file contentTag(s): IO

hh:mm:ss");

6.139 Expand the compressed (ZIP) fileTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0067.html
/*
** a simple unZIP tool
**
** ex. java UnZip file.zip file1
**
java UnZip file.zip
**
*/
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.text.*;

to unzip file 1 from file.zip


to unzip file.zip

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.140 Emit a beepTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0001.html
6.139 Expand the compressed (ZIP) fileTag(s): IO

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 Howto.

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.141 Emit a ToneTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0499.html
//jdk1.3
import javax.sound.sampled.*;
public class SoundUtils {
public static float SAMPLE_RATE = 8000f;
public static void tone(int hz, int msecs)
throws LineUnavailableException
{
tone(hz, msecs, 1.0);
}
public static void tone(int hz, int msecs, double vol)
throws LineUnavailableException
{
byte[] buf = new byte[1];
AudioFormat af =
new AudioFormat(
SAMPLE_RATE, // sampleRate
8,
// sampleSizeInBits

6.141 Emit a ToneTag(s): IO

1,
// channels
true,
// signed
false);
// bigEndian
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) * 127.0 * vol);
sdl.write(buf,0,1);
}
sdl.drain();
sdl.stop();
sdl.close();
}
public static void main(String[] args) throws Exception {
SoundUtils.tone(1000,100);
Thread.sleep(1000);
SoundUtils.tone(100,1000);
Thread.sleep(1000);
SoundUtils.tone(5000,100);
Thread.sleep(1000);
SoundUtils.tone(400,500);
Thread.sleep(1000);
SoundUtils.tone(400,500, 0.2);
}
}

See also this HowTo

6.142 Play an audio file from an applicationTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0006.html
Note: Since JDK1.2, Java can play WAV directly, see
http://java.sun.com/docs/books/tutorial/sound/playing.html.
In application, the javax.sound.* package is used.
import
import
import
import

java.io.File;
java.io.FileInputStream;
javax.sound.sampled.*;
javax.swing.*;

public class AppWithSound extends JFrame {


private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

6.142 Play an audio file from an applicationTag(s): IO

public void run() {


AppWithSound app = new AppWithSound();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.startApp();
}
});
}
public AppWithSound() {
initGUI();
}
private void startApp() {
playStartupSound();
setVisible(true);
}
private void endApp() {
System.exit(0);
}
private void playStartupSound() {
Runnable soundPlayer = new Runnable() {
public void run() {
try {
// use one of the WAV of Windows installation
File tadaSound = new File(System.getenv("windir") + "/" +
"media/tada.wav");
AudioInputStream audioInputStream = AudioSystem
.getAudioInputStream(new FileInputStream(tadaSound));
AudioFormat audioFormat = audioInputStream
.getFormat();
DataLine.Info dataLineInfo = new DataLine.Info(
Clip.class, audioFormat);
Clip clip = (Clip) AudioSystem
.getLine(dataLineInfo);
clip.open(audioInputStream);
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread soundPlayingThread = new Thread(soundPlayer);
soundPlayingThread.start();
}
private void initGUI() {
setSize(300, 200);
}
}

6.142 Play an audio file from an applicationTag(s): IO

6.143 Produce special sound effectTag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0632.html
//jdk1.3
import javax.sound.sampled.*;
import java.util.Random;
public class SoundUtils {
public static float SAMPLE_RATE = 8000f;
public static void laser(int repeat)
throws LineUnavailableException, InterruptedException
{
AudioFormat af =
new AudioFormat(
SAMPLE_RATE, // sampleRate
8,
// sampleSizeInBits
1,
// channels
true,
// signed
false);
// bigEndian
SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
sdl.open(af);
sdl.start();
byte[] buf = new byte[1];
int step;
for (int j=0; j < repeat; j++) {
step = 10;
for(int i=0; i < 2000; i++) {
buf[0] = ((i%step > 0) ? 32 : (byte)0);
if(i%250 == 0) step += 2;
sdl.write(buf,0,1);
}
Thread.sleep(200);
}
sdl.drain();
sdl.stop();
sdl.close();
}
public static void warp(int repeat)
throws LineUnavailableException, InterruptedException
{
AudioFormat af =
new AudioFormat(
SAMPLE_RATE, // sampleRate
8,
// sampleSizeInBits
1,
// channels
true,
// signed
false);
// bigEndian
SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
sdl.open(af);
sdl.start();
byte[] buf = new byte[1];
int step;

6.143 Produce special sound effectTag(s): IO

for (int j=0; j < repeat; j++) {


step = 25;
for(int i=0; i < 2000; i++) {
if(i <500) {
buf[0] = ((i%step > 0) ? 32 : (byte)0);
if(i%25 == 0) step;
}
else {
buf[0] = ((i%step > 0) ? 16 : (byte)0);
if(i%50 == 0) step++;
}
sdl.write(buf,0,1);
}
}
sdl.drain();
sdl.stop();
sdl.close();
}
public static void bang()
throws LineUnavailableException, InterruptedException
{
AudioFormat af =
new AudioFormat(
SAMPLE_RATE, // sampleRate
8,
// sampleSizeInBits
1,
// channels
true,
// signed
false);
// bigEndian
SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
sdl.open(af);
sdl.start();
byte[] buf = new byte[1];
Random r = new Random();
boolean silence = true;
for (int i=0 ; i < 8000 ; i++) {
while(r.nextInt() % 10 != 0) {
buf[0] =
silence ? 0 :
(byte)Math.abs(r.nextInt() %
(int)(1. + 63. * (1. + Math.cos(((double)i)
* Math.PI / 8000.))));
i++;
sdl.write(buf,0,1);
}
silence = !silence;
}
sdl.drain();
sdl.stop();
sdl.close();
}
public static void main(String[] args) throws Exception {
SoundUtils.laser(5);
Thread.sleep(1000);
SoundUtils.warp(10);
Thread.sleep(1000);
SoundUtils.bang();
}
}

6.143 Produce special sound effectTag(s): IO

When a sound is playing, the action is stopped until the sound is finished. To play a sound and
keep the application responding to event, you need to play the sound in a Thread.
import
import
import
import

javax.sound.sampled.*;
javax.swing.*;
java.awt.*;
java.awt.event.*;

public class AppWithSound2 extends JFrame implements ActionListener {


JButton b1;
JButton b2;
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
AppWithSound2 app = new AppWithSound2();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.startApp();
}
});
}
public AppWithSound2() {
initGUI();
}
private void startApp() {
setVisible(true);
}
private void initGUI() {
setLayout(new FlowLayout());
setSize(300, 200);
b1 = new JButton("Sound with no thread");
b2 = new JButton("Sound with thread");
b1.addActionListener(this);
b2.addActionListener(this);
add(b1);
add(b2);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
LaserSound.laser();
}
if (e.getSource() == b2) {
new LaserSound().start();
}
}
}
class LaserSound extends Thread {
public void run() {
LaserSound.laser();
}
public static void laser() {
int repeat = 10;
try {
AudioFormat af = new AudioFormat(8000f, // sampleRate

6.143 Produce special sound effectTag(s): IO

8, // sampleSizeInBits
1, // channels
true, // signed
false); // bigEndian
SourceDataLine sdl;
sdl = AudioSystem.getSourceDataLine(af);
sdl.open(af);
sdl.start();
byte[] buf = new byte[1];
int step;
for (int j = 0; j < repeat; j++) {
step = 10;
for (int i = 0; i < 2000; i++) {
buf[0] = ((i % step > 0) ? 32 : (byte) 0);
if (i % 250 == 0)
step += 2;
sdl.write(buf, 0, 1);
}
Thread.sleep(200);
}
sdl.drain();
sdl.stop();
sdl.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

See also this HowTo

6.144 Use the Java Speech API (JSPAPI)Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javausejavaspeechapi.html
The Java Speech API (JSAPI) is not part of the JDK and Sun does not ship an implementation of
JSAPI. Sun porivides the specification and thirdparties provide the implementations.
The most popular implementation is the opensource TTS (TextToSpeech) package,
http://freetts.sourceforge.net/
You download the required jars here : http://sourceforge.net/projects/freetts/files/
The configuration is done in 2 steps.
speech.properties contains the package to provide the JSAPI implementation. Typically, the file is
located in the JRE\lib directory. In this example, I register the TTS package directly.
You specify the available voices. You have many different ways to do so, see the javadoc at
6.144 Use the Java Speech API (JSPAPI)Tag(s): IO

http://freetts.sourceforge.net/javadoc/com/sun/speech/freetts/VoiceManager.html#getVoices(). In
this example, the available voice is setted with the system property "freetts.voices".
import java.beans.PropertyVetoException;
import java.util.Locale;
import
import
import
import
import
import
import

javax.speech.AudioException;
javax.speech.Central;
javax.speech.EngineException;
javax.speech.EngineStateError;
javax.speech.synthesis.Synthesizer;
javax.speech.synthesis.SynthesizerModeDesc;
javax.speech.synthesis.Voice;

public class SpeechUtils {


SynthesizerModeDesc desc;
Synthesizer synthesizer;
Voice voice;

public void init(String voiceName)


throws EngineException, AudioException, EngineStateError,
PropertyVetoException
{
if (desc == null) {
System.setProperty("freetts.voices",
"com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory");
desc = new SynthesizerModeDesc(Locale.US);
Central.registerEngineCentral
("com.sun.speech.freetts.jsapi.FreeTTSEngineCentral");
synthesizer = Central.createSynthesizer(desc);
synthesizer.allocate();
synthesizer.resume();
SynthesizerModeDesc smd =
(SynthesizerModeDesc)synthesizer.getEngineModeDesc();
Voice[] voices = smd.getVoices();
Voice voice = null;
for(int i = 0; i < voices.length; i++) {
if(voices[i].getName().equals(voiceName)) {
voice = voices[i];
break;
}
}
synthesizer.getSynthesizerProperties().setVoice(voice);
}
}
public void terminate() throws EngineException, EngineStateError {
synthesizer.deallocate();
}
public void doSpeak(String speakText)
throws EngineException, AudioException, IllegalArgumentException,
InterruptedException
{
synthesizer.speakPlainText(speakText, null);
synthesizer.waitEngineState(Synthesizer.QUEUE_EMPTY);
}

6.144 Use the Java Speech API (JSPAPI)Tag(s): IO

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


SpeechUtils su = new SpeechUtils();
su.init("kevin16");
// high quality
su.doSpeak("Hello world from Real's How To");
su.terminate();
}
}

Related links :
http://www.ryanh.com/uncategorized/javaspeechjsapifreetts/
http://java.sun.com/products/javamedia/speech/forDevelopers/jsapidoc/javax/speech/packagesummar
http://today.java.net/pub/a/today/2006/04/13/vocaljava.html

6.145 Play a Windows sound Tag(s): IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaplayawindowssound.html
You can access a sound as defined in the Windows configuration for specific event. The JDK
exposed them as properties and the values for these properties are retrieved with the
getDesktopProperty() method on java.awt.Toolkit. The property related to a sound is a Runnable
that plays the current audio clip for that property.
import java.awt.Toolkit;
public class WindowsSounds {
public static void main(String ... args) throws InterruptedException {
System.out.println("Sound 1");
Runnable sound1 =
(Runnable)Toolkit.getDefaultToolkit().getDesktopProperty("win.sound.default");
if(sound1 != null) sound1.run();
Thread.sleep(1000);
System.out.println("Sound 2");
Runnable sound2 =
(Runnable)Toolkit.getDefaultToolkit().getDesktopProperty("win.sound.exclamation");
if(sound2 != null) sound2.run();

System.out.println("Supported windows property names:");


String propnames[] = (String[])Toolkit.getDefaultToolkit().getDesktopProperty("win.propNa
for(int i = 0; i < propnames.length; i++) {
if (propnames[i].startsWith("win.sound.")) {
System.out.println(propnames[i]);
}
}
}
}
/*
output :

6.145 Play a Windows sound Tag(s): IO

Sound 1
Sound 2
Supported windows property names:
win.sound.asterisk
win.sound.close
win.sound.default
win.sound.exclamation
win.sound.exit
win.sound.hand
win.sound.maximize
win.sound.menuCommand
win.sound.menuPopup
win.sound.minimize
win.sound.open
win.sound.question
win.sound.restoreDown
win.sound.restoreUp
win.sound.start
*/

Keep in mind that this technique is very specific to Windows and will not work on others OS.

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

6.145 Play a Windows sound Tag(s): IO

7 JDBC
7.1 javajdbc

7.2 Get JDBC driver for major database vendorsTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0113.html
Most database vendors provide a JDBC driver for their products, check the vendor Web site.
Oracle : web site
Microsoft SQLServer : web site
MySQL : web site
Sun has a list : Sun's JDBC vendors list
There is no JDBC driver for Microsoft Access. While it's possible to use the ODBCJDBC bridge
included with the JDK, the performance and stability of this solution is not great.
A commercial product, called SteelMDB, is a JDBC type 4 driver that allows to perform SQL
queries and other JDBC operations on Microsoft Access database files (MS Access 2000, 2002,
2003, XP versions). The driver is completely platformindependent and does not require installing
additional client or server software to provide access to MDB files.
http://www.csvjdbc.com/stels_mdb_jdbc.htm

7.3 Connect to a database via JDBCODBCTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0107.html
You have to keep in mind that the bridge JDBCODBC 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 {

7 JDBC

// 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
("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.4 SELECT data from a tableTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0108.html

7.4 SELECT data from a tableTag(s): JDBC

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();
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 SELECT data from a tableTag(s): JDBC

7.5 INSERT data into a tableTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0109.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 class StringUtils {
public static void main(String args[]) {
System.out.println(StringUtils.sqlQuote("Real's HowTo"));
System.out.println(StringUtils.sqlQuote("HowTo"));
System.out.println(StringUtils.sqlQuote(""));
System.out.println(StringUtils.sqlQuote("Real's HowTo's"));
System.out.println(StringUtils.sqlQuote("'"));
System.out.println(StringUtils.sqlQuote("''"));
/*
output:
Real''s HowTo
HowTo
Real''s HowTo''s
''
''''
*/
}
public static String sqlQuote(String str) {
if(str == null || str.length() == 0 || str.indexOf("\'") == 1){
return str;
}
StringBuffer sb = new StringBuffer();

7.5 INSERT data into a tableTag(s): JDBC

for(int i = 0; i < str.length(); i++){


sb.append(str.charAt(i));
if(str.charAt(i)=='\'') sb.append('\'')
}
return sb.toString();
}
}

Or 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();
stmt.close();
}
catch (Exception e){
e.printStackTrace();
}

The character "\" (backslash) can be difficult to use in an INSERT statement since "\" is considered
as an escape character in Java (and probably by the database too).
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.6 Tag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0110.html
Note:the MyConnection class was used to connect to the DB

PreparedStatement prepstmt;
try {
prepstmt = theConn.prepareStatement
("UPDATE tCust SET custName = ? "+
" WHERE custId = ?");

7.6 Tag(s): JDBC

prepstmt.setString(1,"Smith");
prepstmt.setString(2, cust_id.getText());
prepstmt.executeUpdate();
theConn.commit();
prepstmt.close();
}
catch (Exception e) {
e.printStackTrace();
}

7.7 Tag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0111.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.8 Test for an empty ResultSetTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0116.html
boolean found;
ResultSet rs;
...
// execute the query and then
found = rs.next();

7.7 Tag(s): JDBC

if (found)
System.out.println("Record found");
else
System.out.println("RECORD NOT FOUND");

7.9 Get a record count with a SQL StatementTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0292.html
Statement s = conn.createStatement();
ResultSet r = s.executeQuery("SELECT COUNT(*) AS rowcount FROM MyTable");
r.next();
int count = r.getInt("rowcount") ;
r.close() ;
System.out.println("MyTable has " + count + " row(s).");

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();
int count = r.getRow();
r.beforeFirst();
...

NOTE : Your JDBC driver may not support this feature.

7.10 Store and retrieve an object from a tableTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0117.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;

7.9 Get a record count with a SQL StatementTag(s): JDBC

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()) {
// 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);
// recreate the object
Employee emp = (Employee)ois.readObject();
// display the result for demonstration
System.out.println(emp.name);

7.9 Get a record count with a SQL StatementTag(s): JDBC

}
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.11 Retrieve an ImageTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0118.html
// column is column index in ResultSet containing the image,

7.11 Retrieve an ImageTag(s): JDBC

// 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.12 Insert an ImageTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0119.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.13 Call a stored procedureTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0115.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

7.12 Insert an ImageTag(s): JDBC

cs.setInt(2, 1);
cs.registerOutParameter(2, Types.INTEGER);
cs.registerOutParameter(3, Types.INTEGER);
cs.execute();
int output_parm2 = cs.getInt(2);
int output_parm3 = cs.getInt(3);

// #2 is INPUT
//
and OUTPUT
// #3 is OUTPUT

// get the result from OUTPUT #2


// get the result from OUTPUT #3

7.14 Stored procedure with Input/Output parms and a


ResultSetTag(s): JDBC
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0120.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));
}

7.14 Stored procedure with Input/Output parms and a ResultSetTag(s): JDBC

// 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 = : "
+ 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.15 Fix incomplete field returned by the ResultSetTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0121.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.16 Transfer a ResultSet to a JTableTag(s): JDBC Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0309.html
// TableModel definition
String[] tableColumnsName = {"col 1","col 2","col 3"};
DefaultTableModel aModel = (DefaultTableModel) aTable.getModel();
aModel.setColumnIdentifiers(tableColumnsName);
// the query

7.15 Fix incomplete field returned by the ResultSetTag(s): JDBC

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.17 Detect SQL errors or warningsTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0331.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 errortransaction 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();

7.17 Detect SQL errors or warningsTag(s): JDBC

//
//
//
if

If a SQLWarning object was returned by the


Connection object, the warning messages are displayed.
You may have multiple warnings chained together
(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
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.17 Detect SQL errors or warningsTag(s): JDBC

7.18 Using DSNless connectionTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0345.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,"","");
// 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.19 Specify a CharSet when connecting to a DBMSTag(s):


JDBC
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0371.html
Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) ;
// setup the properties
java.util.Properties prop = new java.util.Properties();
prop.put("charSet", "iso88597"); // for example...
prop.put("user", username);
prop.put("password", password);
// Connect to the database
con = DriverManager.getConnection(url, prop);

7.18 Using DSNless connectionTag(s): JDBC

7.20 List tables in a databaseTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0317.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 {
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();
}
}

7.20 List tables in a databaseTag(s): JDBC

void disconnect() {
try {
dbConn.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

7.21 Enable JDBC loggingTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0411.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();
}
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);

7.21 Enable JDBC loggingTag(s): JDBC

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.22 Detect if a table existsTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0485.html
Connection c = ...
DatabaseMetaData dbm = c.getMetaData();
// check if "employee" table is there
ResultSet tables = dbm.getTables(null, null, "employee", null);

7.22 Detect if a table existsTag(s): JDBC

if (rs.next()) {
// Table exists
}
else {
// Table does not exist
}

7.23 Convert a ResultSet to XMLTag(s): JDBC XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0511.html
import
import
import
import
import
import

java.sql.Connection;
java.sql.Statement;
java.sql.Driver;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.ResultSetMetaData;

import
import
import
import
import
import
import

javax.xml.parsers.DocumentBuilder;
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.transform.*;
javax.xml.transform.stream.*;
javax.xml.transform.dom.*;
org.w3c.dom.Document;
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();

7.23 Convert a ResultSet to XMLTag(s): JDBC XML

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,"ISO88591");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "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");

7.23 Convert a ResultSet to XMLTag(s): JDBC XML

*/
}
}

7.24 Display ResultSet data in an HTML Table in ServletTag(s):


JDBC Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0378.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.25 Escape special character in a LIKE clauseTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0554.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.

7.24 Display ResultSet data in an HTML Table in ServletTag(s): JDBC Servlet/JSP

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 value LIKE '%=_' {escape '='}");

If you don't want to use JDBC escape sequence then it's possible to use native SQL based on the
target DBMS.
For Oracle, it will look like this :
SELECT value FROM vendors WHERE value LIKE '%=_%' ESCAPE '=';

ref : LaboOracle.com.

7.26 Log the SQL StatementsTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0602.html

7.27 Plain JDBC Logging


See this HowTo.

7.28 P6Spy
P6Spy is an open source framework for applications that intercept and optionally modify database
statements.

7.26 Log the SQL StatementsTag(s): JDBC

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/
It is a bit old, the latest release is 2003!

7.29 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/

7.30 JDBC Logger


JDBC Logger is an Open Source Java tool that intercepts and logs all database statements that use
JDBC. It is intended for developers to monitor SQL statements generated by EJB, Hibernate or any
other database access tool that doesn't display them in clear.
Download at http://jdbclogger.sourceforge.net/

7.31 Log4JDBC
Log4jdbc is a Java JDBC driver that can log SQL and/or JDBC calls (and optionally SQL timing
information) for other JDBC drivers
Download at http://code.google.com/p/log4jdbc/

7.32 Oracle JDBC


Oracle driver provides some debugging infos. See this HowTo

7.33 Insert data in batch modeTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0658.html
The regular approach
import java.io.IOException;

7.29 Proxool

import
import
import
import

java.sql.Connection;
java.sql.DriverManager;
java.sql.PreparedStatement;
java.sql.SQLException;

public class PerfInsert {


public static void main(String[] args) throws ClassNotFoundException,
SQLException, IOException {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@//oracle.server:1529/prod";
Connection conn = DriverManager.getConnection(url, "scott", "tiger");
conn.setAutoCommit(false);
ExecutionTimer t = new ExecutionTimer(); // see this HowTo
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO PROD.COUNTER VALUES (?,?,?)");
int i =0;
t.start();
while (i < 100) {
pstmt.setString(1, "test");
pstmt.setString(2, String.valueOf(i));
pstmt.setFloat(3, 0);
pstmt.executeUpdate();
i++;
}
conn.commit();
t.end();
System.out.println("Timer : " + t.duration());
pstmt.close();
System.out.println("Ok.");
}
}

When inserting many INSERTs (or DELETE/UPDATE), JDBC provides the addBatch() method to
cumulate the SQL statements. When ready, the whole batch is sent in one shot to minimize the
network traffic. A special attention to the error handling should made.
(Sun) Sending Batch Updates
The performance gain is good. For example, 100 individual INSERTS == 140ms 10 batched
INSERTS == 32ms
Using PreparedStatement in batch mode
import
import
import
import
import

java.io.IOException;
java.sql.Connection;
java.sql.DriverManager;
java.sql.PreparedStatement;
java.sql.SQLException;

public class PerfInsert {


public static void main(String[] args) throws ClassNotFoundException,
SQLException, IOException {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@//oracle.server:1529/prod";
Connection conn = DriverManager.getConnection(url, "scott", "tiger");
conn.setAutoCommit(false);
ExecutionTimer t = new ExecutionTimer(); // see this HowTo
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO PROD.COUNTER VALUES (?,?,?)");
int i =0;
t.start();

7.29 Proxool

while (i < 100) {


pstmt.setString(1, "test");
pstmt.setString(2, String.valueOf(i));
pstmt.setFloat(3, 0);
pstmt.addBatch();
i++;
}
int[] upCounts = stmt.executeBatch();
conn.commit();
t.end();
System.out.println("Timer : " + t.duration());
pstmt.close();
System.out.println("Ok.");
}
}

Using Statement in batch mode


import
import
import
import
import

java.io.IOException;
java.sql.Connection;
java.sql.DriverManager;
java.sql.Statement;
java.sql.SQLException;

public class PerfInsert {


public static void main(String[] args) throws ClassNotFoundException,
SQLException, IOException {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@//oracle.server:1529/prod";
Connection conn = DriverManager.getConnection(url, "scott", "tiger");
conn.setAutoCommit(false);
ExecutionTimer t = new ExecutionTimer(); // see this HowTo
int i =0;
t.start();
while (i < 100) {
stmt.addBatch(
"INSERT INTO PROD.COUNTER VALUES "
+ "(\"test\", " + i + ", 0)");
stmt.addBatch();
i++;
}
int[] upCounts = stmt.executeBatch();
conn.commit();
t.end();
System.out.println("Timer : " + t.duration());
stmt.close();
System.out.println("Ok.");
}
}

7.34 Retrieve large ResultSetTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0659.html
7.34 Retrieve large ResultSetTag(s): JDBC

JDBC provides a way to give a hint about the size of the expected ResultSet.
Statement.setFetchSize() gives a hint about the number of rows that should be fetched from the
database each time new rows are needed. The goal is to reduce unnecessary network round trip.
With Oracle, the default value is 10 (i.e. the Oracle driver will retrieve ResultSets in 10row chunks)
A JDBC Compliant driver may choose to ignore the setFetchSize(). You should do some testing first
to check if the result is optimal.
See (Sun) 5.1.9 Providing Performance Hints
import
import
import
import
import
import
import

java.io.FileWriter;
java.io.IOException;
java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;

public class PerfSelect {


public static void main(String[] args) throws ClassNotFoundException,
SQLException, IOException {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@//oracle.server:1529/prod";
Connection conn = DriverManager.getConnection(url, "scott", "tiger");
conn.setAutoCommit(false);
ExecutionTimer t = new ExecutionTimer(); // see this HowTo
String sql = "SELECT * FROM PROD.DOCUMENTS";
t.start();
Statement stmt = conn.createStatement();
stmt.setFetchSize(200);
ResultSet rs = stmt.executeQuery(sql);
FileWriter fw = new FileWriter("d:/temp/o.out");
while (rs.next()) {
fw.write(rs.getString(1) + " " + rs.getString(2) + "\n");
}
t.end();
System.out.println("Timer : " + t.duration());
stmt.close();
rs.close();
fw.flush();
fw.close();
System.out.println("Ok.");
}
}
/*
348831 rows
without prefetch
48296 ms
48045 ms

(def == 10)

prefetch == 100
14859
14749
prefetch == 200
13343
13296

7.34 Retrieve large ResultSetTag(s): JDBC

prefetch == 500
13891
13812
prefetch == 1000
13078
13078

*/

7.35 Handle datesTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0114.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 'yyyymmdd'}
Time
{t {'hh:mm:ss'}
Timestamp {ts `yyyymmdd 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());
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.
7.35 Handle datesTag(s): JDBC

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 '19991231' } )");

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.36 Get current date using JDBCTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0383.html
With most DBMS, JDBC function escape sequence can be used :
SELECT {fn curdate() }
SELECT {fn curtime() }
SELECT {fn now() }

for current date


for current hour
for current date and hour

for Oracle, you add the from dual


SELECT {fn curdate() } FROM dual
SELECT {fn curtime() } FROM dual
SELECT {fn now() }
FROM dual

for current date


for current hour
for current date and hour

Example :
// for Oracle
String sql =
"select {fn dayname ({fn now()})}," +

7.36 Get current date using JDBCTag(s): JDBC

"
"
"
"

{d '19970524'}, " +
{t '10:30:29' }, " +
{ts '19970524 10:30:29.123'}" +
from dual" ;

ResultSet rs = stmt.executeQuery(sql);
while (rs.next())
System.out.println("results:
"\n "
+ rs.getString(2)
"\n "
+ rs.getString(3)
"\n "
+ rs.getString(4)

" + rs.getString(1) +
+
+
);

7.37 Insert the current dateTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0567.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.38 Read data from Excel worksheetTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0362.html
Let's assume we have a worksheet like this
LASTNAME
Reiser
Ricci
Gugliuzza

FIRSTNAME
Beth
Dylan
Brian

ID
102
111
116

To access this data, we can use the JDBCODBC bridge. Microsoft provides an ODBC driver to
Excel worksheet.
Define an ODBC datasource (system DSN) named "employee_xls" that points to that worksheet.

7.37 Insert the current dateTag(s): JDBC

example 1
import
import
import
import

java.io.*;
java.net.*;
java.sql.*;
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 + "
}
rs.close();
stmt.close();

id : " + id);

}
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);

7.37 Insert the current dateTag(s): JDBC

);

}
System.out.println("");
}
rs.close();
st.close();
}
catch(Exception ex) {
System.err.print("Exception: ");
System.err.println(ex.getMessage());
}
finally {
con.close();
}
}
}

7.39 Handle Excel filesTag(s): IO JDBC Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0516.html
There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only about
OpenSource (and free) solutions.

7.40 JDBCODBC 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 JDBCODBC bridge is used to
access the Excel DSN.
See this HowTo for an example.

7.41 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
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

7.39 Handle Excel filesTag(s): IO JDBC Open Source

import
import
import
import

jxl.Workbook;
jxl.write.Label;
jxl.write.WritableSheet;
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.msexcel");
response.setHeader
("ContentDisposition", "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/

7.42 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. Latest POI
version seems to support the .XLSX format.
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).
7.42 POI

See http://jakarta.apache.org/poi/

7.43 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
${employee.name}

Age
Payment
Bonus
${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
Derek
35
Else
28

Payment Bonus
3000
30,00%
1500
15,00%
4500

Reading values from an XLS with jXLS is very simple. Suppose we have a worksheet with policy
numbers in the first column. We read and process them one by one.
import java.io.File;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

public void doit() throws Exception {


Workbook workbook = Workbook.getWorkbook(new File("policies.xls"));
Sheet sheet = workbook.getSheet(0);
Cell policies[] = sheet.getColumn(0);
for (Cell policy : policies) {
String nopolicy = policy.getContents();
// do something : process(nopolicy);
}
}

7.43 JXLS

See http://jxls.sourceforge.net/

7.44 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 "zeroadmin"
mySQL database. The documentation is minimal at this time.
See http://xlsql.sourceforge.net/

7.45 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
import
import
import

jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
jp.ne.so_net.ga2.no_ji.jcom.*;
java.io.File;
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("./");

7.44 xlSQL

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.46 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);

7.46 OpenXLS Java Spreadsheet SDK

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);
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

7.46 OpenXLS Java Spreadsheet SDK

(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.

7.47 Connect to an Oracle database with JDBCTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0112.html
The JDBC driver for Oracle 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
// 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
//
// SID System ID of the Oracle server database instance.
//
By default, Oracle Database 10g Express Edition
//
creates one database instance called XE.
//
ex : String url = "jdbc:oracle:thin:@myhost:1521:xe";

7.47 Connect to an Oracle database with JDBCTag(s): JDBC

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.");
}
}

You can find the SID in the tnsnames.ora file, ex :


XE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = myhost)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)

While it is not to difficult to connect using the example above, it would be nice to connect without
having to specify a server and a port number. Since release 10.2.0.1.0, it's possible to give only a
TNSNAMES entry and the driver extract the required infos (server and port) for the defined
TNSNAMES.ORA file. In order for this to work you must have configured the file TNSNAMES.ORA
correctly and set a the java property oracle.net.tns_admin.
import
import
import
import
import

java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;

import oracle.jdbc.OracleDriver;
public class TestOra {
public TestOra() {
System.setProperty("oracle.net.tns_admin","\\\\myserver\\TNSNAMES_DIR");
// or
// java.exe Doracle.net.tns_admin=\\myserver\TNSNAMES_DIR TestOra ...
//
}
public void doit
String usr =
String pwd =
String url =

() throws SQLException {
"scott";
"tiger";
"jdbc:oracle:thin:@MYORCL";

DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection(url,usr,pwd);
String sql = "select {fn now()} from dual" ;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);

7.47 Connect to an Oracle database with JDBCTag(s): JDBC

while (rs.next())
System.out.println("results: " + rs.getString(1));
conn.close();
}
public static void main(String[] args){
TestOra test = new TestOra();
try {
test.doit();
System.out.println("Done..");
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
/*
\\myserver\TNSNAMES_DIR\tnsnames.ora

MYORCL =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = orcltest.local)(PORT = 1521))
)
(CONNECT_DATA = (SERVICE_NAME = orcl)(INSTANCE_ROLE=ANY))
)
*/

See also this HowTo to connect using the Oracle Connection Pool.

7.48 Connect to Oracle using a connection poolTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0545.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
7.48 Connect to Oracle using a connection poolTag(s): JDBC

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.
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 {
System.out.println("OracleDataSource Initialization");
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
{

7.48 Connect to Oracle using a connection poolTag(s): JDBC

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 =
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 {

7.48 Connect to Oracle using a connection poolTag(s): JDBC

Thread.sleep(1000);
}
catch(Exception e) { }
}
}
}
}

and finally, the main class


import java.net.URL;
import java.sql.*;
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.49 Retrieve the generated keys (JDBC Oracle)Tag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0656.html
Oracle can generated keys by creating a sequence. This sequence is then incremented with each
INSERT to provides a unique numeric key.
While it's possible to do the INSERT and then a SELECT to RETRIEVE the last sequence, JDBC
3.0 provides a way to tell to the INSERT to return the specified generated keys.
PreparedStatement pstmt = null;
ResultSet result = null;
String sql = "INSERT INTO ORDERS (DESC_ORDER) VALUES(?)";
//
// we have a trigger (on INSERT) to populate a field (ID_ORDER)
// an Oracle sequence is used to generated the value.
//
pstmt = this.dbConnection.prepareStatement(sql,new String [] {"ID_ORDER"});
pstmt.setString(1,orderDto.getDesc());
if(pstmt.executeUpdate() != 1){
throw new OrderException("Error INSERT Order!!!");
}
result = pstmt.getGeneratedKeys();
result.next();
idOrder = result.getLong(1); // 1 > ID_ORDER

7.49 Retrieve the generated keys (JDBC Oracle)Tag(s): JDBC

Works only with INSERT


The JDBC driver must be JDBC 3.0
Oracle 10g Release 2 is required (others DBMS (ingres, DB2, etc.) support the same feature)
You can check if this feature is supported
DatabaseMetaData metaData = this.dbConnection.getMetaData();
log("SupportsGetGeneratedKeys?="+metaData.supportsGetGeneratedKeys());
log("ProductDatabaseName="+metaData.getDatabaseProductName());
log("ProductDatabaseVersion="+metaData.getDatabaseProductVersion());
log("ProductDatabaseMajorVersion="+metaData.getDatabaseMajorVersion());
log("ProductDatabaseMinorVersion="+metaData.getDatabaseMinorVersion());
log("ProductDriverName="+metaData.getDriverName());
log("ProductDriverVersion="+metaData.getDriverVersion());
log("ProductDriverMajor="+metaData.getDriverMajorVersion());
log("ProductDriverMinor="+metaData.getDriverMinorVersion());
log("JDBCMajorVersion="+metaData.getJDBCMajorVersion());
log("JDBCMinorVersion="+metaData.getJDBCMajorVersion());

Nice article on the subject : Oracle JDBC: Automatic key generation and retrieval
Thanks to F.Joyal for his help

7.50 Debug Oracle JDBC connectionTag(s): JDBC


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0663.html
See this HowTo if you want to log only the SQL statement.
To get Oracle JDBC log output, you must use the oracle driver debug JAR files (in your
classpath), which are indicated with a "_g" in the file name, ex. ojdbc5_g.jar.
Then you need to enable java.util.logging (since Oracle 10/JDK1.4)to see the activities
java Doracle.jdbc.Trace=true

Djava.util.logging.config.file=c:/myapp/oracledebug.propertie

The oracledebug.properties contains the logging configuration.


handlers = java.util.logging.FileHandler
#
or can be handlers = java.util.logging.ConsoleHandler
java.util.logging.FileHandler.pattern = c:/myapp/jdbc.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
#
or can be java.util.logging.FileHandler.formatter = java.util.logging.XmlFormatter
oracle.jdbc.driver.level = FINE
# Uncomment and/or change the levels for more detail
#oracle.jdbc.connector.level = FINE
#oracle.jdbc.internal.level = FINE
#oracle.jdbc.datum.level = FINEST

7.50 Debug Oracle JDBC connectionTag(s): JDBC

#oracle.jdbc.adt.level = FINEST
#oracle.jdbc.conversion.level = FINEST
#oracle.jdbc.adt.level = FINEST
#oracle.jdbc.thin.level = FINEST
#oracle.jdbc.datum.level = FINEST
#oracle.jdbc.kprb.level = FINEST
#oracle.jdbc.pool.level = FINEST
#oracle.jdbc.xa.level = FINEST
#oracle.jdbc.sqlj.level = FINEST
#oracle.jdbc.oci.level = FINEST
#oracle.jdbc.jpub.level = FINEST

# Category definitions (and corresponding levels) are listed in the following:


#
#
USER_OPER
JDBC API level tracing.
#
INFO
(expected volume: low)
#
#
PROG_ERR
Program error (eg. an unexpected value encountered
#
SEVERE
in a switch statement). Messages of this category
#
is not maskable.
#
(expected volume: low)
#
#
ERROR
Error conditions that usually lead to catastrophic
#
SEVERE
or unrecoverable results. Messages of this
#
category is not maskable.
#
(expected volume: low)
#
#
WARNING
Error conditions that are usually recoverable.
#
WARNING
Note that the module and submodule filters do not
#
apply to messages of this category. See also
#
enableWarning().
#
(expected volume: low)
#
#
FUNCTION
Function entry/return information.
#
FINE
(expected volume: medium)
#
#
DEBUG1
Highlevel debug information.
#
FINER
(expected volume: medium)
#
#
DEBUG2
Detail debug information.
#
FINEST
(expected volume: high)
#
#
SQL_STR
SQL string
#
CONFIG
(expected volume: low)

For OCI connection, it's a little bit different.


If you use the OCI driver, you can enable Net8 tracing on both the client and the server. Keep in
mind, however, that enabling Net8 tracing translates into a substantial performance hit.
To enable client tracing, you add four parameters to your sqlnet.ora file, which is located in your
$ORACLE_HOME\network\admin directory.
TRACE_LEVEL_CLIENT = SUPPORT
TRACE_DIRECTORY_CLIENT = c:\oracle\trace
TRACE_UNIQUE_CLIENT = ON
TRACE_FILE_CLIENT = SESS

7.50 Debug Oracle JDBC connectionTag(s): JDBC

TRACE_LEVEL_CLIENT can be one of the following four values:


0 or OFF
4 or USER
10 or ADMIN
16 or SUPPORT

To turn tracing on and get the most amount of information, specify the following:
TRACE_LEVEL_CLIENT = SUPPORT

To turn tracing off, which you definitely want to do after your debugging session is complete, use
0 or OFF:
TRACE_LEVEL_CLIENT = OFF

7.51 Connect to an Oracle database using KerberosTag(s):


JDBC
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaoraclejdbcconnectwithkerberos.html
The Oracle thin driver (v11g) supports Kerberos authentication.
Using this method, you don't need to provide a username/password to Oracle. Kerberos
authentication can take advantage of the user name and password maintained by the operating
system to authenticate users to the database or use another set of user credentials specified by
the application.
The knowledge of how to configure your Kerberos environment is required.
import
import
import
import
import
import

java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;
java.util.Properties;

import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.net.ano.AnoServices;
public class TestOra3 {
public TestOra3() {
}
public void doit () throws SQLException {
Properties props = new Properties();
props.setProperty(
OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICES,
"( " + AnoServices.AUTHENTICATION_KERBEROS5 + " )");
props.setProperty(

7.51 Connect to an Oracle database using KerberosTag(s): JDBC

OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_MUTUAL,
"true");
System.setProperty("java.security.krb5.conf","c:/oracle/krb5.conf");
String url = "jdbc:oracle:thin:@//oracleserver.mydomain.com:5561/mydatabaseinstance";
DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection(url,props);
String sql = "select {fn user()} from dual" ;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next())
System.out.println("results: " + rs.getString(1));
conn.close();
}
public static void main(String[] args){
TestOra3 test = new TestOra3();
try {
test.doit();
System.out.println("Done..");
}
catch (SQLException e) {
e.printStackTrace();
}
}
}

A list of problems that may occur when attempting a login :


http://java.sun.com/j2se/1.5.0/docs/guide/security/jgss/tutorials/Troubleshooting.html.
On my installation (Windows XP SP2), I got the exception :
javax.security.auth.login.LoginException: KrbException:
KDC has no support for encryption type (14)

This registry entry has solved the problem :


HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\
Value Name: allowtgtsessionkey
Value Type: REG_DWORD
Value: 0x01

7.52 Identify the connected program to an Oracle


databaseTag(s): JDBC
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaoraclejdbcidentifyconnectionorigin.html
The v$session view contains session information for each current session.

7.52 Identify the connected program to an Oracle databaseTag(s): JDBC

When connecting with ODBC or OCI, the program column will contain the executable name used
to make the connection. If the connection is made with the Thin Driver,the program is "JDBC Thin
Client" (by default). The good news is that this information can be customized at the connect time
to provide a more interesting name (maximum length = 64 characters).
import
import
import
import
import
import

java.sql.Connection;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.SQLException;
java.sql.Statement;
java.util.Properties;

import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
public class TestOra5 {
public TestOra5() {

public void doit () throws SQLException {


Properties props = new Properties();
props.setProperty("user","scott");
props.setProperty("password","tiger");
props.setProperty(
OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_PROGRAM,
"My Java program : " + this.getClass().getName() );
String url = "jdbc:oracle:thin:@//oracle.mycompany.com:5561/myinstance";
DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection(url, props);
String sql =
"SELECT username, osuser, program, machine " +
"FROM SYS.V_$SESSION " +
"WHERE username IS NOT null ORDER BY logon_time, sid";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
String format = "|%1$20s|%2$20s|%3$40s|%4$20s\n";
System.out.format(format, "username", "osuser.", "program", "machine");
while (rs.next())
System.out.format
( format, rs.getString(1), rs.getString(2),
rs.getString(3), rs.getString(4));
conn.close();
}
public static void main(String[] args){
TestOra5 test = new TestOra5();
try {
test.doit();
System.out.println("Done..");
}
catch (SQLException e) {
e.printStackTrace();
}
}
}

Output :
7.52 Identify the connected program to an Oracle databaseTag(s): JDBC

|username
|bigadmin
|real
|scott

|osuser.
|real
|real
|real

|program
|JDBC Thin Client
|Winsql.exe
|My Java program : TestOra5

|machine
|Jupiter
|Saturn
|Mercury

7.53 Use a CHAR field in the WHERE clause in a


PreparedStatementTag(s): JDBC
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaoraclecharfieldpreparedstatement.html
With Oracle, if a CHAR field used in a WHERE clause contains trailing spaces then the trailing
spaces must be there, there is no automatic trimming.
For example, if the "code_value" field is defined as CHAR(10) and the content is "A10" then the
real value is "A10
" and the trailing spaces must be present in the comparaison to have a
match.
The following PreparedStatement will fail to retrieve the value :
PreparedStatement ps;
ps = conn.prepareStatement("SELECT desc_value from prod.DICT_VALUES WHERE code_value= ?") ;
ps.setString(1,"A10");
rs = ps.executeQuery();
while (rs.next())
System.out.println("results: " + rs.getString(1));

But this one is ok


PreparedStatement ps;
ps = conn.prepareStatement("SELECT desc_value from prod.DICT_VALUES WHERE code_value= ?") ;
ps.setString(1,"A10
");
rs = ps.executeQuery();
while (rs.next())
System.out.println("results: " + rs.getString(1));

The easy fix to define the field as a VARCHAR not a CHAR or replace the PreparedStatement
with a Statement.
Statement s;
s= conn.createStatement();
String val = "A10";
String sql ="SELECT desc_value from prod.DICT_VALUES WHERE code_value='" + val + "'" ;
ResultSet rs = s.executeQuery(sql);
while (rs.next())
System.out.println("results: " + rs.getString(1));

To keep a PreparedStatement, you need to add explicitly the trailing spaces or trim the value.
The first try is to trim the value with the rtrim() function.
7.53 Use a CHAR field in the WHERE clause in a PreparedStatementTag(s): JDBC

ps = conn.prepareStatement("SELECT desc_value from prod.DICT_VALUES WHERE rtrim(code_value)=


ps.setString(1,"A10");
rs = ps.executeQuery();
while (rs.next())
System.out.println("results: " + rs.getString(1));

This is working fine but Oracle will not use the index and probably perform a table scan which is
not a good thing!
Oracle provides an API to make sure that the parameter received is handled as a CHAR value by
the database.
import oracle.jdbc.OraclePreparedStatement;
...
PreparedStatement ps;
ps = conn.prepareStatement("SELECT dewsc_value from prod.DICT_VALUES WHERE code_value= ?") ;
((OraclePreparedStatement)ps).setFixedCHAR(1, "A10");
rs = ps.executeQuery();
while (rs.next())
System.out.println("results: " + rs.getString(1));

The good thing is that we don't need to know the CHAR width of the field, the driver will figure it
out for us but using the special Oracle class can be problem.
A better solution is to instruct the database to add the missing trailing spaces with the rpad()
function.

ps = conn.prepareStatement("SELECT desc_value from prod.DICT_VALUES WHERE code_value= rpad(?


ps.setString(1,"A10");
rs = ps.executeQuery();
while (rs.next())
System.out.println("results: " + rs.getString(1));

This a better solution because ee are not using a special Oracle class and the database will use
the index.

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

7.53 Use a CHAR field in the WHERE clause in a PreparedStatementTag(s): JDBC

8 JNI
8.1 javajni

8.2 Use native code through JNITag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0283.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 CTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0284.html

8 JNI

To Java from C (as seen from the previous Howto) :


#include "JavaHowTo.h"
JNIEXPORT jstring JNICALL Java_JavaHowTo_sayHello
(JNIEnv *env, jobject obj) {
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 {

8 JNI

public static void main(String[] args) {


JavaHowTo jht = new JavaHowTo();
jht.sayHello();
}
}

8.4 Set the computer clockTag(s): Date and Time JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0285.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.4 Set the computer clockTag(s): Date and Time JNI

8.5 Determine the signature of a methodTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0286.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);

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
boolean
byte
char
double
float
int
long
object
short
void
array

Chararacter
Z
B
C
D
F
I
J
L
S
V
[

Note that to specify an object, the "L" is followed by the object's class name and ends with a
semicolon, ';' .
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 {};

8.5 Determine the signature of a methodTag(s): JNI

/*
()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
*/

The javap utility can be used on the java.* or your own classes.

8.6 Use arraysTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0287.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");
}
}

8.6 Use arraysTag(s): JNI

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));
}
}

Thanks to H. Horn for the following HowTo


Without passing the array directly to the JNI function, it's possible to fetch directly from the class the
array.
Note that to get the reflection stuff working, the native method (printArrayR) could'nt be static.
The Java code
class JNIHowTo {
private static native void printArray (int[] t); // print an int[] array
private native void printArrayR (); // print int[] array 'myArray' via reflection
static {
System.loadLibrary("javahowto");
}
private int[] myArray = { 4, 7, 5, 9, 2, 0, 1 };
public static void main (String[] args) {
JNIHowTo jht = new JNIHowTo();
printArray(jht.myArray); // print 'myArray'
jht.printArrayR(); // print 'myArray' via reflection
}
}

The JNI code (tested on 64bit Windows / Java 6u24 64bit using mingw 64bit cross compiler
(x86_64w64mingw32gcc).
#include "JNIHowTo.h"
JNIEXPORT void JNICALL Java_JNIHowTo_printArray
(JNIEnv* env, jclass obj, jintArray arr) {
jsize len = (*env)>GetArrayLength(env, arr);
printf("int[] : [");
if (len > 0) {
jboolean iscopy;
jint* tab = (*env)>GetIntArrayElements(env, arr,
for (int i = 0; i < len ; i++) printf(" %d", (int)tab[i]);
if (iscopy == JNI_TRUE) (*env)>ReleaseIntArrayElements(env, arr, tab, JNI_ABORT);
}
printf(" ]\n"); fflush(stdout);
}
JNIEXPORT void JNICALL Java_JNIHowTo_printArrayR (JNIEnv* env, jclass obj) {
jclass
cls = (*env)>GetObjectClass(env, obj);
jfieldID fid = (*env)>GetFieldID(env, cls, "myArray", "[I");
if (fid) {
jobject arr = (*env)>GetObjectField(env, obj, fid);
jsize
len = (*env)>GetArrayLength(env, arr);
printf("via reflection:\nint[] : [");
if (len > 0) {
jboolean iscopy;

8.6 Use arraysTag(s): JNI

jint* tab = (*env)>GetIntArrayElements(env, arr, &iscopy);


for (int i = 0; i < len ; i++) printf(" %d", (int)tab[i]);
if (iscopy == JNI_TRUE) (*env)>ReleaseIntArrayElements(env, arr, tab, JNI_ABORT);
}
printf(" ]\n"); fflush(stdout);
}
}

8.7 Load a DLLTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0318.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 MouseWheelTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0314.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.7 Load a DLLTag(s): JNI

8.9 Throw an Exception (from JNI code)Tag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0323.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
(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)Tag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0322.html
The MyOwnException class
8.9 Throw an Exception (from JNI code)Tag(s): JNI

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 {
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 packageTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0348.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);

8.11 JNI from a packageTag(s): JNI

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

8.12 Make a Window "stay on top"Tag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0353.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){
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 CTag(s): JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0354.html
8.12 Make a Window "stay on top"Tag(s): JNI

#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);
if (args == 0) {
printf("Out of memory\n");
exit(1);
}
env>CallStaticVoidMethod(cls, mid, args);
return 0;
}

8.14 Retrieve environment variable (JNI)Tag(s): Environment JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0460.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

8.14 Retrieve environment variable (JNI)Tag(s): Environment JNI

(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 7bit ASCII characters.
See also this HowTo.

8.15 Get the PIDTag(s): Environment JNI


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0467.html
class JavaHowTo {
public native long getCurrentProcessId();
static {
System.loadLibrary("jni2");
}
}
public class JNIJavaHowTo {
public static void main(String[] args) {
JavaHowTo jht = new JavaHowTo();
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;
}

8.15 Get the PIDTag(s): Environment JNI

JNIEXPORT jlong JNICALL Java_JavaHowTo_getCurrentProcessId


(JNIEnv *, jobject) {
// return GetCurrentProcessId();
return getpid();
}

You can download the whole thing here.


For a Javaonly solution, see this HowTo

8.16 Clear the console, set color and cursor position (JNI)Tag(s):
JNI
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0469.html
[Windows only]
First you need this Java stub (JavaHowTo.java) to provide an interface to the JNI DLL (jni3.dll).
class JavaHowTo {
public
public
public
public
public
public

static
static
static
static
static
static

final
final
final
final
final
final

short
short
short
short
short
short

FOREGROUND_BLACK = 0x0;
FOREGROUND_BLUE = 0x1;
FOREGROUND_GREEN = 0x2;
FOREGROUND_RED
= 0x4;
FOREGROUND_WHITE = 0x7;
FOREGROUND_INTENSITY = 0x8;

public static final short BACKGROUND_BLUE = 0x10;


public static final short BACKGROUND_GREEN = 0x20;
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.

8.16 Clear the console, set color and cursor position (JNI)Tag(s): JNI

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) {
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);
}

8.16 Clear the console, set color and cursor position (JNI)Tag(s): JNI

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");
// 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.

8.16 Clear the console, set color and cursor position (JNI)Tag(s): JNI

8.17 Call Windows API (Open source solution)Tag(s): JNI Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0497.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/

8.18 Detect if a program is running (JNA)Tag(s): JNI/JNA


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectifaprogramisrunningusingjna.html
JNA (Java Native Access) provides Java programs easy access to native shared libraries (DLLs on
Windows) without writing anything but Java code no JNI or native code is required.
In this HowTo, we detect if an instance of program is running or not. The following code checks if
Excel is running. It Excel is running, we activate the window and bring it to the front.
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;

// https://github.com/twall/jna#readme
//
you need 2 jars : jna3.5.1.jar and platform3.5.1.jar
public class IsRunning {
public static void main(String[] args) {
HWND hwnd = User32.INSTANCE.FindWindow
(null, "Microsoft Excel Classeur1"); // window title
if (hwnd == null) {
System.out.println("Excel is not running");
}
else{
User32.INSTANCE.ShowWindow(hwnd, 9 );
// SW_RESTORE
User32.INSTANCE.SetForegroundWindow(hwnd);
// bring to front
}

8.17 Call Windows API (Open source solution)Tag(s): JNI Open Source

}
}

This technique looks for the window title. Since my Excel installation is in French then the default
sheet name is Classeur1(in English it would be Sheet1).
Another way is to look for the window class name. For Excel, the class name is XLMAIN.
To search for the class name instead of the window title, change this line :
HWND hwnd = User32.INSTANCE.FindWindow("XLMAIN", null); // window class name

To determine the class name of a window for a specific program, you can use something like Spy++
(installed with Visual Studio).

It is also possible to search for the class name and the title to make the search more precise.

8.19 Get Windows Special Folders (JNA) Tag(s): JNI/JNA


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javagetwindowsspecialfoldersusingjna.html
JNA (Java Native Access) provides Java programs easy access to native shared libraries (DLLs on
Windows) without writing anything but Java code no JNI or native code is required.
In this HowTo, we retrieve the path of some Windows Special Folders : Program Files, Common
Documents and the Desktop.
You can get the others by using the right identifier from the constants defined in the ShlObj
interface.
import com.sun.jna.Native;

8.19 Get Windows Special Folders (JNA) Tag(s): JNI/JNA

import com.sun.jna.platform.win32.Shell32;
import com.sun.jna.platform.win32.ShlObj;
import com.sun.jna.platform.win32.WinDef;

// https://github.com/twall/jna#readme
//
you need 2 jars : jna3.5.1.jar and platform3.5.1.jar
public class GetFolderPathDemo {
public static void main(String[] args) {
char[] pszPath = new char[WinDef.MAX_PATH];
Shell32.INSTANCE.SHGetFolderPath(null,
ShlObj.CSIDL_PROGRAM_FILES, null, ShlObj.SHGFP_TYPE_CURRENT,
pszPath);
System.out.println(Native.toString(pszPath));
Shell32.INSTANCE.SHGetFolderPath(null,
ShlObj.CSIDL_DESKTOPDIRECTORY, null, ShlObj.SHGFP_TYPE_CURRENT,
pszPath);
System.out.println(Native.toString(pszPath));
Shell32.INSTANCE.SHGetFolderPath(null,
ShlObj.CSIDL_COMMON_DOCUMENTS, null, ShlObj.SHGFP_TYPE_CURRENT,
pszPath);
System.out.println(Native.toString(pszPath));
/*
* output :
* C:\Program Files
* C:\Users\Real_User\Desktop
* C:\Users\Public\Documents
*/
}
}

See also : 1, 2 and 3

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

8.19 Get Windows Special Folders (JNA) Tag(s): JNI/JNA

9 Javascript interaction
9.1 javajs

9.2 * Read me *Tag(s): Javascript interaction


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0168.html

The examples in these Howto's are tested with Netscape 7 (or better) on Windows.
Windows and Linux
The LiveConnect package is included with the Java plugin.
The official documentation for the various versions can be found at
http://java.sun.com/products/plugin/reference/docs/index.html. You need to add the plugin.jar to the
classpath (JRE_HOME\lib) for compilation.
Mac (old)
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
Mac OSX
Java is preinstalled with Mac OSX.
The required jar is in /System/Library/Frameworks/JavaVM.framework/Versions/<your
version>/Home/lib
You need to add the plugin.jar to the classpath (JRE_HOME\lib) for compilation.

9.3 Wakeup a Java appletTag(s): Javascript interaction


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0169.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.
9 Javascript interaction

[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;
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 = kj;
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]

9 Javascript interaction

<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
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 Javascript interaction

9.4 Call a Java method from JavascriptTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0170.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.
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>

9.4 Call a Java method from JavascriptTag(s): Javascript interaction

</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>
<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


JavaScriptTag(s): Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0346.html
[IE4 or better]
<OBJECT ID="myApplet" ...>

9.5 Calling Java applets methods using DOM and JavaScriptTag(s): Javascript interaction

...
<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
Plugin.

9.6 Access Java variables from JavascriptTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0171.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).
[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());
}

9.6 Access Java variables from JavascriptTag(s): Javascript interaction

</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 appletTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0172.html

9.8 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)";
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>

9.7 Call Javascript from a Java appletTag(s): Javascript interaction

<APPLET CODE="InJava4.class"
NAME="myApplet" MAYSCRIPT
HEIGHT=10 WIDTH=10>
</APPLET>
</BODY>
/HTML
Try it here

9.9 Using the netscape.javascript.JSObject package


Official documentation for JSObject
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.
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
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);
}
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.*;
...

9.9 Using the netscape.javascript.JSObject package

// 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);

9.10 Create dynamic HTML from a Java appletTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0173.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]

9.10 Create dynamic HTML from a Java appletTag(s): Javascript interaction

import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
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.11 Have Applets on different frames communicates with each


otherTag(s): Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0174.html

9.11 Have Applets on different frames communicates with each otherTag(s): Javascript interaction

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
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
java.net.URL;
netscape.javascript.*;

public class InterFrameDemo extends Applet implements ActionListener {


TextField tf;
Button
b;
String
target;
public void init() {

9.11 Have Applets on different frames communicates with each otherTag(s): Javascript interaction

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 JAVAonly solution check this Java Howto

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


different pageTag(s): Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0181.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

FirstApplet.java
import java.applet.*;

9.12 Send a message from an Applet to another Applet on a different pageTag(s): Javascript interaction

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 Howto 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> '
html += '<PARAM NAME="Message" VALUE="' + theMessage + '"> '
html += '</APPLET>'
document.close()
document.open()

9.12 Send a message from an Applet to another Applet on a different pageTag(s): Javascript interaction

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 Howto.

9.13 Retrieve values from a Java applet for HTML form


(CGI)Tag(s): Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0175.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(){

9.13 Retrieve values from a Java applet for HTML form (CGI)Tag(s): Javascript interaction

document.myForm.q.value = document.myApplet.getFirstName();
return true;
}
</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.14 Detect if an Applet is readyTag(s): Javascript interaction


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0176.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>

9.14 Detect if an Applet is readyTag(s): Javascript interaction

...
<BODY onLoad="waituntilok();">
....
/BODY

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.15 Read/Write HTML field values from JAVATag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0177.html

9.15 Read/Write HTML field values from JAVATag(s): Javascript interaction

[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");

before using an JSObject related to an HTML document.


But there is a workaround, simply pass the informations through Javascript functions!
[JSjava.java]
import
import
import
import

java.applet.*;
java.awt.event.*;
java.awt.*;
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>

9.15 Read/Write HTML field values from JAVATag(s): Javascript interaction

<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
For best result, never use LiveConnect JSObject in Applet's init() method.

9.16 Detect if Java is enabledTag(s): Javascript interaction


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0178.html
from Javascript :
function isJavaAvailable(){
return ( navigator.javaEnabled &navigator.javaEnabled() );
}
For an HTML solution, check this Howto

9.17 Detect if Java 1.1 (with event delegation) is availableTag(s):


Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0179.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;

9.16 Detect if Java is enabledTag(s): Javascript interaction

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.18 Access Cookies from a Java AppletTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0180.html
This Applet uses the package netscape.javascript.JSObject.
To compile such program, you have to include in the CLASSPATH a special jar included in the JRE
installation.
For Java 1.4.2 and later: add plugin.jar to your classpath when compiling. It can be found in the lib
directory of your JRE installation, ex. C:\Program Files\Java\jre1.5.0\lib\plugin.jar
NOTE : For Java 1.4.0/1.4.1: use jaws.jar (same directory).
[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
import
import
import

netscape.javascript.*;
java.awt.*;
java.awt.event.*;
java.applet.*;

public class TestCookie extends Applet


implements ActionListener {
TextField tf1, tf2;

9.18 Access Cookies from a Java AppletTag(s): Javascript interaction

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);
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);
}
}

9.18 Access Cookies from a Java AppletTag(s): Javascript interaction

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);
}
return "";
}
}
You can try it here.

See this text file with some useful Javascript functions for cookies handling.
Check this Howto to detect if Cookies are enabled or not.

9.19 Set Applet PARAM VALUE from javascriptTag(s):


Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0182.html
9.19 Set Applet PARAM VALUE from javascriptTag(s): Javascript interaction

PARAM VALUE can't be changed ar runtime but during layout time, javascript "entities" can be
used to set calculated VALUES.
In this Howto, 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 Howto for an example.

9.20 Pass an Array between Java and JavascriptTag(s):


Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0183.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!

9.20 Pass an Array between Java and JavascriptTag(s): Javascript interaction

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 Javaside, 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]


<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();

9.20 Pass an Array between Java and JavascriptTag(s): Javascript interaction

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()
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;

9.20 Pass an Array between Java and JavascriptTag(s): Javascript interaction

}
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.21 Interaction without LiveConnectTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0184.html
JavaJavascript interaction may not be possible with old browsers or platforms.
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 document.search property). And then the parameter extracted is send to another
javascript function in the visible frame.

9.21 Interaction without LiveConnectTag(s): Javascript interaction

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;

9.21 Interaction without LiveConnectTag(s): Javascript interaction

}
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.*;
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.

9.21 Interaction without LiveConnectTag(s): Javascript interaction

First, the 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">
<INPUT TYPE=button VALUE="Send to JAVA" onClick="send2Java();">
</FORM>
<APPLET CODE=SimpleApplet2.class
WIDTH=300
HEIGHT=150>
</APPLET></BODY></HTML>

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.*;

9.21 Interaction without LiveConnectTag(s): Javascript interaction

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);
}
}

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;
}

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("?");
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.

9.21 Interaction without LiveConnectTag(s): Javascript interaction

NOTE: A Static class can be shared between Applets only if the Applets are coming from the same server and the MAYSCRIPT is not used.

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.
NOTE : With IE, you need to run this sample through a Web server.

9.22 Directory listing on the Web server in a Java AppletTag(s):


Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0185.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.22 Directory listing on the Web server in a Java AppletTag(s): Javascript interaction

</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
import
import
import
import

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

public class Selector extends Applet


implements ActionListener {
java.awt.List l;
boolean okToDisplay = false;

9.22 Directory listing on the Web server in a Java AppletTag(s): Javascript interaction

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 Howto is inspired by an article by Martin Webb on http://www.irt.org

9.23 Have a Java button close the browser windowTag(s):


Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0282.html
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
netscape.javascript.*;

public class WinClose extends Applet


implements ActionListener{
Button wc = new Button("Close me");

9.23 Have a Java button close the browser windowTag(s): Javascript interaction

public void init() {


wc.setActionCommand("CLOSE");
wc.addActionListener(this);
add(wc);
}
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.24 Detect if cookies are enabledTag(s): Javascript interaction


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0303.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'
document.write("</APPLET>");
</SCRIPT>
</BODY></HTML>

VALUE=" + cookieOk + ">");

[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")));

9.24 Detect if cookies are enabledTag(s): Javascript interaction

}
}

9.25 Display a page after all applets are loadedTag(s): Javascript


interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../jsdetails/js0071.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>

9.26 Detect browser type from an AppletTag(s):


Applet Environment Javascript interaction
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadetectbrowsertypefromanapplet.html

9.27 Call a Javascript from the Applet


With LiveConnect, we call a javascript to return the "UserAgent".

9.25 Display a page after all applets are loadedTag(s): Javascript interaction

To compile, make sure that you have the plugin.jar in the classpath (or Eclipse Build Path). This jar
is usually located in [JRE]/lib folder. During runtime, it's already included by the Java plugin so you
don't have to worry about that.
The Java class
import
import
import
import

java.applet.*;
java.awt.event.*;
java.awt.*;
netscape.javascript.*;

public class GetUserAgent extends Applet


implements ActionListener {
private static final long serialVersionUID = 1L;
TextField tf;
Button b1;
JSObject win;
public void init(){
setLayout(new FlowLayout());
tf = new TextField(35);
b1 = new Button("get useragent from javascript");
b1.addActionListener(this);
add(tf);add(b1);
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == b1) {
JSObject win = (JSObject)JSObject.getWindow(this);
tf.setText((String)win.eval("getUserAgent();"));
}
}
}

Don't forget the MAYSCRIPT parameter in the APPLET tag, it's required since the Applet is using
the JSObject to interact with the Javascript.
<html>
<head>
<script>
function getUserAgent() {
return navigator.userAgent;
}
</script>
</head><body>
<applet code="GetUserAgent.class" MAYSCRIPT height=100 width=500></Applet>
</body>
</html>

Try it here
You need to parse the returned value to detect browser type. Look at this utility,
http://code.google.com/p/useragentutils/ or at this code :
http://nerds.palmdrive.net/useragent/code.html to get the idea.

9.25 Display a page after all applets are loadedTag(s): Javascript interaction

9.28 Get the value from the serverside


When serving the HTML containing the Applet, you add the UserAgent as parameter for the
Applet.
In a JSP/EL
<applet ... >
<param ... >
<param name="userAgent" value="${header['useragent']}" />
</applet>

and in the Applet


String userAgent = getParameter("userAgent");

and parse the returned value...

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

9.28 Get the value from the serverside

10 Servlet/JSP
10.1 javajsp

10.2 Read meTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0379.html
You may to take a look to these related Howto's in the EAServer/Jaguar section.

10.3 Get parameters passed to a servletTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0357.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);
}
}

10 Servlet/JSP

10.4 Detect no argument condition in a ServletTag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0341.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>");
}
}

10.4 Detect no argument condition in a ServletTag(s): Servlet/JSP

10.5 Set a Cookie from a servletTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0358.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);
}
}

10.6 Read a Cookie from a servletTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0359.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);
}

10.5 Set a Cookie from a servletTag(s): Servlet/JSP

10.7 Delete (or expire) a Cookie from a servletTag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0360.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.setMaxAge( 300 );
// Expire after the browser is closed
// cookie.setMaxAge( 1 );
// Expire right now
// cookie.setMaxAge( 0 );
}
public void doGet(HttpServletRequest req, HttpServletResponse res) {
doPost(req, res);
}
}

10.8 Ask for a password from a ServletTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0342.html
public void askPassword(HttpServletResponse response) {
response.setStatus(response.SC_UNAUTHORIZED);
response.setHeader("WWWAuthenticate",
"BASIC realm=\"protectedarea\"");

10.7 Delete (or expire) a Cookie from a servletTag(s): Servlet/JSP

then the browser will popup a dialog for username/password

10.9 Talk to a CGI/ServletTag(s): Networking Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0082.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/cgibin/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
3letter 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/cgibin/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/cgibin/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("contenttype","application/xwwwformurlencoded");
DataOutputStream out = new DataOutputStream(c.getOutputStream());
out.writeBytes(encoded);
out.flush(); out.close();
BufferedReader in =
new BufferedReader(new InputStreamReader(c.getInputStream());
String aLine;

10.9 Talk to a CGI/ServletTag(s): Networking Servlet/JSP

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.10 Test for CookiesTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0374.html
import javax.servlet.*;
import javax.servlet.http.*;
public class Test4Cookies extends HttpServlet {
private
private
private
private

static
static
static
static

final
final
final
final

Cookie
String
String
String

cookie = new Cookie( "hello" , "world" );


paramName = "foo";
successURI = "/success.htm";
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 ServletTag(s):


JDBC Servlet/JSP
Current version of this HowTo :
10.10 Test for CookiesTag(s): Servlet/JSP

http://www.rgagnon.com/javadetails/../javadetails/java0378.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;
}

10.12 Specify the filename to be used for a file sent by a


ServletTag(s): Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0387.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("Contentlength",Integer.toString(textFile.length()));
response.setHeader("Contenttype","application/octetstream");
response.setHeader("Contentdisposition","inline; filename=" + filename );
// open the file and write it in the OutputStream
NOTE: For PDF output, see this HowTo

10.12 Specify the filename to be used for a file sent by a ServletTag(s): Servlet/JSP

10.13 Pass information to another servlet/jspTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0401.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


RequestDispatcher dispatch = request.getRequestDispatcher("next.jsp");
dispatch.forward(request, response);

10.14 Handle PDF outputTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0404.html
Set the contenttype 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 contenttypes, so you need to give it a hint, and the ".pdf" extension is
an easy way.
Set the "contentlength" 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("ContentDisposition", "inline;filename=somepdf.pdf");

10.13 Pass information to another servlet/jspTag(s): Servlet/JSP

10.15 Detect if the connection is via a secure channelTag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0415.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

10.16 In a Servlet, check if Form Field is presentTag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0443.html
public isDefined(HttpServletRequest req, String fieldNameToSearchFor) {
return req.getParameterMap().containsKey(fieldNameToSearchFor);
}

10.17 Get the root dir of a web appTag(s):


Servlet/JSP Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0519.html
In a JSP
String path = application.getRealPath("/");

In a Servlet
String path = getServletContext.getRealPath("/");

10.15 Detect if the connection is via a secure channelTag(s): Servlet/JSP

10.18 Get client IP address from JSPTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0363.html
<%
out.print( request.getRemoteAddr() );
out.print( request.getRemoteHost() );
%>

You may not get the real client IP if a the client is behind a proxy, you will get the IP of the proxy
and not the client. However, the proxy may include the requesting client IP in a special HTTP
header.
<%
out.print( request.getHeader("xforwardedfor") );
%>

10.19 Output a binary stream from a JSPTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0366.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.
Having said that, since a JSP will be converted to a servlet, it's possible to modifed the output
stream.
You must be careful to format your JSP to emit no whitespace
[image.jsp]
<%@ page import="java.io.*" %>
<%@ page import="java.net.*" %>

10.18 Get client IP address from JSPTag(s): Servlet/JSP

<%@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.

There is a trimWhiteSpaces directive that should help to remove the whitespaces form the
generated JSP.
In your JSP code :
<%@ page trimDirectiveWhitespaces="true" %>

Or in the jspconfig section your web.xml


<jspconfig>
<jsppropertygroup>
<urlpattern>*.jsp</urlpattern>
<trimdirectivewhitespaces>true</trimdirectivewhitespaces>
</jsppropertygroup>
</jspconfig>

If you really have a required space in the generated JSP then you need use the HTML
nonbreaking space entity : &nbsp; .

10.20 Use a connection cache from JSPTag(s):


Servlet/JSP Jaguar/EAServer
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0380.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 ODBCJDBC provided by Sun. But performance of such a bridge is poor and the reliability is not good in a
multithreaded environment.

To define a cache using ODBCJDBC (bridge) connection, follow these steps:

10.20 Use a connection cache from JSPTag(s): Servlet/JSP Jaguar/EAServer

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 cachebyname 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 =
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 hardcoding 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
}

10.20 Use a connection cache from JSPTag(s): Servlet/JSP Jaguar/EAServer

10.21 Read a Web Application propertyTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0381.html
Web Application properties are defined in the WEBINF/web.xml deployment descriptor (in between
the <webapp> </webapp> tag)
<enventry>
<enventryname>docPath</enventryname>
<enventryvalue>c:/doc/doc1</enventryvalue>
<enventrytype>java.lang.String</enventrytype>
</enventry>
<enventry>
<enventryname>docUser</enventryname>
<enventryvalue>net1</enventryvalue>
<enventrytype>java.lang.String</enventrytype>
</enventry>

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 JSPTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0396.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.21 Read a Web Application propertyTag(s): Servlet/JSP

10.23 Define a method in a JSP pageTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0410.html
<%!
public String sayHello(){
return "Hello";
}
%>

<%= sayHello() %>

10.24 Precompile JSP pagesTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0414.html
Some JSP containers (as per section 8.4.2 of the JSP 1.2 specification) support the capability of
precompiling a JSP page.
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
page
page
page

contentType="text/html;charset=UTF8" language="java" %>


import="javax.servlet.*"%>
import="javax.servlet.http.*,javax.servlet.jsp.*"%>
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);

10.23 Define a method in a JSP pageTag(s): Servlet/JSP

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.25 Get a list of directories for JSPTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0417.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++) {

10.25 Get a list of directories for JSPTag(s): Servlet/JSP

file = new java.io.File(root + list[i]);


if (file.isDirectory()) {
%>
<li><a href="javadoc/<%=list[i]%>" target="_top"><%=list[i]%></a><br>
<%
}
}
}
%>
</ul>

10.26 Use and share a class in JSP pages Tag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0508.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 WEBINF/class directory.
<%
Hello h = new Hello();
out.print(h.say());
%>

Create a JAR file containing the .class file(s) and deploy the resulting JAR file via your webapp's
WEBINF/lib directory.
<%
Hello h = new Hello();
out.print(h.say());
%>

Create a tag library for it, deploy it via the webapp's WEBINF/tld directory.
TAG source code
TAG source code :
package test;
import java.io.*;

10.26 Use and share a class in JSP pages Tag(s): Servlet/JSP

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 WEBINF/class directory.


TLD configuration (in the WEBINF/tlds as hello.tld)
<taglib>
<tag>
<name>hello</name>
<tagclass>test.HelloTag</tagclass>
</tag>
</taglib>

and to use the tag


<%@ taglib prefix="ht" uri="WEBINF/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" %>

10.27 Get the root dir of a web appTag(s):


Servlet/JSP Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0519.html
In a JSP
String path = application.getRealPath("/");

10.27 Get the root dir of a web appTag(s): Servlet/JSP Servlet/JSP

In a Servlet
String path = getServletContext.getRealPath("/");

10.28 Launch an applet from a JSPTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0534.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>

10.29 Prevent caching of a JSP outputTag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0590.html
You will need to set the appropriate HTTP header attributes.
<%
response.setHeader("CacheControl","nocache");
response.setHeader("Pragma","nocache");
response.setDateHeader ("Expires", 1);
%>

However, cache handling is tricky with IE brower.


See http://support.microsoft.com/kb/q222064/.

10.28 Launch an applet from a JSPTag(s): Servlet/JSP

By adding a second HEAD is supposed to solve the problem!


<%
response.setHeader("CacheControl","nocache");
response.setHeader("Pragma","nocache");
response.setDateHeader ("Expires", 1);
%>
<HTML>
<HEAD>
</HEAD>
<BODY>
my page body
</BODY>
<HEAD>
<META HTTPEQUIV="PRAGMA" CONTENT="NOCACHE">
<META HTTPEQUIV="Expires" CONTENT="1">
</HEAD>
</HTML>

NOTE: Pragma: nocache 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 Launch an external program, capture its output and


display it in a JSPTag(s): Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0648.html
In this HowTo, the Windows utility NET is executed to get the members of a given group. The
JSP captures the output and to display it as Web page.
<H1>Members of the <%=request.getParameter("group")%> group</H1>
<%
String cmdline = "net group " + request.getParameter("group") + " /domain";
out.println("<pre>");
try {
String line;
Process p = Runtime.getRuntime().exec(cmdline);
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
out.println(line);
}
input.close();
}
catch (Exception err) {

10.30 Launch an external program, capture its output and display it in a JSPTag(s): Servlet/JSP

err.printStackTrace();
}
out.println("</pre>");
%>

The next example calls a VBSCRIPT to list the Windows groups for a specific user.
the VBS (listmembergroups.vbs)
Option Explicit
Dim objNetwork, strDomain, strUser, objUser, objGroup, strGroupMemberships
Set objUser = GetObject("WinNT://ssqvie/" &WScript.Arguments.item(0))
wscript.echo "<H2>" &objUser.Fullname &"</H2>"
For Each objGroup In objUser.Groups
wscript.echo objGroup.Name
Next

The JSP (http://myserver.local/myapp/listgroups.jsp?user=scott)

<H1> User <%=request.getParameter("user")%></H1>


<%
String cmdline = "cscript.exe //NoLogo \\\\myscripts_dir\\listmembergroups.vbs " + request.ge
out.println("<pre>");
String line;
java.util.ArrayList<String> list = new java.util.ArrayList<String>();
try {
Process p = Runtime.getRuntime().exec(cmdline);
BufferedReader input =
new BufferedReader
(new InputStreamReader(p.getInputStream(), "Cp850"));
while ((line = input.readLine()) != null) {
list.add(line);
}
input.close();
}
catch (Exception err) {
out.println(err);
}
java.util.Collections.sort(list);
for (String item:list) {
out.println(item);
}
out.println("</pre>");
%>

As always, special care must be taken if there is a risk that the called program can write
something into stderr (then the process will hang forever).

10.30 Launch an external program, capture its output and display it in a JSPTag(s): Servlet/JSP

10.31 Call another EJBTag(s): Servlet/JSP Jaguar/EAServer


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0384.html
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("MyPackage/MyEJB");
MyEJBHome home = (MyEJBHome)
PortableRemoteObject.narrow(objref, MyEJBHome.class);
return (MyEJB) home.create();

10.32 Keep java files generated from JSP (BEA WLS)Tag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0446.html
Set the 'keepgenerated' parameter in weblogic.xml to 'true'
<jspdescriptor>
<jspparam>
<paramname>keepgenerated</paramname>
<paramvalue>true</paramvalue>
</jspparam>
<jspparam>
<paramname>workingdir</paramname>
<paramvalue>c:/bea10/user_projects/domains/mydomain/tmp</paramvalue>
</jspparam>
</jspdescriptor>
Thanks to jimbo for the tip!

10.33 Get the server version (BEA WLS)Tag(s): Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0447.html
<%@page import = "weblogic.common.internal.VersionInfo"%>
...
<%VersionInfo serverVersion = VersionInfo.theOne();%>
...
%=serverVersion.getImplementationVersion()%

10.31 Call another EJBTag(s): Servlet/JSP Jaguar/EAServer

or from the command line


java cp weblogic.jar weblogic.version
Thanks to Frederic Close for the tip!

10.34 Quickly create a Web application with BEA WLSTag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0449.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
3. Type this command : md testapp
4. Type this command : md testapp\WEBINF
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

10.35 Nicely display WEB.XML informationsTag(s):


Servlet/JSP XML Jaguar/EAServer
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0451.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 :
10.34 Quickly create a Web application with BEA WLSTag(s): Servlet/JSP

<?xml version="1.0" encoding="UTF8"?>


<?xmlstylesheet type="text/xsl" href="treeview.xsl"?>
...

or do the transformation in Java, for a hint see this Howto.


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 httpequiv="ContentType" content="text/html; charset=ISO88591">
<%@ 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/treeview2.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 );
}

10.34 Quickly create a Web application with BEA WLSTag(s): Servlet/JSP

10.36 Reverse the CLASSLOADER order (BEA)Tag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0551.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 WEBINF\LIB, create a file called
weblogic.xml in the WEBINF directory with the content :
<!DOCTYPE weblogicwebapp PUBLIC
"//BEA Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810webjar.dtd">
<weblogicwebapp>
<containerdescriptor>
<preferwebinfclasses>true</preferwebinfclasses>
</containerdescriptor>
</weblogicwebapp>

Another technique is to use a FilteringClassLoader.


The FilteringClassLoader provides a mechanism for you to configure deployment descriptors to
explicitly specify that certain packages should always be loaded from the application, rather than
being loaded by the system classloader.
To configure the FilteringClassLoader to specify how a certain package is to be loaded, add a
preferapplicationpackages descriptor element to the weblogicapplication.xml
The following example specifies that org.apache.log4j.* is loaded from the application, not the
system classloader:
<preferapplicationpackages>
<packagename>org.apache.log4j.*</packagename>
</preferapplicationpackages>

ref :
http://download.oracle.com/docs/cd/E11035_01/wls100/programming/classloading.html#wp1097187

10.36 Reverse the CLASSLOADER order (BEA)Tag(s): Servlet/JSP

10.37 Detect change in JSP and recompile (BEA)Tag(s):


Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0562.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.
<jspdescriptor>
<jspparam>
<paramname>pagecheckseconds</paramname>
<paramvalue>60</paramvalue>
</jspparam>
</jspdescriptor>

pagecheckseconds 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.

10.38 Obtain a remote connection to a DataSource or EJB


(Weblogic)Tag(s): Servlet/JSP
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0664.html
It's possible to obtain a remote connection to a Datasource defined in the application server. In
this example, the connection is made to a Weblogic server so you need wlclient.jar in the
classpath.
import
import
import
import
import

java.sql.*;
java.util.Properties;
javax.naming.InitialContext;
javax.rmi.PortableRemoteObject;
javax.sql.DataSource;

public class RemoteConnection {


private RemoteConnection() { }

10.37 Detect change in JSP and recompile (BEA)Tag(s): Servlet/JSP

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


Properties env = new Properties();
String datasourceName = "mydatasourcename";
env.put("java.naming.factory.initial",
"weblogic.jndi.WLInitialContextFactory");
env.put("java.naming.provider.url",
"t3://xxxxxxxxxxxxx.xxx.xxxxx:7101");
InitialContext ctxProxy = new InitialContext(env);
Object dsObj = ctxProxy.lookup(datasourceName);
DataSource ds = (DataSource) PortableRemoteObject.narrow(dsObj,
javax.sql.DataSource.class);
PreparedStatement ps = null;
Connection conn = null;
ResultSet result = null;
try {
conn = ds.getConnection();
String SelectString = "SELECT NAME, ADDRESS FROM EMPLOYEE";
ps = conn.prepareStatement(SelectString);
for (result = ps.executeQuery(); result.next();) {
String data = result.getString(1) + " : " + result.getString(2);
System.out.println(data);
}
}
catch (Exception ex) {
ex.printStackTrace();
}
finally {
result.close();
ps.close();
conn.close();
conn = null;
ps = null;
result = null;
}
}
}

The next example, make a remote call to an EJB host in a Weblogic server. You need wlclient
and the EJB client jars in the classpath.
import
import
import
import

java.util.Properties;
javax.naming.InitialContext;
javax.rmi.PortableRemoteObject;
com.company.common.myejb.*;

public class RemoteEJBCall {


private RemoteEJBCall() {

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


Properties env = new Properties();
env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
env.put(javax.naming.Context.PROVIDER_URL,
"t3://xxxxxxxxxxxxx.xxx.xxxxx:7101");
InitialContext ctx = new InitialContext(env);
Object obj = ctx.lookup("common/MyEJB");
MyEJBHome home = (((MyEJBHome) PortableRemoteObject
.narrow(obj, MyEJBHome.class)));
MyEJB myEJB = home.create();
System.out.println(myEJB.doit());

10.37 Detect change in JSP and recompile (BEA)Tag(s): Servlet/JSP

}
}

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

10.37 Detect change in JSP and recompile (BEA)Tag(s): Servlet/JSP

11 Language
11.1 javalanguage

11.2 * Read me *Tag(s): Language String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0290.html
If you have difficulty to find what you are your are looking for, try do use search on this site using
Google.
Enter your search terms
www.rgagnon.com

Web

Submit search form


If you can't find then you may want to look at these other sites :
Java Glossary
Many subjects covered in depth.
The Java Developers Almanac 1.4 (exampledepot.com)
Contains many code examples.
Sun Developers Online Community
You need to register first (free). Be sure to search the forums first before asking a question because
regular posters can be a little bit rude if you don't!
Stack Overflow
A site where you can ask question (not restricted to Java), really innovative in the way it works.
Participants are really cool.
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

11 Language

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.3 Obtain from where a Class is loadedTag(s): Language Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0300.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[]){

11.3 Obtain from where a Class is loadedTag(s): Language Varia

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

11.4 Get the class name in a static methodTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0402.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();
}
}
}

The hardcoded way


package com.rgagnon.howto;
public class Test {
public static void main(String[] args) throws Exception {
System.out.println (Test.class.getSimpleName());
System.out.println (Test.class.getCanonicalName());
System.out.println (Test.class.getName());
/*
output :
Test
com.rgagnon.howto.Test
com.rgagnon.howto.Test
*/
}
}

11.4 Get the class name in a static methodTag(s): Language

11.5 Get the current method nameTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0420.html

11.6 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

11.7 JDK1.5
While the above snippet is not bad, it is expensive since we need to create an Exception.
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");

11.5 Get the current method nameTag(s): Language

}
}
}
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()[2].getMethodName()); // output : main
}
}

See also this HowTo.

11.8 Call a method dynamically (Reflection)Tag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0031.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);
// 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());
}

11.8 Call a method dynamically (Reflection)Tag(s): Language

/* 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);
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) {

11.8 Call a method dynamically (Reflection)Tag(s): Language

System.out.println(s1 + " " + s2);


}
}

11.9 Detect if a package is availableTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0422.html
public class ClassUtils {
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");
}
}

11.9 Detect if a package is availableTag(s): Language

11.10 Create an object from a stringTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0351.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[] { };
// 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);
}

11.10 Create an object from a stringTag(s): Language

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

11.11 Get a variable value from the variable nameTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0038.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
public int
public String
}

{
firstValue = 3.1416;
secondValue = 42;
thirdValue = "Hello world";

11.11 Get a variable value from the variable nameTag(s): Language

11.12 Make methods that have unspecified number of


parametersTag(s): Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0289.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);
}
}
/*
output :
>java TestIt 1 2 3 howto
1

11.12 Make methods that have unspecified number of parametersTag(s): Language

2
3
howto
*/
}

11.13 Create a java source dynamically, compile and callTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0039.html

11.14 Java 1.6


Java 1.6 provides ToolProvider.getSystemJavaCompiler() to get a JavaCompiler implementation.
This example creates an Hello class source, compiles it and calls a given method.
import java.io.*;
import java.lang.reflect.Method;
import java.util.Arrays;
import
import
import
import

javax.tools.JavaCompiler;
javax.tools.StandardJavaFileManager;
javax.tools.StandardLocation;
javax.tools.ToolProvider;

public class DynamicCompilation {


public static void main(String[] args) throws Exception {
// create the source
File sourceFile
= new File("/temp/Hello.java");
FileWriter writer = new FileWriter(sourceFile);
writer.write(
"public class Hello{ \n" +
" public void doit() { \n" +
"
System.out.println(\"Hello world\") ;\n" +
" }\n" +
"}"
);
writer.close();
JavaCompiler compiler
= ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager =
compiler.getStandardFileManager(null, null, null);
fileManager.setLocation(StandardLocation.CLASS_OUTPUT,
Arrays.asList(new File("/temp")));
// Compile the file
compiler.getTask(null,
fileManager,

11.13 Create a java source dynamically, compile and callTag(s): Language

null,
null,
null,
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile)))
.call();
fileManager.close();

// delete the source file


// sourceFile.deleteOnExit();
runIt();
}
@SuppressWarnings("unchecked")
public static void runIt() {
try {
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName("Hello");
Object iClass = thisClass.newInstance();
Method thisMethod = thisClass.getDeclaredMethod("doit", params);
thisMethod.invoke(iClass, paramsObj);
}
catch (Exception e) {
e.printStackTrace();
}
}
}

The tools.jar (located in the [JDK1.6]\lib) must be in the classpath during runtime, it is not included
with the JRE.
You can compile many sources in one shot.
The directory used to store the resulting class must be in the classpath if you want to use
compiled class. In Eclipse, you add the directory in the Build Path (as an External Class Folder).

11.15 Java 1.5 or less


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 {
System.out.println(mtc.todaySource + " is bad.");
}
}
public void createIt() {

11.15 Java 1.5 or less

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.16 Launch an application from another applicationTag(s):


IO Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0394.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");

11.16 Launch an application from another applicationTag(s): IO Language

}
}

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 hardcoded.


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();

11.16 Launch an application from another applicationTag(s): IO Language

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.17 Access the enclosing class from an inner classTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0037.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(){
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 :

11.17 Access the enclosing class from an inner classTag(s): Language

Hello world!
*/
}
public void doit() {
new InnerClass().sayHello();
}
public void enclosingClassMethod(){
System.out.println("Hello world!");
}
class InnerClass {
public void sayHello() {
testItClass.enclosingClassMethod();
}
}
}

11.18 Access inner class from outsideTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0425.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.18 Access inner class from outsideTag(s): Language

11.19 Use globally defined constantsTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0040.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
public static final
public static final
}

{
integer SUCCESS = 1;
integer FAILURE = 1;
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 applicationlevel class needs to implement the
interface to be able to see the constant definitions.
public interface APPCONSTANT
public static final String
public static final String
public static final String
}

{
APPNAME = "The Super APP";
APPVERSION = "version 1.0";
DBDRIVER = "oracle.jdbc.driver.OracleDriver";

then to use a constant, simply implement the interface


public class TheAppFrame extends Frame
implements APPCONSTANT {
TheAppFrame {
...
setTitle(APPNAME);
...
}
...
}

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.
11.19 Use globally defined constantsTag(s): Language

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);
}
}

11.20 Serialize an ObjectTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0042.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 {
/*
** FIFO
*/
Queue() {
super();
}
void put(Object o) {
addElement(o);
}
Object get() {
if (isEmpty()) return null;

11.20 Serialize an ObjectTag(s): Language

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 Howto to serialize using XML format.


If you need to serialize and manipulate huge objects, take a look at this opensource project.
joafip( java data object persistence in file ) at http://joafip.sourceforge.net.

11.20 Serialize an ObjectTag(s): Language

11.21 Serialize an Object over a socketTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0043.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 resending the object or open a new connection each time.

11.22 Easily remove my debugging codeTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0130.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:
11.21 Serialize an Object over a socketTag(s): Language

public class Debug {


public static final boolean RELEASE = false;
}

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.23 Have a singletonTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0355.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; }
}

To use it
OnlyOne myOne = OnlyOne.getInstance();

11.24 Multiple expressions in for loopsTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0316.html
11.23 Have a singletonTag(s): Language

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.25 Handle the List conflictTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0372.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();
...

11.26 Use a generic toString()Tag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0432.html
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class ClassUtils {
private ClassUtils() {}
public static String toString( Object o ) {
ArrayList list = new ArrayList();
ClassUtils.toString( o, o.getClass(), list );

11.25 Handle the List conflictTag(s): Language

return o.getClass().getName().concat( list.toString() );


}
private static void toString( Object o, Class clazz, List 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 ) {
toString( o, clazz.getSuperclass(), list );
}
}
}

To use it :
public class ClassUtilsTest {
String hello = "world";
int i = 42;
public static void main(String ... args) {
System.out.println(ClassUtils.toString(new ClassUtilsTest()));
// ClassUtilsTest[hello=world, i=42]
}
}

The generic toString() dumps the overrided values too :


public class ClassUtilsTest2 extends ClassUtilsTest {
String hello="fubar";
double d = Math.PI;
public static void main(String ... args) {
System.out.println(ClassUtils.toString(new ClassUtilsTest2()));
// ClassUtilsTest2[hello=fubar, d=3.141592653589793, hello=world, i=42]
}
}

Andres Santana wrote :


I saw this article (use a generic toString()) and I might have another solution for it using
/**
* Print all properties for a given bean. It's useful for overwriting
* toString method.
*
* @param bean
*
Object to get all properties from.
* @param showNulls
*
Determine if you wether you want to show null properties or
*
not.
* @return String representing bean state.
* @author andres santana
*/

11.25 Handle the List conflictTag(s): Language

public static String showBean(Object bean, boolean showNulls) {


if (bean == null) return null;
StringBuilder sb =
new StringBuilder(bean.getClass().getName()).append("[");
try {
BeanInfo bi = Introspector.getBeanInfo(bean.getClass());
PropertyDescriptor[] pd = bi.getPropertyDescriptors();
for (int i = 0; i < pd.length; i++) {
if (!"class".equals(pd[i].getName())) {
Object result = pd[i].getReadMethod().invoke(bean);
if (showNulls || result != null) {
sb.append(pd[i].getDisplayName()).append("=").append(result);
if (i == pd.length 1) continue;
sb.append(",");
}
}
}
}
catch (Exception ex) { }
return sb.append("]").toString();
}

11.27 Use Object.clone()Tag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0433.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();

11.27 Use Object.clone()Tag(s): Language

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
// 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
}
}

11.28 Static field, constructor and exceptionTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0444.html

11.28 Static field, constructor and exceptionTag(s): Language

Consider the following class


public class Foo {
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 {
}
}

11.29 Use a Label breakTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0500.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;

11.29 Use a Label breakTag(s): Language

j += 1;
}
}
System.out.println(j); // output 5
}
}

11.30 Put printStackTrace() into a StringTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0537.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.

11.30 Put printStackTrace() into a StringTag(s): Language

11.31 Iterate enum valuesTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0655.html
public class EnumTest {
enum Simpsons {
HOMER ("Homer"),
MADGE ("Marge"),
MAGGIE ("Maggie"),
BART ("Bart"),
LISA ("Lisa");
private String name;
Simpsons(String name) { this.name = name; }
public String getName() { return name; }
}
public static void main (String ... args) {
for (Simpsons member : Simpsons.values()) {
System.out.println(member.getName());
}
}
}
/*
output :
Homer
Marge
Maggie
Bart
Lisa
*/

11.32 Get fields and values from an Object Tag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javagetfieldsandvaluesfromanobject.html
Take this Dummy Class.
public class Dummy {
public String value1 = "foo";
public int value2 = 42;
public Integer value3 = new Integer(43);
private String value4 = "bar";

11.31 Iterate enum valuesTag(s): Language

We want to list the fields and the values of an instance.


import
import
import
import

java.lang.reflect.Field;
java.lang.reflect.Modifier;
java.util.HashMap;
java.util.Map;

public class ObjectUtils {


private ObjectUtils() {}

public static Map<String, Object> getFieldNamesAndValues(final Object obj, boolean publicOn


throws IllegalArgumentException,IllegalAccessException
{
Class<? extends Object> c1 = obj.getClass();
Map<String, Object> map = new HashMap<String, Object>();
Field[] fields = c1.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
String name = fields[i].getName();
if (publicOnly) {
if(Modifier.isPublic(fields[i].getModifiers())) {
Object value = fields[i].get(obj);
map.put(name, value);
}
}
else {
fields[i].setAccessible(true);
Object value = fields[i].get(obj);
map.put(name, value);
}
}
return map;
}
/**
* @param args
*/
public static void main(String[] args) throws Exception {
Dummy dummy = new Dummy();
System.out.println(ObjectUtils.getFieldNamesAndValues(dummy,true));
System.out.println(ObjectUtils.getFieldNamesAndValues(dummy,false));
/*
* output :
* {value3=43, value1=foo, value2=42}
* {value3=43, value4=bar, value1=foo, value2=42}
*/
}
}

11.31 Iterate enum valuesTag(s): Language

11.33 Use a HashtableTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0027.html
Hashtables are very useful for maintaining a 1to1 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.34 Scan the content of a hashtableTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0032.html
Enumeration keys = hash.keys();
while( keys.hasMoreElements() ) {
Object key = keys.nextElement();
Object value = hash.get(key);
}

11.35 Sort an arrayTag(s): Language Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0008.html
[ArraySorter.java] JDK1.1
public class ArraySorter {
/*
** Sort in the same array

11.33 Use a HashtableTag(s): Language

*/
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]) >
i++;
while( (j > from) &(comparer.compare(center, a[j]) <
j;
}
else {
// Decending sort
while( (i < to) &(comparer.compare( center, a[i]) <
i++;
while( (j > from) &(comparer.compare(center, a[j]) >
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);
}

0) )
0) )

0) )
0) )

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)

11.33 Use a HashtableTag(s): Language

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 casesensitive
String[] myArray = new String[] {"foo","bar","baz"};
java.util.Arrays.sort(myArray);

caseinsensitive
String[] myArray = new String[] {"foo","Bar","baz"};
java.util.Arrays.sort(myArray, java.text.Collator.getInstance());

11.36 Initialize multidimensional arrayTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0036.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.36 Initialize multidimensional arrayTag(s): Language

11.37 Get array upperboundTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0280.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 );
}
}

11.38 Convert a String to an array or an array to a stringTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0368.html

11.38.1 String to Array


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.
public String[] stringtoArray( String s, String sep ) {
// convert a String s to an Array, the elements
// are delimited by sep
// NOTE : for old JDK only (<1.4).
//
for JDK 1.4 +, use String.split() instead
StringBuffer buf = new StringBuffer(s);
int arraysize = 1;

11.37 Get array upperboundTag(s): Language

for ( int i = 0; i < buf.length(); i++ ) {


if ( sep.indexOf(buf.charAt(i) ) != 1 )
arraysize++;
}
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;
}
Thanks to T. GUIRADO

11.38.2 Array to String


The StringBuffer approach :
public class StringUtils {
private StringUtils() {}
public static String arrayToString(String[] a, String separator) {
if (a == null || separator == null) {
return null;
}
StringBuffer result = new StringBuffer();
if (a.length > 0) {
result.append(a[0]);
for (int i=1; i < a.length; i++) {
result.append(separator);
result.append(a[i]);
}
}
return result.toString();
}
public static void main(String args[]) throws Exception {
System.out.println(
StringUtils.arrayToString(new String[] { "a" , "b", "c" } ,
);
}
}

11.38.2 Array to String

",")

The StringBuilder approach (JDK1.5):


public class StringUtils {
private StringUtils() {}
public static String arrayToString(String[] a, String separator) {
if (a == null || separator == null) {
return null;
}
StringBuilder result = new StringBuilder();
if (a.length > 0) {
result.append(a[0]);
for (int i=1; i < a.length; i++) {
result.append(separator);
result.append(a[i]);
}
}
return result.toString();
}
public static void main(String args[]) throws Exception {
System.out.println(
StringUtils.arrayToString(new String[] { "a" , "b", "c" } ,
);
}

",")

Where possible, it is recommended that StringBuilder be used in preference to StringBuffer as it


will be faster under most implementations.
Instances of StringBuilder are not safe for use by multiple threads. If such synchronization is
required then it is recommended that StringBuffer be used.

11.39 Sort in reverse orderTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0428.html
Arrays.sort (myArray, Collections.reverseOrder());

11.40 Resize an arrayTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0431.html

11.39 Sort in reverse orderTag(s): Language

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);
}
public void doit2() {
// multi dimensions
ArrayList list = new ArrayList();
ArrayList l1 = new ArrayList();
l1.add("a");
ArrayList l2 = new ArrayList();

11.39 Sort in reverse orderTag(s): Language

// a

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();
System.out.println("Array 2 "
+ ((ArrayList)list.get(1)).get(0));
// b
}

// 1

11.41 Dump array contentTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0465.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
mutidimensional 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
// [a, b, c, d]
// [[0.5, 0.7, 0.4, 0.6], [0.5, 1.1, 0.5, 0.8]]
}
}

11.41 Dump array contentTag(s): Language

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);
}
}

11.42 Initialize a static arrayTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0475.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]);
}
}
}

11.43 Sort an HashtableTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0478.html
Data in hashtable are not sorted. We extract the keys and sort them.

11.42 Initialize a static arrayTag(s): Language

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 to sort an HashMap.
See this Howto to sort a Properties.

11.42 Initialize a static arrayTag(s): Language

11.44 Eliminate "[unchecked] unchecked call ..." compiler


warning Tag(s): Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0521.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.44 Eliminate "[unchecked] unchecked call ..." compiler warning Tag(s): Language

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.

11.44 Eliminate "[unchecked] unchecked call ..." compiler warning Tag(s): Language

12 ANT
When compiling with ANT, you see the following output :
[javac] Note: Some input files use unchecked or unsafe operations.
[javac] Note: Recompile with Xlint:unchecked for details.

but it's not easy to see the details of those unsafe operations. To add the Xlint, you need to use
the compilerarg tag in the javac task definition.
Something like
<target name="compile" description="Compile code">
<mkdir dir="${bin}"/>
<mkdir dir="${lib}"/>
<javac srcdir="${src}" destdir="${bin}"
includeAntRuntime="no"
classpathref="lib.path"
debug="${compile.debug}">
<compilerarg value="Xlint:unchecked"/>
</javac>
</target>

12.1 Sort on many fieldsTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0520.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;
}
public String toString() {
return "[ firstname=" + firstName + ",lastname=" + lastName + "]";
}

12 ANT

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
import
import
import
import

java.util.ArrayList;
java.util.Arrays;
java.util.Collections;
java.util.List;
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);
}
// do the simpsons
for(int i = 0 ; i < Simpsons.length ; i ++) {
Person one = new Person(Simpsons[i],"Simpsons");
names.add(one);

12 ANT

}
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]
*/
}
}

12.2 Optimize Collection usageTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0553.html
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 warandpeace.txt and then count the duplicated
words. as you can see depending on the Collection used, the execution time is very different!
12.2 Optimize Collection usageTag(s): Language

import java.util.*;
import java.io.*;
class TestCollectionPerformance {
private static String TEXT_BOOK_NAME = "warandpeace.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
522396
522396
522396

duplicated
duplicated
duplicated
duplicated

words.
words.
words.
words.

Using
Using
Using
Using

java.util.HashSet, time = 453ms.


java.util.TreeSet, time = 1031ms.
java.util.ArrayList, time = 100937ms.
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.
12.2 Optimize Collection usageTag(s): Language

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

12.3 Sort an HashMapTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0561.html
Sort based on the keys
Map yourMap= new HashMap();
// put some tuples in yourMap ...
Map sortedMap = new TreeMap(yourMap);

To sort only the keys :


import
import
import
import
import

java.util.HashMap;
java.util.Iterator;
java.util.Map;
java.util.SortedSet;
java.util.TreeSet;

...
Map<String,java.io.File> theSimpsons = new HashMap<String,java.io.File>();
theSimpsons.put("Bart", new java.io.File("Bart.jpg"));
theSimpsons.put("Lisa", new java.io.File("Lisa.jpg"));
theSimpsons.put("Marge", new java.io.File("Marge.jpg"));
theSimpsons.put("Barney", new java.io.File("Barney.jpg"));
theSimpsons.put("Homer", new java.io.File("Homer.jpg"));
theSimpsons.put("Maggie", new java.io.File("Maggie.jpg"));
SortedSet<String> sortedset= new TreeSet<String>(theSimpsons.keySet());
Iterator<String> it = sortedset.iterator();
while (it.hasNext()) {
System.out.println (it.next());
}
...

Sort based on the values


HashMap yourMap = new HashMap();

12.3 Sort an HashMapTag(s): Language

// 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();
}

12.4 Get keys corresponding to a value from a MapTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0564.html
This method returns a List of the keys corresponding to a given value.
[Java 5]
import
import
import
import

java.util.ArrayList;
java.util.HashMap;
java.util.List;
java.util.Map;

public class MapUtils {


private MapUtils() {}
public static List<Object> getKeysFromValue(Map<?, ?> hm, Object value){
List <Object>list = new ArrayList<Object>();
for(Object o:hm.keySet()){
if(hm.get(o).equals(value)) {
list.add(o);
}

12.4 Get keys corresponding to a value from a MapTag(s): Language

}
return list;
}

public static void main(String[] argv) {


Map<String, String> map = new HashMap<String, String>();
map.put("1","Homer");
map.put("2","Marge");
map.put("3","Bart");
map.put("4","Maggie");
map.put("5","Bart");
System.out.println(MapUtils.getKeysFromValue(map,"Bart"));
}
}

[Java 1.4]
import
import
import
import
import
import

java.util.ArrayList;
java.util.HashMap;
java.util.Iterator;
java.util.List;
java.util.Map;
java.util.Set;

public class MapUtils {


private MapUtils() {}
public static List getKeysFromValue(Map hm,Object value){
Set ref = hm.keySet();
Iterator it = ref.iterator();
List list = new ArrayList();
while (it.hasNext()) {
Object o = it.next();
if(hm.get(o).equals(value)) {
list.add(o);
}
}
return list;
}
public static void main(String[] args) {
Map map = new HashMap();
map.put("1","Homer");
map.put("2","Marge");
map.put("3","Bart");
map.put("4","Maggie");
map.put("5","Bart");
System.out.println(MapUtils.getKeysFromValue(map,"Bart"));
}
}

12.4 Get keys corresponding to a value from a MapTag(s): Language

12.5 Iterate a Collection and remove an itemTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0619.html
You get an exception if while scanning a Collection, you decide to remove an item.
import java.util.ArrayList;
public class Simple {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
for(String s: list)
{
if (s.equals("Barney")) {
list.remove("Barney");
}
System.out.println(s);
}
}
/*
output :
Bart
Lisa
Marge
Barney
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
at java.util.AbstractList$Itr.next(Unknown Source)
at com.rgagnon.howto.Simple.main(Simple.java:20)
*/
}

The trick is to use an Iterator and remove the item with Iterator.remove()
import java.util.ArrayList;
import java.util.Iterator;
public class Simple {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
String s = iter.next();
if (s.equals("Barney")) {

12.5 Iterate a Collection and remove an itemTag(s): Language

iter.remove();
}
else {
System.out.println(s);
}
}
for(String s: list)
{
System.out.println(s);
}
}
/*
output :
Bart
Lisa
Marge
Homer
Maggie
Bart
Lisa
Marge
Homer
Maggie
*/
}

12.6 Count distinct elements in a VectorTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0377.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++) {

12.6 Count distinct elements in a VectorTag(s): Language

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);
return set.size();
}

12.7 Dump the content of a Collection (JDK 1.5)Tag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0628.html

12.7.1 List
public class DumpCollection {
public static void main(String[] args) {
java.util.ArrayList<String> theSimpsons = new
java.util.ArrayList<String>();
theSimpsons.add("Bart");
theSimpsons.add("Lisa");
theSimpsons.add("Marge");
theSimpsons.add("Barney");
theSimpsons.add("Homer");
theSimpsons.add("Maggie");
for (String character: theSimpsons) {
System.out.println(character);
}

12.7 Dump the content of a Collection (JDK 1.5)Tag(s): Language

}
}

Or convert the list as an Array :


System.out.println(java.util.Arrays.toString(theSimpsons.toArray()));
/*
output :
*/

[Bart, Lisa, Marge, Barney, Homer, Maggie]

12.7.2 Map
import java.util.*;
import java.io.*;
public class DumpCollection {
public static void main(String[] args) {
Map<String,File> theSimpsons = new HashMap<String,File>();
theSimpsons.put("Bart", new File("Bart.jpg"));
theSimpsons.put("Lisa", new File("Lisa.jpg"));
theSimpsons.put("Marge", new File("Marge.jpg"));
theSimpsons.put("Barney", new File("Barney.jpg"));
theSimpsons.put("Homer", new File("Homer.jpg"));
theSimpsons.put("Maggie", new File("Maggie.jpg"));
dump(theSimpsons);
}
public static void dump(Map<?,?> map) {
for (Map.Entry<?,?> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
/*
output :
Bart: Bart.jpg
Lisa: Lisa.jpg
Maggie: Maggie.jpg
Homer: Homer.jpg
Barney: Barney.jpg
Marge: Marge.jpg
*/

12.8 Initialize a CollectionTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0633.html

12.7.2 Map

The regular way


import java.util.List;
import java.util.ArrayList;
public class InitCollections {
public static void main(String args[]) {
ArrayList<String> list = new ArrayList<String>();
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
dump(list);
}
public static void dump(List<String> list) {
for (String s:list) {
System.out.println(s);
}
}
}

Using a static initializer


import java.util.List;
import java.util.ArrayList;
public class InitCollections {
static ArrayList<String> list = new ArrayList<String>();
static {
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
}
public static void main(String args[]) {
dump(list);
}
public static void dump(List<String> list) {
for (String s:list) {
System.out.println(s);
}
}
}

Using the Double Brace Initialization.


Careful with this one because it can cause memory leak.

import java.util.List;
import java.util.ArrayList;
public class InitCollections {
static ArrayList<String> list = new ArrayList<String>() {{
add("Bart");
add("Lisa");
add("Marge");
add("Barney");

12.7.2 Map

add("Homer");
add("Maggie");
}};
public static void main(String args[]) {
dump(list);
}
public static void dump(List<String> list) {
for (String s:list) {
System.out.println(s);
}
}
}

Use Arrays.asList()
import java.util.List;
import java.util.Arrays;
public class InitCollections {
public static void main(String args[]) {
List list = Arrays.asList("Bart", "Lisa", "Marge", "Homer", "Maggie");
dump(list);
}
public static void dump(List<String> list) {
for (String s:list) {
System.out.println(s);
}
}
}

Using Static import


First a small static class
package com.rgagnon.howto;
import java.util.Arrays;
import java.util.List;
public class CollectionUtils {
public static <T> List<T> List(T...elems){
return Arrays.asList( elems );
}
}

then
package com.rgagnon.howto;
import static com.rgagnon.howto.CollectionUtils.List;
import java.util.List;
public class InitCollections {
public static void main(String args[]) {
List<String> list = List("Bart", "Lisa", "Marge", "Homer", "Maggie");
dump(list);
}

12.7.2 Map

public static void dump(List<String> list) {


for (String s:list) {
System.out.println(s);
}
}
}

12.9 Merge (or add) two arrays into oneTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0636.html
The easy way is to convert the arrays into Lists, add one into another and finally convert back to
an array.
import java.util.*;
public class Test2 {
public static void main(String args[]){
String a[] = {"a", "b", "c"};
String b[] = {"d", "e" };
List<String> list = new ArrayList<String>(Arrays.asList(a));
list.addAll(Arrays.asList(b));
Object [] c = list.toArray();
System.out.println(Arrays.toString(c));
/*
output : [a, b, c, d, e]
*/
}
}

From there a more versatile method is developped to accept a list of arrays to be merged into
one.
public class CollectionUtils {
public static String[] join(String [] ... parms) {
// calculate size of target array
int size = 0;
for (String[] array : parms) {
size += array.length;
}
String[] result = new String[size];
int j = 0;
for (String[] array : parms) {
for (String s : array) {

12.9 Merge (or add) two arrays into oneTag(s): Language

result[j++] = s;
}
}
return result;
}

public static void main(String[] args) {


String a[] = { "1", "2", "3" };
String b[] = { "4", "5", "6" };
String c[] = { "7", "8", "9" };
String[] big = (String [])join(a,b,c);
System.out.println(java.util.Arrays.toString(big));
/*
* output :
*
[1, 2, 3, 4, 5, 6, 7, 8, 9]
*/
}
}

12.10 Define an array (or Map, or ENUM) of functionsTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0005.html

12.10.1 Using an interface


First we define an interface.
public interface Command {
void exec();
}

then the implementation of the functions


public class ACommandImpl implements Command {
@Override
public void exec() {
System.out.println("This is Command type A");
}
}
public class BCommandImpl implements Command {
@Override
public void exec() {
System.out.println("This is Command type B");
}
}

12.10 Define an array (or Map, or ENUM) of functionsTag(s): Language

public class CCommandImpl implements Command {


@Override
public void exec() {
System.out.println("This is Command type C");
}
}

We put in an array an instance of each implementation. Then we are able to run the desired
function by using the array index.
public class TestCommand {
public static void main(String[] args) {
Command[] commands = new Command[3];
commands[0] = new ACommandImpl();
commands[1] = new BCommandImpl();
commands[2] = new CCommandImpl();
// no error checking!
for (;;) {
String s = javax.swing.JOptionPane.showInputDialog
("Command no ? (0,1 or 2)", new Integer(0));
if (s == null) break;
commands[Integer.parseInt(s)].exec();
}
}
}

To use a String instead of a number to access to desired function, use a Map.


public class TestCommand {
public static void main(String[] args) {
java.util.Map <String, Command> commands =
new java.util.HashMap<String, Command>();
commands.put("A", new ACommandImpl());
commands.put("B", new BCommandImpl());
commands.put("C", new CCommandImpl());
// no error checking!
for (;;) {
String s = javax.swing.JOptionPane.showInputDialog
("Command ID ? (A,B or C)", "A");
if (s == null) break;
commands.get(s.toUpperCase()).exec();
}
}
}

12.10.2 Using an enum


public interface Command {
void exec();
}
enum Functions implements Command {
A() {
public void exec() {
System.out.println("This is Command type A");
}
},
B() {
public void exec() {
System.out.println("This is Command type B");
}

12.10.2 Using an enum

},
C() {
public void exec() {
System.out.println("This is Command type C");
}
}
}

then
public class TestCommand {
public static void main(String[] args) {
// no error checking!
for (;;) {
String s = javax.swing.JOptionPane.showInputDialog
("Command ID ? (A,B or C)", "A");
if (s == null) break;
Functions function = Functions.valueOf(s.toUpperCase());
function.exec();
}
}
}

NOTE : Using this technique, it's possible to simulate "switch ... case" based on a string value.

12.11 Join a List as a StringTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0649.html
import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.ArrayList;
public class CollectionUtils {
private CollectionUtils() {}
public static String join (AbstractCollection<String> s) {
return CollectionUtils.join(s, "");
}
public static String join
(AbstractCollection<String> s, String delimiter)
{
if (s == null || s.isEmpty()) return "";
Iterator<String> iter = s.iterator();
StringBuilder builder = new StringBuilder(iter.next());
while( iter.hasNext() ) {
builder.append(delimiter).append(iter.next());
}
return builder.toString();
}

12.11 Join a List as a StringTag(s): Language

public static void main(String[] args) {


ArrayList<String> list = new ArrayList<String>();
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
System.out.println(CollectionUtils.join(list));
// output : BartLisaMargeBarneyHomerMaggie
System.out.println(CollectionUtils.join(list,","));
// output : Bart,Lisa,Marge,Barney,Homer,Maggie
}
}

12.12 Remove duplicates from a List Tag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaremoveduplicatesinalist.html
Order is not preserved
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
public class ListUtils {
private ListUtils() {}
public static <T> void removeDuplicate(List <T> list) {
HashSet <T> h = new HashSet<T>(list);
list.clear();
list.addAll(h);
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
System.out.println(list);
// output : [Bart, Lisa, Marge, Marge, Barney, Homer, Maggie]
ListUtils.removeDuplicate(list);
System.out.println(list);
// output : [Bart, Lisa, Maggie, Homer, Barney, Marge]
}
}

12.12 Remove duplicates from a List Tag(s): Language

Order is preserved
import
import
import
import
import

java.util.HashSet;
java.util.ArrayList;
java.util.Iterator;
java.util.List;
java.util.Set;

public class ListUtils {


private ListUtils() {}
@SuppressWarnings("unchecked")
public static <T> void removeDuplicate(List <T> list) {
Set <T> set = new HashSet <T>();
List <T> newList = new ArrayList <T>();
for (Iterator <T>iter = list.iterator();
iter.hasNext(); ) {
Object element = iter.next();
if (set.add((T) element))
newList.add((T) element);
}
list.clear();
list.addAll(newList);
}
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Bart");
list.add("Lisa");
list.add("Marge");
list.add("Marge");
list.add("Barney");
list.add("Homer");
list.add("Maggie");
System.out.println(list);
// output : [Bart, Lisa, Marge, Marge, Barney, Homer, Maggie]
ListUtils.removeDuplicate(list);
System.out.println(list);
// output : [Bart, Lisa, Marge, Barney, Homer, Maggie]
}
}

12.13 Convert a Map to a Properties (or vice versa)Tag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaconvertmaptoproperties.html
Map to Properties
public static Properties mapToProperties(Map<String, String> map) {
Properties p = new Properties();
Set<Map.Entry<String,String>> set = map.entrySet();

12.13 Convert a Map to a Properties (or vice versa)Tag(s): Language

for (Map.Entry<String,String> entry : set) {


p.put(entry.getKey(), entry.getValue());
}
return p;
}

Properties to Map
public static Map<String, String> propertiesToMap(Properties props) {
HashMap<String, String> hm = new HashMap<String,String>();
Enumeration<Object> e = props.keys();
while (e.hasMoreElements()) {
String s = (String)e.nextElement();
hm.put(s, props.getProperty(s));
}
return hm;
}

12.14 Use an INI file (properties)Tag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0024.html

12.15 Open Source packages


The ini4j is a simple Java API for handling configuration files in Windows .INI format.
http://ini4j.sourceforge.net/
As a bonus, ini4j can deal with variable subsitution, parse .REG file and write or read the registry.
The Apache Commons Configuration package provides the HierarchicalINIConfiguration class
to handle Windows INI file.
http://commons.apache.org/configuration/

12.16 Using Properties


The structure of a Properties 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

12.14 Use an INI file (properties)Tag(s): Language

[JAVA code]
import java.util.*;
import java.io.*;
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 serverside process.
To read a Properties file via an Applet, load the Properties files this way :
12.14 Use an INI file (properties)Tag(s): Language

p.load((new URL(getCodeBase(), "user.props")).openStream());

A Properties file stored in a JAR can be loaded this way :


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!

12.17 Load a properties fileTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0434.html
import
import
import
import
import

java.util.Properties;
java.io.File;
java.io.IOException;
java.io.FileInputStream;
java.net.URL;

public class PropsUtils {


private PropsUtils() { }
/**
* Load a properties file from the classpath
* @param propsName
* @return Properties
* @throws Exception
*/
public static Properties load(String propsName) throws Exception {
Properties props = new Properties();
URL url = ClassLoader.getSystemResource(propsName);
props.load(url.openStream());
return props;
}
/**
* Load a Properties File
* @param propsFile
* @return Properties
* @throws IOException
*/
public static Properties load(File propsFile) throws IOException {
Properties props = new Properties();
FileInputStream fis = new FileInputStream(propsFile);
props.load(fis);
fis.close();
return props;
}
}

Load from the startup directory of your application (ex. directory containing the jar)

12.17 Load a properties fileTag(s): Language

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);
fis.close();
System.out.println(props);

12.18 Accentuated characters in Properties/ResourceBundle


fileTag(s): Internationalization Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0492.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).

12.19 Have a multiline value in a properties fileTag(s):


Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0503.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 :


12.18 Accentuated characters in Properties/ResourceBundle fileTag(s): Internationalization Language

[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

12.20 Use XML with PropertiesTag(s): Language XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0578.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);

12.20 Use XML with PropertiesTag(s): Language XML

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="UTF8"?>
<!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>

12.21 Use the Registry to store informations (Preferences


API)Tag(s): Language
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0421.html
With JDK1.4, the Preferences class can use the Windows registry (on Unix, a file is used) :
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();

12.21 Use the Registry to store informations (Preferences API)Tag(s): Language

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 Howto 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

12.22 Sort Properties when savingTag(s): Language


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0614.html
Create a SortedProperties class which extend the regular Properties. Then override the keys()
method to return the sorted keys instead.

import
import
import
import

java.util.Collections;
java.util.Enumeration;
java.util.Properties;
java.util.Vector;

public class SortedProperties extends Properties {


/**
* Overrides, called by the store method.
*/
@SuppressWarnings("unchecked")
public synchronized Enumeration keys() {
Enumeration keysEnum = super.keys();
Vector keyList = new Vector();
while(keysEnum.hasMoreElements()){
keyList.add(keysEnum.nextElement());
}
Collections.sort(keyList);
return keyList.elements();
}
/**
* Demo
*/
public static void main(String[] args) throws Exception {
// regular Properties
Properties p = new Properties();
p.put("B", "value B");
p.put("C", "value C");
p.put("A", "value A");
p.put("D", "value D");

12.22 Sort Properties when savingTag(s): Language

java.io.FileOutputStream fos = new java.io.FileOutputStream("/temp/p.props");


p.store(fos, "regular props");
/*
#regular props
#Thu Jul 31 22:21:51 EDT 2008
A=value A
D=value D
C=value C
B=value B
*/
// same data but with sorted Properties
SortedProperties sp = new SortedProperties();
sp.put("B", "value B");
sp.put("C", "value C");
sp.put("A", "value A");
sp.put("D", "value D");
fos = new java.io.FileOutputStream("/temp/sp.props");
sp.store(fos, "sorted props");
/*
#sorted props
#Thu Jul 31 22:34:06 EDT 2008
A=value A
B=value B
C=value C
D=value D
*/
}
}

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

12.22 Sort Properties when savingTag(s): Language

13 Networking
13.1 javanet

13.2 Extract network card addressTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0369.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 IPbound adapters, including the MAC address (displayed as
"physical address").
In Linux, "ifconfig" does something similar.
Example for Windows
import
import
import
import

java.net.InetAddress;
java.io.InputStream;
java.io.BufferedInputStream;
java.io.IOException;

13 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 =
"^[09AF]{2}[09AF]{2}[09AF]{2}[09AF]{2}[09AF]{2}[09AF]{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;
}

13 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();
}
}
}

13 Networking

13.3 Get the workstation name/ipTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0390.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

To list all the interfaces available on a workstation :


[JDK1.4]
import
import
import
import

java.net.*;
java.util.*;
java.io.*;
java.nio.*;

public class IPAdress {


public void getInterfaces (){
try {
Enumeration e = NetworkInterface.getNetworkInterfaces();
while(e.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) e.nextElement();
System.out.println("Net interface: "+ni.getName());
Enumeration e2 = ni.getInetAddresses();
while (e2.hasMoreElements()){
InetAddress ip = (InetAddress) e2.nextElement();
System.out.println("IP address: "+ ip.toString());
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
IPAdress ip = new IPAdress();

13.3 Get the workstation name/ipTag(s): Networking

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 "lowtech" 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).
[JDK1.4 or less] Pass it to your JVM as java Dcomputername="%COMPUTERNAME%" ... and
then get the value with System.getProperty("computername")
[JDK1.5 or more] You can extract environment variable directly with
System.getenv("COMPUTERNAME")
To get the IP of a client from the server side, see this HowTo.

13.4 Find port number not in useTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0412.html
On Windows, "netstat an" list the ports currently in use.
Take a look at http://www.iana.org/assignments/portnumbers for a list of assigned numbers.

13.4 Find port number not in useTag(s): Networking

13.5 Disable DNS cachingTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0445.html
JDK1.4
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.
A value of 1 indicates "cache forever".
networkaddress.cache.negative.ttl (default: 10)
Specified in java.security to indicate the caching policy for unsuccessful
name lookups from the name service. The value is specified as as integer to
indicate the number of seconds to cache the failure for unsuccessful 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 commandline
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 commandline 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


JDK1.6
The default value has changed for networkaddress.cache.ttl, check the documentation at
http://java.sun.com/javase/6/docs/technotes/guides/net/properties.html#nct
13.5 Disable DNS cachingTag(s): Networking

13.6 Allow user:password in URLTag(s):


Networking Security Common problems WinAPI/Registry
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb0249.html
The following URL syntax is no longer supported in Internet Explorer or in Windows Explorer after
you install the MS04004 Cumulative Security Update for Internet Explorer (832894):
http(s)://username:password@server/resource.ext

This change in the default behavior is also implemented by security updates and service packs that
were released after the 832894 security update.
By default, this new default behavior for handling user information in HTTP or HTTPS URLs applies
only to Windows Explorer and Internet Explorer. To use this new behavior in other programs that
host the Web browser control, create a DWORD value named SampleApp.exe, where
SampleApp.exe is the name of the executable file that runs the program. Set the DWORD value's
value data to 1 in one of the following registry keys.
For all users of the program, set the value in the following registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE

For the current user of the program only, set the value in the following registry key:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE

To disable the new default behavior in Windows Explorer and Internet Explorer, create
iexplore.exe and explorer.exe DWORD values in one of the following registry keys and set their
value data to 0.
For all users of the program, set the value in the following registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE

For the current user of the program only, set the value in the following registry key:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE
ref Microsoft Article ID : 834489

13.6 Allow user:password in URLTag(s): Networking Security Common problems WinAPI/Registry

13.7 Encode/Decode to/from Base64Tag(s):


String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0598.html
As seen in this HowTo, the sun.misc.BASE64Encoder/Decoder or creating your own Base64
handling are the more common way to deal with Base64 encoding/decoding.
Here some alternatives which are maybe easier (and safer) to use.

13.8 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
*/
}
}

13.7 Encode/Decode to/from Base64Tag(s): String/Number Networking

13.9 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();
}
}
}

13.10 MiGBase64

MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

13.11 Lookup using MX record to validate mail serverTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0452.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
import
import

java.util.Hashtable;
javax.naming.*;
javax.naming.directory.*;

public class MXLookup {

13.9 Using Apache Commons Codec

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
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
13.9 Using Apache Commons Codec

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 catchall account as the catch
account will receive the mail (it does, however, mean that someone will at least SEE the
message).
import
import
import
import
import

java.io.*;
java.net.*;
java.util.*;
javax.naming.*;
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;
}

13.9 Using Apache Commons Codec

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;
}
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.

13.9 Using Apache Commons Codec

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
say( wtr, "MAIL
res = hear( rdr
if ( res != 250

sender address
FROM: <tim@orbaker.com>" );
);
) 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();
}
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 :


13.9 Using Apache Commons Codec

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
import
import
import
import

java.io.*;
java.net.*;
java.util.*;
javax.naming.*;
javax.naming.directory.*;

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();

13.9 Using Apache Commons Codec

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 *************
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

13.9 Using Apache Commons Codec

// 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
say( wtr, "MAIL
res = hear( rdr
if ( res != 250

sender address
FROM: <tim@orbaker.com>" );
);
) 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();
}
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;

13.9 Using Apache Commons Codec

}
}

A note sent by M. Donders.


While using the code I noticed a problem with greylisting.
Greylisting, is an anti spam attempt which denies service
for the first time the triple of client, sender and address
reaches the smtp server. Greylisting will send back a
temporary error (450) and therefore the address will be
denied. In this case it probably is better to accept the
address as verified, because there is no better information
available at that moment.

A list a possible SMTP Reply Codes:


Code
211
214
220
221
250
251
252

253
354
355
421
432
450
451
452
453
454
458
459
500
501
502
503
504
521
530
534
538
550
551
552
553
554

Description
System status, or system help reply.
Help message.
Domain service ready.
Ready to start TLS.
Domain service closing transmission channel.
OK, queuing for node node started.
Requested mail action okay, completed.
OK, no messages waiting for node node.
User not local, will forward to forwardpath.
OK, pending messages for node node started.
Cannot VRFY user (e.g., info is not local),
but will take message for this user and attempt delivery.
OK, messages pending messages for node node started.
Start mail input; end with ..
Octetoffset is the transaction offset.
Domain service not available, closing transmission channel.
A password transition is needed.
Requested mail action not taken: mailbox unavailable.
(ex. mailbox busy)
Requested action aborted: local error in processing.
Unable to process ATRN request now
Requested action not taken: insufficient system storage.
You have no mail.
TLS not available due to temporary reason.
Encryption required for requested authentication mechanism.
Unable to queue messages for node node.
Node node not allowed: reason.
Command not recognized: command.
Syntax error.
Syntax error, no parameters allowed.
Command not implemented.
Bad sequence of commands.
Command parameter not implemented.
Machine does not accept mail.
Must issue a STARTTLS command first.
Encryption required for requested authentication mechanism.
Authentication mechanism is too weak.
Encryption required for requested authentication mechanism.
Requested action not taken: mailbox unavailable.
User not local; please try forwardpath.
Requested mail action aborted: exceeded storage allocation.
Requested action not taken: mailbox name not allowed.
Transaction failed.

13.9 Using Apache Commons Codec

RFC0821

13.12 Send an email using the SMTP protocolTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0079.html
SMTP is the protocol used to send an email.
Article on how SMTP works.
Unless you have a good reason, try to use the JavaMail API (see section Mail(Javamail)).
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
(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");

13.12 Send an email using the SMTP protocolTag(s): Networking

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();
}
}
}

13.13 Check if there is mail waitingTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0080.html
import java.net.*;
import java.io.*;
public class CheckMail {
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 {

13.13 Check if there is mail waitingTag(s): Networking

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;
}
}

13.13 Check if there is mail waitingTag(s): Networking

13.14 Receive emailTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0081.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)
)))) {
t += s + "\n";
}
//
// To remove the mail on the server :

13.14 Receive emailTag(s): Networking

//
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;
}
}

13.14 Receive emailTag(s): Networking

13.15 Send email with an attachmentTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0083.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 PY Colle for the tip!
sendln(in, out, "DATA");

13.15 Send email with an attachmentTag(s): Networking

sendln(out, "MIMEVersion: 1.0");


sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock>");
sendln
(out, "ContentType: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n" + boundary);
// Send the
sendln(out,
sendln(out,
sendln(out,

body
"ContentType: text/plain; charset=\"usascii\"\r\n");
"I'm alive. Help me!\r\n\r\n");
"\r\n" + boundary );

// send the GIF


sendln(out, "ContentType:image/gif; name="+FileName);
sendln
(out, "ContentDisposition: attachment;filename=\""+FileName+"\"");
sendln(out, "Contenttransferencoding: 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 USASCII,
allowing 6 bits for each character so the character

13.15 Send email with an attachmentTag(s): Networking

"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
is what happens :
The text string is converted into its USASCII 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
e
n

01101101
01100101
01101110

These three "8bits" are concatenated to make a


24 bit stream
011011010110010101101110
This 24 bit stream is then split up into 4 6bit
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
011011 010110 010100
b
W
U
b
W
U
so "bWU="

(AND to fill the missing bits)

("=" is the padding character)

is the base64 equivalent.

encode "m"
01101101
011011 01
111111
011011 010000
b
Q

(AND to fill the missing bits)


=

(two paddings are added)

Finally, MIME specifies that lines are 76 characters wide maximum.


*/
static String BaseTable[] = {

13.15 Send email with an attachmentTag(s): Networking

"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","+","/"
};
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
int
int
int
int

n3byt
nrest
k
linelength
i

=
=
=
=
=

n / 3;
// how 3 bytes groups?
n % 3;
// the remaining bytes from the grouping
n3byt * 3; // we are doing 3 bytes at a time
0;
// current linelength
0;
// index

// do the 3bytes 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);

13.15 Send email with an attachmentTag(s): Networking

}
else if (nrest==1) {
// 1 byte left
buf[0] = (byte)((bytes[k] &0xFC) >> 2);
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");

13.15 Send email with an attachmentTag(s): Networking

sendln(in, out, "MAIL FROM: <real@gagnon.com>");


sendln(in, out, "RCPT TO: <" + recipient + ">" );
sendln(in, out, "DATA");
sendln(out, "MIMEVersion: 1.0");
sendln(out, "Subject: remember me");
sendln(out, "From: Elvis Presley <Elvis.Presley@jailhouse.rock<");
sendln
(out,"ContentType: multipart/mixed; boundary=\"" + boundary +"\"");
sendln(out, "\r\n" + boundary);
// send the GIF
sendln(out, "ContentType: text/plain; charset=\"usascii\"\r\n");
sendln(out, "I'm alive. Help me!\n\n");
sendln(out, "\r\n" + "" + boundary );
sendln(out, "ContentType:image/gif; name="+FileName1);
sendln
(out, "ContentDisposition: attachment;filename=\""+FileName1+"\"");
sendln(out, "Contenttransferencoding: base64\r\n");
MIMEBase64.encode(FileName1, out);
sendln(out, "\r\n" + boundary);
// the text file
sendln(out, "ContentType: text/plain; name="+FileName2);
sendln(out, "ContentDisposition: inline;filename=\""+FileName2+"\"");
// to send the file as an attachment instead of "inline" use :
// sendln
// (out, "ContentType: text/plain; name="+FileName2);
// sendln
// (out,"ContentDisposition: attachment;filename=\""+FileName2+"\"");
sendln(out, "ContentTransferEncoding: 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.

13.16 Send email with JavaMailTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0321.html

13.16 Send email with JavaMailTag(s): Networking

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;
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=ISO88591");
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("elvis@presley.org"));
transport.connect();

13.16 Send email with JavaMailTag(s): Networking

transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

Email with attachment


import
import
import
import

javax.mail.*;
javax.mail.internet.*;
javax.activation.FileDataSource;
javax.activation.DataHandler;

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();
}
}

13.16 Send email with JavaMailTag(s): Networking

13.17 Send email with authenticationTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0538.html
import
import
import
import

javax.mail.*;
javax.mail.internet.*;
javax.mail.Authenticator;
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";
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.

13.17 Send email with authenticationTag(s): Networking

13.18 Send HTML mail with images (Javamail)Tag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0504.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");

13.18 Send HTML mail with images (Javamail)Tag(s): Networking

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>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 Webbased (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 contentid 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
//

13.18 Send HTML mail with images (Javamail)Tag(s): Networking

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");
// 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("ContentID","<image>");
// add it
multipart.addBodyPart(messageBodyPart);
// put everything together
message.setContent(multipart);
transport.connect();
transport.sendMessage(message,
message.getRecipients(Message.RecipientType.TO));
transport.close();
}
}

13.19 Debug a JavaMail ProgramTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0552.html

13.20 JavaMail Debug mode


To set the JavaMail Debug mode "on" :
Session mailSession = Session.getDefaultInstance(props, null);
mailSession.setDebug(true);

or set the property when launching the JVM


java Dmail.debug=true ...

This setting puts the JavaMail classes in debug mode mode to System.out.
To redirect the JavaMail debugging output to a more appropriate log file you can
link a PrintStream to a ByteArrayOutputStream,
13.19 Debug a JavaMail ProgramTag(s): Networking

tell to JavaMail to use your PrintStream,


do the JavaMail stuff,
dump the the content of the ByteArrayOutputStream to your favorite logger.
ByteArrayOutputStream os = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(os);
Session mailSession = Session.getDefaultInstance(props, null);
try {
if (MAIL_DEBUG) {
logger.info("JAVAMAIL debug mode is ON");
mailSession.setDebug(true);
mailSession.setDebugOut(ps);
}
...
transport.close();
if (MAIL_DEBUG) { logger.info(os); }
}
finally {
ps.close();
os.close();
}

13.21 Verify connectivity to the MailServer with Telnet :


telnet mymailserver 25

for example, you can detect if your firewall is blocking your connection.
Windows 7
By default, the telnet client is not installed on a Win7 workstation. To installed it, open command
shell and type :
pkgmgr /iu:"TelnetClient"

You can also install it through the Control Panel, see Microsoft Technet.

13.22 Use a JavaMail server mockup to act as "inmemory"


mail server
See https://java.net/projects/mockjavamail and http://quintanasoft.com/dumbster/. These
mockups 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.

13.23 Send email with SMTPS (eg. Google GMail)


(Javamail)Tag(s): Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0570.html
13.21 Verify connectivity to the MailServer with Telnet :

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
private
private
private

static
static
static
static

final
final
final
final

String SMTP_HOST_NAME = "smtp.gmail.com";


int SMTP_HOST_PORT = 465;
String SMTP_AUTH_USER = "myaccount@gmail.com";
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 SMTPSSL");
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");

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 Unknown50.49
...

13.21 Verify connectivity to the MailServer with Telnet :

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/packagesummary.html
This setting, mail.smtps.quitwait, is not required anymore! (july2007)

13.23.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)

13.24 Mix plain text and HTML content in a mailTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0471.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");

13.23.1 Settings for well known mail providers

multipart.addBodyPart(messageBodyPart);
message.setContent(multipart);
Transport.send(message);

13.25 Read an Outlook MSG fileTag(s): Networking Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0613.html
When Outlook Express saves an email, it uses the EML format which is a good thing because the
format is a standard.
You read them with Javamail easily, see this HowTo.
But Outlook (not the Express but the one with Office) can only save an email with the MSG format
which is Microsoft specific.

13.26 Apache POI HSMF


http://poi.apache.org/hsmf/
HSMF is the POI Project's pure Java implementation of the Outlook MSG format.
This example takes a MSG file and extracts the attachment(s).
POI 3.6
import
import
import
import
import
import
import
import

java.io.ByteArrayInputStream;
java.io.File;
java.io.FileOutputStream;
java.io.IOException;
java.io.OutputStream;
java.io.PrintWriter;
java.util.Iterator;
java.util.Map;

import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
// You need poiscratchpad3.6

and poi3.6 ( http://poi.apache.org/ )

public class DetectMSGAttachment {


public static void main (String ... args) throws IOException {
String msgfile = "c:/temp/messagewithattachment.msg";
MAPIMessage msg = new MAPIMessage(msgfile);
Map attachmentMap = msg.getAttachmentFiles();
if(attachmentMap.size() > 0) {

13.25 Read an Outlook MSG fileTag(s): Networking Open Source

for (Iterator ii = attachmentMap.entrySet().iterator(); ii.hasNext();) {


Map.Entry entry = (Map.Entry)ii.next();
String attachmentfilename = entry.getKey().toString();
System.out.println(attachmentfilename);
// extract attachment
ByteArrayInputStream fileIn = (ByteArrayInputStream)entry.getValue();
File f = new File("c:/temp", attachmentfilename); // output
OutputStream fileOut = null;
try {
fileOut = new FileOutputStream(f);
byte[] buffer = new byte[2048];
int bNum = fileIn.read(buffer);
while(bNum > 0) {
fileOut.write(buffer);
bNum = fileIn.read(buffer);
}
}
finally {
try {
if(fileIn != null) {
fileIn.close();
}
}
finally {
if(fileOut != null) {
fileOut.close();
}
}
}
}
}
else {
System.out.println("No attachment");
}
}
}

POI 3.7
import
import
import
import
import
import
import
import

java.io.ByteArrayInputStream;
java.io.File;
java.io.FileOutputStream;
java.io.IOException;
java.io.OutputStream;
java.io.PrintWriter;
java.util.Iterator;
java.util.Map;

import
import
import
import
import

org.apache.poi.hdgf.chunks.Chunk;
org.apache.poi.hsmf.MAPIMessage;
org.apache.poi.hsmf.datatypes.AttachmentChunks;
org.apache.poi.hsmf.datatypes.Chunks;
org.apache.poi.hsmf.exceptions.ChunkNotFoundException;

// You need poiscratchpad3.7 and poi3.7 ( http://poi.apache.org/ )


public class DetectMSGAttachment {
public static void main (String ... args) throws IOException {
String msgfile = "c:/temp/messagewithattachment.msg";
MAPIMessage msg = new MAPIMessage(msgfile);
AttachmentChunks attachments[] = msg.getAttachmentFiles();
if(attachments.length > 0) {
for (AttachmentChunks a : attachments) {

13.25 Read an Outlook MSG fileTag(s): Networking Open Source

System.out.println(a.attachLongFileName);
// extract attachment
ByteArrayInputStream fileIn = new ByteArrayInputStream(a.attachData.getValue(
File f = new File("c:/temp", a.attachLongFileName.toString()); // output
OutputStream fileOut = null;
try {
fileOut = new FileOutputStream(f);
byte[] buffer = new byte[2048];
int bNum = fileIn.read(buffer);
while(bNum > 0) {
fileOut.write(buffer);
bNum = fileIn.read(buffer);
}
}
finally {
try {
if(fileIn != null) {
fileIn.close();
}
}
finally {
if(fileOut != null) {
fileOut.close();
}
}
}
}
}
else {
System.out.println("No attachment");
}
}
}

13.27 msgparser
http://auxilii.com/msgparser/
msgparser is a small open source Java library that parses Outlook .msg files and provides their
content using Java objects. msgparser uses the Apache POI POIFS library to parse the
message files which use the OLE 2 Compound Document format.
import java.util.List;
import com.auxilii.msgparser.*;
import com.auxilii.msgparser.attachment.*;
public class SimpleMsgParser {
public static void main(String[] args) throws Exception{
MsgParser msgp = new MsgParser();
Message msg = msgp.parseMsg("c:/temp/test2.msg");
String
String
String
String

fromEmail = msg.getFromEmail();
fromName = msg.getFromName();
subject = msg.getSubject();
body = msg.getBodyText();

System.out.println("From :" + fromName + " <" + fromEmail + ">");


System.out.println("Subject :" + subject);
System.out.println("");
System.out.println(body);

13.27 msgparser

System.out.println("");
List atts = msg.getAttachments();
for (Attachment att : atts) {
if (att instanceof FileAttachment) {
FileAttachment file = (FileAttachment) att;
System.out.println("Attachment : " + file.getFilename());
// you get the actual attachment with
// byte date[] = file.getData();
}
}
}
}

13.28 jmbox
https://jmbox.dev.java.net/
The jmbox project (read jambox) is a Local Store Provider for JavaMail, enabling developers to
use JavaMail api to manage the mail stored in local repositories like Outlook Express, Mozilla,
Netscape etc.
At the moment are supported navigation and reading from Outlook Express 5/6 mail (dbx format).

13.29 Handle EML file with JavaMailTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0458.html

13.30 Loading an .EML file


When saving an email to a file, the resulting file has an eml extension (email fileswhich are in
RFC 822 format). This kind of file can be read and parsed by JavaMail.
import
import
import
import

java.util.*;
java.io.*;
javax.mail.*;
javax.mail.internet.*;

public class ReadEmail {


public static void main(String args[]) throws Exception{
display(new File("C:\\temp\\message.eml"));
}
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");

13.28 jmbox

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 :


XMozillaStatus: 0001
XMozillaStatus2: 00000000
Received: from tomts25srv.bellnexxia.net
(tomts25.bellnexxia.net [209.226.175.188])
by tactika.com (8.9.3/8.9.3) with ESMTP id NAA07621
for <real@rgagnon.com>; Sun, 1 Feb 2004 13:25:33 0500 (EST)
Date: Sun, 01 Feb 2004 13:31:40 0500
From: real gagnon <real@rgagnon.com>
ReplyTo: real@rgagnon.com
UserAgent: Mozilla/5.0
(Windows; U; Windows NT 5.1; enUS; rv:1.4)
Gecko/20030624 Netscape/7.1 (ax)
XAcceptLanguage: enus, en
MIMEVersion: 1.0
To: real@rgagnon.com
Subject: Example for HowTo
ContentType: text/plain; charset=usascii; format=flowed
ContentTransferEncoding: 7bit
XUIDL: 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 <real@rgagnon.com>

Body :
This is an example for HowTo

13.31 Saving an email to .EML file


First you connect to the mail server with POP3 or IMAP protocol to retrieve the emails.
...
folder = store.getDefaultFolder().getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message[] messages = folder.getMessages();
...
for (int i=0; i < messages.length; ++i) {
Message msg = messages[i];
String subject = msg.getSubject();
processSaveToFile(msg, subject);

13.31 Saving an email to .EML file

...
}
...

Individual email are represented by the Message class.


private void processSaveToFile (javax.mail.Message msg, String subject)
throws MessagingException, IOException
{
String whereToSave = "c:/temp/ + sanitizeFilename(subject) + ".eml";
logger.info("Sauvegarde vers "+ whereToSave);
OutputStream out = new FileOutputStream(new File(whereToSave));
try {
msg.writeTo(out);
}
finally {
if (out != null) { out.flush(); out.close(); }
}
}

Since the subject is used to set the filename, it's not a bad idea to sanitize it to remove illegal
characters.
private static String sanitizeFilename(String name) {
return name.replaceAll("[:\\\\/*?|<> \"]", "_");
}

13.32 Receive email using IMAPTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javareceiveemailusingimap.html
IMAP presents mail messages as entries in a hierarchy of folders, one of which will be an inbox.
Java Mail comes with Provider implementations for POP3 and IMAP, and the secure versions of
those as POP3S and IMAPS.
This HowTo connects to a Google Mail account with IMAPS. IMAP protocol is more advanced
than POP. With IMAP, you can talk back to the server and sync your changes automatically.
This Howto connects to a server using the IMAPS (Secure, encrypted IMAP) to download
messages with or without attachments and save them into files.
import
import
import
import

java.io.*;
java.util.*;
javax.mail.*;
javax.mail.internet.*;

public class ReceiveMailImap {


public ReceiveMailImap() {}

13.32 Receive email using IMAPTag(s): Networking

//
// inspired by :
// http://www.mikedesjardins.net/content/2008/03/usingjavamailtoreadandextract/
//
public static void doit() throws MessagingException, IOException {
Folder folder = null;
Store store = null;
try {
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", "imaps");
Session session = Session.getDefaultInstance(props, null);
// session.setDebug(true);
store = session.getStore("imaps");
store.connect("imap.gmail.com","myemail@gmail.com", "******");
folder = store.getFolder("Inbox");
/* Others GMail folders :
* [Gmail]/All Mail
This folder contains all of your Gmail messages.
* [Gmail]/Drafts
Your drafts.
* [Gmail]/Sent Mail Messages you sent to other people.
* [Gmail]/Spam
Messages marked as spam.
* [Gmail]/Starred
Starred messages.
* [Gmail]/Trash
Messages deleted from Gmail.
*/
folder.open(Folder.READ_WRITE);
Message messages[] = folder.getMessages();
System.out.println("No of Messages : " + folder.getMessageCount());
System.out.println("No of Unread Messages : " + folder.getUnreadMessageCount());
for (int i=0; i < messages.length; ++i) {
System.out.println("MESSAGE #" + (i + 1) + ":");
Message msg = messages[i];
/*
if we don''t want to fetch messages already processed
if (!msg.isSet(Flags.Flag.SEEN)) {
String from = "unknown";
...
}
*/
String from = "unknown";
if (msg.getReplyTo().length >= 1) {
from = msg.getReplyTo()[0].toString();
}
else if (msg.getFrom().length >= 1) {
from = msg.getFrom()[0].toString();
}
String subject = msg.getSubject();
System.out.println("Saving ... " + subject +" " + from);
// you may want to replace the spaces with "_"
// the TEMP directory is used to store the files
String filename = "c:/temp/" + subject;
saveParts(msg.getContent(), filename);
msg.setFlag(Flags.Flag.SEEN,true);
// to delete the message
// msg.setFlag(Flags.Flag.DELETED, true);
}
}
finally {
if (folder != null) { folder.close(true); }
if (store != null) { store.close(); }
}
}

13.32 Receive email using IMAPTag(s): Networking

public static void saveParts(Object content, String filename)


throws IOException, MessagingException
{
OutputStream out = null;
InputStream in = null;
try {
if (content instanceof Multipart) {
Multipart multi = ((Multipart)content);
int parts = multi.getCount();
for (int j=0; j < parts; ++j) {
MimeBodyPart part = (MimeBodyPart)multi.getBodyPart(j);
if (part.getContent() instanceof Multipart) {
// partwithinapart, do some recursion...
saveParts(part.getContent(), filename);
}
else {
String extension = "";
if (part.isMimeType("text/html")) {
extension = "html";
}
else {
if (part.isMimeType("text/plain")) {
extension = "txt";
}
else {
// Try to get the name of the attachment
extension = part.getDataHandler().getName();
}
filename = filename + "." + extension;
System.out.println("... " + filename);
out = new FileOutputStream(new File(filename));
in = part.getInputStream();
int k;
while ((k = in.read()) != 1) {
out.write(k);
}
}
}
}
}
}
finally {
if (in != null) { in.close(); }
if (out != null) { out.flush(); out.close(); }
}
}
public static void main(String args[]) throws Exception {
ReceiveMailImap.doit();
}
}

See this HowTo to download using the POP3 protocol.

13.32 Receive email using IMAPTag(s): Networking

13.33 Receive email using POP3Tag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javareceiveemailusingpop3.html
POP3 supports simple downloadanddelete requirements for access to remote mailboxes.
Java Mail comes with Provider implementations for POP3 and IMAP, and the secure versions of
those as POP3S and IMAPS.
This Howto connects to a server using the POP3S (Secure, encrypted POP3) to download
messages with or without attachments and save them into files.
import java.io.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.MimeBodyPart;
public class ReceiveMailPOP3 {
private static final String HOST = "pop.gmail.com";
private static final String USERNAME = "myemail@gmail.com";
private static final String PASSWORD = "******";
public static void doit() throws MessagingException, IOException {
Folder folder = null;
Store store = null;
try {
Properties props = new Properties();
props.put("mail.store.protocol", "pop3s"); // Google uses POP3S not POP3
Session session = Session.getDefaultInstance(props);
// session.setDebug(true);
store = session.getStore();
store.connect(HOST, USERNAME, PASSWORD);
folder = store.getDefaultFolder().getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message[] messages = folder.getMessages();
System.out.println("No of Messages : " + folder.getMessageCount());
System.out.println("No of Unread Messages : " + folder.getUnreadMessageCount());
for (int i=0; i < messages.length; ++i) {
System.out.println("MESSAGE #" + (i + 1) + ":");
Message msg = messages[i];
String from = "unknown";
if (msg.getReplyTo().length >= 1) {
from = msg.getReplyTo()[0].toString();
}
else if (msg.getFrom().length >= 1) {
from = msg.getFrom()[0].toString();
}
String subject = msg.getSubject();
System.out.println("Saving ... " + subject +" " + from);
// you may want to replace the spaces with "_"
// the files will be saved into the TEMP directory
String filename = "c:/temp/" + subject;
saveParts(msg.getContent(), filename);
}
}
finally {
if (folder != null) { folder.close(true); }
if (store != null) { store.close(); }

13.33 Receive email using POP3Tag(s): Networking

}
}
public static void saveParts(Object content, String filename)
throws IOException, MessagingException
{
OutputStream out = null;
InputStream in = null;
try {
if (content instanceof Multipart) {
Multipart multi = ((Multipart)content);
int parts = multi.getCount();
for (int j=0; j < parts; ++j) {
MimeBodyPart part = (MimeBodyPart)multi.getBodyPart(j);
if (part.getContent() instanceof Multipart) {
// partwithinapart, do some recursion...
saveParts(part.getContent(), filename);
}
else {
String extension = "";
if (part.isMimeType("text/html")) {
extension = "html";
}
else {
if (part.isMimeType("text/plain")) {
extension = "txt";
}
else {
// Try to get the name of the attachment
extension = part.getDataHandler().getName();
}
filename = filename + "." + extension;
System.out.println("... " + filename);
out = new FileOutputStream(new File(filename));
in = part.getInputStream();
int k;
while ((k = in.read()) != 1) {
out.write(k);
}
}
}
}
}
}
finally {
if (in != null) { in.close(); }
if (out != null) { out.flush(); out.close(); }
}
}
public static void main(String args[]) throws Exception {
ReceiveMailPOP3.doit();
}
}

See this HowTo to download using the IMAP protocol.

13.33 Receive email using POP3Tag(s): Networking

13.34 Check if a file was modified on the serverTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0069.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, reopen 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();
}
}

13.35 Check if a page existsTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0059.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
*/
}
public static boolean exists(String URLName){
try {
HttpURLConnection.setFollowRedirects(false);
// note : you may also need

13.34 Check if a file was modified on the serverTag(s): Networking

//
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
("ProxyAuthorization", "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;
}
}
}

13.34 Check if a file was modified on the serverTag(s): Networking

13.36 Connect through a ProxyTag(s): Networking Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0085.html

13.36.1 The Networking Properties


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/javase/6/docs/technotes/guides/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 :
System.setProperty("http.proxyHost", "myProxyServer.com");
System.setProperty("http.proxyPort", "80");

Since Java 1.5 you can also pass a java.net.Proxy instance to the openConnection() method:
//Proxy instance, proxy ip = 123.0.0.1 with port 8080
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("123.0.0.1", 8080));
URL url = new URL("http://www.yahoo.com");
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
String page;
StringBuffer tmp = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while ((line = in.readLine()) != null){
page.append(line + "\n");
}
System.out.println(page);

so you don't need to set system properties.


You can use the default PROXY as defined by your networking settings.
System.setProperty("java.net.useSystemProxies", "true");
List l = null;
try {
l = ProxySelector.getDefault().select(new URI("http://www.yahoo.com"));

13.36 Connect through a ProxyTag(s): Networking Networking

}
catch (URISyntaxException e) {
e.printStackTrace();
}
if (l != null) {
for (Iterator iter = l.iterator(); iter.hasNext() {
java.net.Proxy proxy = (java.net.Proxy) iter.next();
System.out.println("proxy hostname : " + proxy.type());
InetSocketAddress addr = (InetSocketAddress) proxy.address();
if (addr == null) {
System.out.println("No Proxy");
}
else {
System.out.println("proxy hostname : " + addr.getHostName());
System.out.println("proxy port : " + addr.getPort());
}
}
}

To bypass the PROXY,


URL url = new URL("http://internal.server.local/");
URLConnection conn = url.openConnection(Proxy.NO_PROXY);

13.36.2 Proxy and Username/Password


You might need to identify yourself to the proxy server.
One way is to use the HTTP property "ProxyAuthorization" with a username:password base64
encoded.
System.setProperty("http.proxyHost", "myProxyServer.com");
System.setProperty("http.proxyPort", "80");
URL url=new URL("http://someserver/somepage");
URLConnection uc = url.openConnection ();
String encoded = new String
(Base64.base64Encode(new String("username:password").getBytes()));
uc.setRequestProperty("ProxyAuthorization", "Basic " + encoded);
uc.connect();
NOTE: For a base64 function, see this Howto.

The following example dumps the content of a URL but before we identify ourself to the proxy.
import java.net.*;
import java.io.*;
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];

13.36.2 Proxy and Username/Password

// PROXY
System.setProperty("http.proxyHost","proxy.mydomain.local") ;
System.setProperty("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
("ProxyAuthorization", "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.
public static void dump(String URLName){
try {
DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];
// PROXY
System.setProperty("http.proxyHost","proxy.mydomain.local") ;
System.setProperty("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());
while(1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}

13.36.2 Proxy and Username/Password

13.36.3 Bypass a Proxy


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

13.37 Identify yourself using HTTP AuthentificationTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0084.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
{
URLConnection conn = url.openConnection();
conn.setDoInput (true);

13.36.3 Bypass a Proxy

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
'A', 'B',
'I', 'J',
'Q', 'R',
'Y', 'Z',
'g', 'h',
'o', 'p',
'w', 'x',
'4', '5',
};

static char base64Array [] = {


'C', 'D', 'E', 'F', 'G', 'H',
'K', 'L', 'M', 'N', 'O', 'P',
'S', 'T', 'U', 'V', 'W', 'X',
'a', 'b', 'c', 'd', 'e', 'f',
'i', 'j', 'k', 'l', 'm', 'n',
'q', 'r', 's', 't', 'u', 'v',
'y', 'z', '0', '1', '2', '3',
'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:
encodedString += base64Array [c3];
encodedString += "=";
break;

13.36.3 Bypass a Proxy

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 Howto.
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("ProxyAuthorization", "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.

13.38 Talk to a CGI/ServletTag(s): Networking Servlet/JSP


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0082.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/cgibin/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 3letter 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/cgibin/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);

13.38 Talk to a CGI/ServletTag(s): Networking Servlet/JSP

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/cgibin/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("contenttype","application/xwwwformurlencoded");
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.

13.39 Write/Read cookies using HTTPTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0092.html
For a JavaJavascript solution, check this Howto.

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.

13.39 Write/Read cookies using HTTPTag(s): Networking

*/
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);
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("SetCookie")) {
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++;
}
}

13.39 Write/Read cookies using HTTPTag(s): Networking

/**
* Display all the cookies currently in the HashTable
*
*/
public void viewAllCookies() {
System.out.println("All Cookies are:");
Enumeration keys = theCookies.keys();
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

13.40 Read a file from the internet Tag(s): Networking IO


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javareadafilefromtheinternet.html

13.40 Read a file from the internet Tag(s): Networking IO

import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
public class NetUtils {
private NetUtils() {}
public static String getTextContent(URL url) throws IOException {
Scanner s = new Scanner(url.openStream()).useDelimiter("\\Z");;
String content = s.next();
return content;
}
public static void main(String[] args) throws IOException {
URL url = new URL("http://www.rgagnon.com/varia/copyrightnotice.txt");
System.out.println(NetUtils.getTextContent(url));
}
}

13.41 Read a GIF or CLASS from an URL save it locallyTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0060.html
import java.io.*;
import java.net.*;
public class SuckURL {
String aFile;
String aURL;
public static void main(String args[]) {
// GIF JAVA Howto at Real's Home
String url =
"http://www.rgagnon.com/images/";
SuckURL b = new SuckURL(url, "jht.gif");
b.doit();
}
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 );

13.41 Read a GIF or CLASS from an URL save it locallyTag(s): Networking

// 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();
}
}

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=126574361.

13.41 Read a GIF or CLASS from an URL save it locallyTag(s): Networking

13.42 Resolve a relative URLTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0297.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/java0001.html");
System.out.println ( relativeURL.toExternalForm ());
/*
output :
http://www.rgagnon.com/javadetails/java0001.html
*/
}
}

13.43 File size from URLTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0298.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();
}
catch(Exception e) {
e.printStackTrace();
}

13.42 Resolve a relative URLTag(s): Networking

}
}

13.44 Use the HTTPS protocolTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0308.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 SSLsymbol (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:\

13.45 Fix certificate problem in HTTPSTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javafixcertificateprobleminHTTPS.html
HTTPS protocol is supported since JDK1.4 (AFAIK), you have nothing special to do.

13.44 Use the HTTPS protocolTag(s): Networking

import
import
import
import

java.io.InputStreamReader;
java.io.Reader;
java.net.URL;
java.net.URLConnection;

public class ConnectHttps {


public static void main(String[] args) throws Exception {
URL url = new URL("https://securewebsite.com");
URLConnection con = url.openConnection();
Reader reader = new InputStreamReader(con.getInputStream());
while (true) {
int ch = reader.read();
if (ch==1) {
break;
}
System.out.print((char)ch);
}
}
}

However, you can have a problem if the server certificate is selfsigned by a testing certification
authority (CA) which is not in trusted CAs of Java on the client side. An exception like
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

is thrown. This is a common situation with a development server.


The fix is to add the self signed certificate to trusted CAs on the client side. You do that by
updating the CACERT file in the your JRE_HOME/lib directory.
Check this tutorial : http://www.javasamples.com/showtutorial.php?tutorialid=210
Or you can override the check and accept an untrusted certificate (with the risk coming with it!).
import
import
import
import

java.io.InputStreamReader;
java.io.Reader;
java.net.URL;
java.net.URLConnection;

import
import
import
import
import
import
import

javax.net.ssl.HostnameVerifier;
javax.net.ssl.HttpsURLConnection;
javax.net.ssl.SSLContext;
javax.net.ssl.SSLSession;
javax.net.ssl.TrustManager;
javax.net.ssl.X509TrustManager;
java.security.cert.X509Certificate;

public class ConnectHttps {


public static void main(String[] args) throws Exception {
/*
* fix for
*
Exception in thread "main" javax.net.ssl.SSLHandshakeException:
*
sun.security.validator.ValidatorException:
*
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilder
*
unable to find valid certification path to requested target
*/
TrustManager[] trustAllCerts = new TrustManager[] {

13.44 Use the HTTPS protocolTag(s): Networking

new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {

public void checkServerTrusted(X509Certificate[] certs, String authType) {

}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create alltrusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the alltrusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
/*
* end of the fix
*/
URL url = new URL("https://securewebsite.com");
URLConnection con = url.openConnection();
Reader reader = new InputStreamReader(con.getInputStream());
while (true) {
int ch = reader.read();
if (ch==1) {
break;
}
System.out.print((char)ch);
}
}
}

13.46 Fetch a page from GoogleTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0399.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="

13.46 Fetch a page from GoogleTag(s): Networking

+ search + "e=UTF8";

URL urlObject = new URL(google);


URLConnection con = urlObject.openConnection();
con.setRequestProperty
( "UserAgent", "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)");

13.47 Upload a file to a serverTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0543.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 clientside code only. A simple way to use the HTML tag in a FORM
<FORM METHOD=POST ENCTYPE="multipart/formdata" 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 (serverside) to handle file upload are :
Jakarta Commons File Upload
O'reilly MultipartRequest (com.oreilly.servlet)

13.47 Upload a file to a serverTag(s): Networking

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.

13.48 Remove HTML tags from a file to extract only the


TEXTTag(s): IO String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0424.html

13.49 Using regular expression


A special regular expression is used to strip out anything between a < and > .
import java.io.*;
public class Html2TextWithRegExp {
private Html2TextWithRegExp() {}
public static void main (String[] args) throws Exception{
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader("javanew.html"));
String line;
while ( (line=br.readLine()) != null) {
sb.append(line);
// or
// sb.append(line).append(System.getProperty("line.separator"));
}
String nohtml = sb.toString().replaceAll("\\<.*?>","");
System.out.println(nohtml);
}
}

However if any Javascript is present, the script will be seen as text. Also you may need to add
some logic during the reading to take into account only what is inside the <BODY> tag.

13.50 Using javax.swing.text.html.HTMLEditorKit


In most cases, the HTMLEditorKit is used with a JEditorPane text component but it can be also
used directly to extract text from an HTML page.
import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.util.List;
java.util.ArrayList;

13.48 Remove HTML tags from a file to extract only the TEXTTag(s): IO String/Number Networking

import
import
import
import

javax.swing.text.html.parser.ParserDelegator;
javax.swing.text.html.HTMLEditorKit.ParserCallback;
javax.swing.text.html.HTML.Tag;
javax.swing.text.MutableAttributeSet;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String> extractText(Reader reader) throws IOException {
final ArrayList<String> list = new ArrayList<String>();
ParserDelegator parserDelegator = new ParserDelegator();
ParserCallback parserCallback = new ParserCallback() {
public void handleText(final char[] data, final int pos) {
list.add(new String(data));
}
public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos) { }
public void handleEndTag(Tag t, final int pos) { }
public void handleSimpleTag(Tag t, MutableAttributeSet a, final int pos) { }
public void handleComment(final char[] data, final int pos) { }
public void handleError(final java.lang.String errMsg, final int pos) { }
};
parserDelegator.parse(reader, parserCallback, true);
return list;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader("javanew.html");
List<String> lines = HTMLUtils.extractText(reader);
for (String line : lines) {
System.out.println(line);
}
}
}

Note that the HTMLEditorKit can be easily confused if the HTML to be parsed is not wellformed.

13.51 Using an HTML parser


This is maybe the best solution (if the choosen parser is good !).
There are many parsers available on the net. In this HowTo, I will use the OpenSource package
Jsoup.
Jsoup is entirely self contained and has no dependencies which is a good thing.
import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.io.BufferedReader;
org.jsoup.Jsoup;

public class HTMLUtils {


private HTMLUtils() {}
public static String extractText(Reader reader) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(reader);
String line;

13.51 Using an HTML parser

while ( (line=br.readLine()) != null) {


sb.append(line);
}
String textOnly = Jsoup.parse(sb.toString()).text();
return textOnly;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader
("C:/RealHowTo/topics/javalanguage.html");
System.out.println(HTMLUtils.extractText(reader));
}
}

13.52 Using Apache Tika


Apache Tika
import java.io.FileInputStream;
import java.io.InputStream;
import
import
import
import
import
import

org.apache.tika.metadata.Metadata;
org.apache.tika.parser.AutoDetectParser;
org.apache.tika.parser.ParseContext;
org.apache.tika.parser.Parser;
org.apache.tika.sax.BodyContentHandler;
org.xml.sax.ContentHandler;

public class ParseHTMLWithTika {


public static void main(String args[]) throws Exception {
InputStream is = null;
try {
is = new FileInputStream("C:/Temp/javax.html");
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
Parser parser = new AutoDetectParser();
parser.parse(is, contenthandler, metadata, new ParseContext());
System.out.println(contenthandler.toString());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (is != null) is.close();
}
}
}

See Extract text from a PDF using Apache Tika, Get Mime Type from a file.
See also Extract links from an HTML page

13.52 Using Apache Tika

13.53 Extract links from an HTML pageTag(s):


String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0639.html

13.54 Using javax.swing.text.html.HTMLEditorKit


import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.util.List;
java.util.ArrayList;

import
import
import
import
import

javax.swing.text.html.parser.ParserDelegator;
javax.swing.text.html.HTMLEditorKit.ParserCallback;
javax.swing.text.html.HTML.Tag;
javax.swing.text.html.HTML.Attribute;
javax.swing.text.MutableAttributeSet;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String> extractLinks(Reader reader) throws IOException {
final ArrayList<String> list = new ArrayList<String>();
ParserDelegator parserDelegator = new ParserDelegator();
ParserCallback parserCallback = new ParserCallback() {
public void handleText(final char[] data, final int pos) { }
public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos) {
if (tag == Tag.A) {
String address = (String) attribute.getAttribute(Attribute.HREF);
list.add(address);
}
}
public void handleEndTag(Tag t, final int pos) { }
public void handleSimpleTag(Tag t, MutableAttributeSet a, final int pos) { }
public void handleComment(final char[] data, final int pos) { }
public void handleError(final java.lang.String errMsg, final int pos) { }
};
parserDelegator.parse(reader, parserCallback, false);
return list;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader("javanew.html");
List<String> links = HTMLUtils.extractLinks(reader);
for (String link : links) {
System.out.println(link);
}
}
}

13.55 Using an HTML parser


In this HowTo, I will use the OpenSource package Jsoup.
import java.io.IOException;

13.53 Extract links from an HTML pageTag(s): String/Number Networking

import java.util.List;
import java.util.ArrayList;
import
import
import
import

org.jsoup.Jsoup;
org.jsoup.nodes.Document;
org.jsoup.nodes.Element;
org.jsoup.select.Elements;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String>extractLinks(String url) throws IOException {
final ArrayList<String> result = new ArrayList<String>();
Document doc = Jsoup.connect(url).get();
Elements links = doc.select("a[href]");
Elements media = doc.select("[src]");
Elements imports = doc.select("link[href]");
// href ...
for (Element link : links) {
result.add(link.attr("abs:href"));
}
// img ...
for (Element src : media) {
result.add(src.attr("abs:src"));
}
// js, css, ...
for (Element link : imports) {
result.add(link.attr("abs:href"));
}
return result;
}

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


String site = "http://www.rgagnon.com/topics/javalanguage.html";
List<String> links = HTMLUtils.extractLinks(site);
for (String link : links) {
System.out.println(link);
}
}
}

See also how to extract text from an HTML page.

13.56 Call a web service (generated with BEA


ServiceGen)Tag(s): Networking
Current version of this HowTo :
13.56 Call a web service (generated with BEA ServiceGen)Tag(s): Networking

http://www.rgagnon.com/javadetails/../javadetails/java0657.html
ServiceGen is an utility to generate a client module to access a web service hosted by BEA WLS.
This example use a generated client to call the function list of a Web Service.
import com.company.webservices.client.Commonwebservices;
import com.company.webservices.client.CommonwebservicesPort;
import com.company.webservices.client.Commonwebservices_Impl;
public class Test {
public static void main(String ... args) throws Exception{
System.setProperty("weblogic.webservice.verbose", "true");
String wsdlUri = "http://server.company.local/wsdl/commonWS.xml";
Commonwebservices ws = new Commonwebservices_Impl(wsdlUri);
CommonwebservicesPort wsp = ws.getcommonwebservicesPort("myusername", "mypassword");
String list = wsc.list();
System.out.println(list);
}
}

A typical output :

URL

http://server.company.local:80/commonWS/commonwebservices

Headers
:
ContentLength: [459]
SOAPAction: [""]
ContentType: [text/xml; charset=utf8]
<?xml version="1.0" encoding="utf8" standalone="yes"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<env:Header></env:Header>
<env:Body env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<m:list xmlns:m="http://company.local/common"></m:list>
</env:Body></env:Envelope>
<! END REQUEST FROM CLIENT >
<! RESPONSE TO CLIENT >

URL
: http://server.company.local:80/commonWS/commonwebservices
Response Code :200
Headers
:
Date=Mon, 17 Aug 2009 14:36:29 GMT
Server=MicrosoftIIS/6.0
XPoweredBy=Servlet/2.5 JSP/2.1
CacheControl=nocache="setcookie"
ContentLength=1211
ContentType=text/xml; charset=ISO88591
SetCookie=JSESSIONID=BJYXKJqfFC7nl9TMgYkJg9DpL5kZ1nTQy2M8v1BXJnT1R8n1DhfX!1553076658; pat
Envelope
:
<?xml version="1.0" encoding="ISO88591" standalone="yes"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"

13.56 Call a web service (generated with BEA ServiceGen)Tag(s): Networking

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<env:Header></env:Header>
<env:Body env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<m:listResponse xmlns:m="http://company.local/common">
<result xsi:type="xsd:string">\\company.local\fonc_sas, \\company.local\unit_sas, \\company.l
</result></m:listResponse></env:Body></env:Envelope>
<! END RESPONSE TO CLIENT >
\\company.local\fonc_sas, \\company.local\unit_sas, \\company.local\prod_sas

If you need authentication to access the WSDL then it's possible to do something like this :
String wsdlUri =
"http://myusername:mypassword@server.company.local/commonWS/commonwebservices?WSDL";

13.57 Do basic authentication when calling a webservice


Tag(s): Networking

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javadobasicauthenticationwhencallingawebserv
You have a web service, generated with JAXWS or something else. You have the required client
class but you need to provide a username/password. This can done easily with the help of the
java.net.Authenticator. In this snippet, we are using an anonymous Authenticator to pass the
credentials.

java.net.Authenticator myAuth = new java.net.Authenticator() {


@Override
protected java.net.PasswordAuthentication getPasswordAuthentication() {
return new java.net.PasswordAuthentication("ws.user", "ws.pwd".toCharArray());
}
};
java.net.Authenticator.setDefault(myAuth);
MyWebService myws = new MyWebService(new URL(url));
MyWebServicesHost mywsh = myws.getMyServicesHostPort();
logger.info(" result :" + mywsh.myFunction("42"));

or use a regular class instead of an anonymous one.


import java.net.Authenticator;
import java.net.PasswordAuthentication;
public class MyAuthenticator extends Authenticator {
private String user;
private String password;
public MyAuthenticator(String user,String password) {
this.user = user;
this.password = password;
}
@Override

13.57 Do basic authentication when calling a webservice Tag(s): Networking

protected PasswordAuthentication getPasswordAuthentication() {


PasswordAuthentication auth = new PasswordAuthentication(user,password.toCharArray())
return auth;
}
}

13.58 WS authentication from Weblogic


WLS uses its own HTTP protocol implementation, so the above technique won't work, a 401
return code is always returned.
So if from Weblogic, you need to call a Web service and identify yourself using HTTP BASIC then
you need to make sure to use the Sun's HTTP implementation, not the default and "push" the
credentials.
import javax.xml.ws.BindingProvider;
...
URL url;
if (wsUrl.startsWith("https")) {
url = new URL(null, svcUrl, new sun.net.www.protocol.https.Handler());
}
else {
url = new URL(null, svcUrl, new sun.net.www.protocol.http.Handler());
}

MyWebService myws = new MyWebService(url);


MyWebServicesHost mywsh = myws.getMyServicesHostPort();

((BindingProvider)engine).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "usernam
((BindingProvider)engine).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "passwor
logger.info(" result :" + mywsh.myFunction("42"));

13.59 Have a simple HTTP serverTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javahaveasimplehttpserver.html
Since Java 1.6, there's a builtin HTTP server included with the JDK.
The HttpServer provides a simple highlevel Http server API, which can be used to build
embedded HTTP servers.
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;

13.58 WS authentication from Weblogic

import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
/*
* a simple static http server
*/
public class SimpleHttpServer {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/test", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
String response = "Welcome Real's HowTo test page";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}

Compile and execute. To access the local server, open a browser at http://localhost:8000/test.
The next HttpServer provides 2 contexts :
http://localhost:8000/info to display an informative message.
http://localhost:8000/get to download a specific PDF to the browser.
import
import
import
import
import
import

java.io.BufferedInputStream;
java.io.File;
java.io.FileInputStream;
java.io.IOException;
java.io.OutputStream;
java.net.InetSocketAddress;

import
import
import
import

com.sun.net.httpserver.HttpExchange;
com.sun.net.httpserver.HttpHandler;
com.sun.net.httpserver.HttpServer;
com.sun.net.httpserver.Headers;

public class SimpleHttpServer {


public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/info", new InfoHandler());
server.createContext("/get", new GetHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class InfoHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
String response = "Use /get to download a PDF";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}

13.58 WS authentication from Weblogic

static class GetHandler implements HttpHandler {


public void handle(HttpExchange t) throws IOException {
// add the required response header for a PDF file
Headers h = t.getResponseHeaders();
h.add("ContentType", "application/pdf");
// a PDF (you provide your own!)
File file = new File ("c:/temp/doc.pdf");
byte [] bytearray = new byte [(int)file.length()];
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(bytearray, 0, bytearray.length);
// ok, we are ready to send the response.
t.sendResponseHeaders(200, file.length());
OutputStream os = t.getResponseBody();
os.write(bytearray,0,bytearray.length);
os.close();
}
}
}

See these related HowTo :


Handle URL parameters using the JDK HTTP server
Do Basic authentication using the JDK HTTP server
See also SimpleWeb, an open source http server.

13.60 Connect through a ProxyTag(s): Networking Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0085.html

13.60.1 The Networking Properties


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/javase/6/docs/technotes/guides/net/properties.html.
You can set the required properties when starting the JVM for a JAVA application from the
command line:

13.60 Connect through a ProxyTag(s): Networking Networking

java

Dhttp.proxyHost=myproxyserver.com

Dhttp.proxyPort=80 MyJavaApp

Or in your source :
System.setProperty("http.proxyHost", "myProxyServer.com");
System.setProperty("http.proxyPort", "80");

Since Java 1.5 you can also pass a java.net.Proxy instance to the openConnection() method:
//Proxy instance, proxy ip = 123.0.0.1 with port 8080
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("123.0.0.1", 8080));
URL url = new URL("http://www.yahoo.com");
HttpURLConnection uc = (HttpURLConnection)url.openConnection(proxy);
uc.connect();
String page;
StringBuffer tmp = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
while ((line = in.readLine()) != null){
page.append(line + "\n");
}
System.out.println(page);

so you don't need to set system properties.


You can use the default PROXY as defined by your networking settings.
System.setProperty("java.net.useSystemProxies", "true");
List l = null;
try {
l = ProxySelector.getDefault().select(new URI("http://www.yahoo.com"));
}
catch (URISyntaxException e) {
e.printStackTrace();
}
if (l != null) {
for (Iterator iter = l.iterator(); iter.hasNext() {
java.net.Proxy proxy = (java.net.Proxy) iter.next();
System.out.println("proxy hostname : " + proxy.type());
InetSocketAddress addr = (InetSocketAddress) proxy.address();
if (addr == null) {
System.out.println("No Proxy");
}
else {
System.out.println("proxy hostname : " + addr.getHostName());
System.out.println("proxy port : " + addr.getPort());
}
}
}

To bypass the PROXY,


URL url = new URL("http://internal.server.local/");
URLConnection conn = url.openConnection(Proxy.NO_PROXY);

13.60 Connect through a ProxyTag(s): Networking Networking

13.60.2 Proxy and Username/Password


You might need to identify yourself to the proxy server.
One way is to use the HTTP property "ProxyAuthorization" with a username:password base64
encoded.
System.setProperty("http.proxyHost", "myProxyServer.com");
System.setProperty("http.proxyPort", "80");
URL url=new URL("http://someserver/somepage");
URLConnection uc = url.openConnection ();
String encoded = new String
(Base64.base64Encode(new String("username:password").getBytes()));
uc.setRequestProperty("ProxyAuthorization", "Basic " + encoded);
uc.connect();
NOTE: For a base64 function, see this Howto.

The following example dumps the content of a URL but before we identify ourself to the proxy.
import java.net.*;
import java.io.*;
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
System.setProperty("http.proxyHost","proxy.mydomain.local") ;
System.setProperty("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
("ProxyAuthorization", "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();

13.60.2 Proxy and Username/Password

}
}
}

With JDK1.2, the java.net.Authenticator can be used to send the credentials when needed.
public static void dump(String URLName){
try {
DataInputStream di = null;
FileOutputStream fo = null;
byte [] b = new byte[1];
// PROXY
System.setProperty("http.proxyHost","proxy.mydomain.local") ;
System.setProperty("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());
while(1 != di.read(b,0,1)) {
System.out.print(new String(b));
}
}
catch (Exception e) {
e.printStackTrace();
}
}

13.60.3 Bypass a Proxy


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

13.61 Have timeout on socket connectionTag(s): Networking


Current version of this HowTo :
13.60.3 Bypass a Proxy

http://www.rgagnon.com/javadetails/../javadetails/java0086.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.

13.62 Ping a serverTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0093.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 lowlevel 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.*;
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();}
}
}
}

13.62 Ping a serverTag(s): Networking

NOTE: To make this a more "complete PING", you may want to check this Howto 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) .

13.63 Get the Date from serverTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0094.html
This can be done by opening a socket to the port "daytime" (port 13) (on Unix or NT machine).
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);

13.63 Get the Date from serverTag(s): Networking

if (i==1) return;
System.out.print(new String(b,0,i));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}

13.64 Use the java.net.Socket.setSoLinger methodTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0293.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()

13.65 Use the java.net.Socket.setTcpNoDelay methodTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0294.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
13.64 Use the java.net.Socket.setSoLinger methodTag(s): Networking

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()

13.66 Find out who is accessing my ServerSocketTag(s):


Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0295.html
Socket aSock = myServerSocket.accept();
System.out.println
("Connection from : "
+ aSock.getInetAddress().getHostAddress()
+ ':' + aSock.getPort());

13.67 Transfer a file via SocketTag(s): Networking


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0542.html
A client module connects to a server then a file is sent to the client.
This example is very simple with no authentication and hardcoded filename!

First the server module.


import
import
import
import
import
import
import

java.io.BufferedInputStream;
java.io.File;
java.io.FileInputStream;
java.io.IOException;
java.io.OutputStream;
java.net.ServerSocket;
java.net.Socket;

public class SimpleFileServer {


public final static int SOCKET_PORT = 13267; // you may change this
public final static String FILE_TO_SEND = "c:/temp/source.pdf"; // you may change this
public static void main (String [] args ) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;

13.66 Find out who is accessing my ServerSocketTag(s): Networking

OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
try {
servsock = new ServerSocket(SOCKET_PORT);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// send file
File myFile = new File (FILE_TO_SEND);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)"
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
finally {
if (bis != null) bis.close();
if (os != null) os.close();
if (sock!=null) sock.close();
}
}
}
finally {
if (servsock != null) servsock.close();
}
}
}

The client module


import
import
import
import
import

java.io.BufferedOutputStream;
java.io.FileOutputStream;
java.io.IOException;
java.io.InputStream;
java.net.Socket;

public class SimpleFileClient {

public final static int SOCKET_PORT = 13267;


// you may change this
public final static String SERVER = "127.0.0.1"; // localhost
public final static String
FILE_TO_RECEIVED = "c:/temp/sourcedownloaded.pdf"; // you may change this, I give a
// different name because i don't
// overwrite the one used by serv

public final static int FILE_SIZE = 6022386; // file size temporary hard coded
// should bigger than the file to be downloade
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {

13.66 Find out who is accessing my ServerSocketTag(s): Networking

sock = new Socket(SERVER, SOCKET_PORT);


System.out.println("Connecting...");
// receive file
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
bos = new BufferedOutputStream(fos);
bytesRead = is.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead =
is.read(mybytearray, current, (mybytearray.lengthcurrent));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > 1);
bos.write(mybytearray, 0 , current);
bos.flush();
System.out.println("File " + FILE_TO_RECEIVED
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
}
}
}

To try it, first you start the server. You make sure that the file to be sent (as specified in
SimpleFileServer) exists! Then you execute the client module.
To download a file, a simpler and better way is to use the builtin JDK HTTP server, see this
HowTo

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

13.66 Find out who is accessing my ServerSocketTag(s): Networking

14 Security
14.1 javasecurity

14.2 Encrypt a passwordTag(s): Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0400.html

14.3 Transmit a password with MessageDigest


Message digests are secure oneway hash functions that take arbitrarysized data and output a
fixedlength hash value.
A Oneway hash function computes a number from a given data. There is no way to decrypt that
number to retrieve its original value. The only way is to compute again the same value and check if
the result is the same than the previouly computed one.
In this scenario, the user sends a password to the server (through a secure connection). The server
computes the computed hash code with the stored hash, if it's the same then the password is
correct. The password is never stored in the database.

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 hash = byteArrayToHexString(CryptoUtils.computeHash(Input.sval));
System.out.println("the computed hash (hex string) : " + hash);
boolean ok = true;
String inputHash = "";
while (ok) {
System.out.print("Now try to enter a password : " );
Input.nextToken();
inputHash = byteArrayToHexString(CryptoUtils.computeHash(Input.sval));
if (hash.equals(inputHash)){
System.out.println("You got it!");
ok = false;
}
else

14 Security

System.out.println("Wrong, try again...!");


}
}
catch (Exception e){
e.printStackTrace();
}
}
public static byte[] computeHash(String x)
throws Exception
{
java.security.MessageDigest d =null;
d = java.security.MessageDigest.getInstance("SHA1");
d.reset();
d.update(x.getBytes());
return d.digest();
}
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();
}
}

The output is :
Input your secret password : howto
the computed hash (hex string) : 96A26200CBB466C1DD05CB6D9C7C13F1B90A82AC
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!

14.4 Store a password in a properties file


If an automated task needs to log in then you must provide a username/password. Since it's an
automated task you can retrieve the username/password from something like a properties file. A
security best practice is to never store a password in plain text, you must encrypt it using an
appropriate algorithm. The javax.crypto package provides those algorithms and AES is one of them.
To retrieve the original value from an encrypted string, you need to use a secret key habitually
stored in a different location than the user/password file.
In this scenario, a process gets its user and password from a properties file. The password is
crypted, the process uses a "key" stored in a different secure location to decrypt the password. The
password is sent to the server for authentication by comparing the computed hash of the received
password with the hash code stored for this user in the database.

14.4 Store a password in a properties file

In this HowTo, a key file is created during the encryption process if the specified key file is not
found.
import
import
import
import
import
import
import
import
import

java.io.File;
java.io.FileWriter;
java.io.FileReader;
java.io.FileNotFoundException;
java.io.IOException;
java.security.GeneralSecurityException;
java.security.NoSuchAlgorithmException;
java.util.Properties;
java.util.Scanner;

import
import
import
import

javax.crypto.Cipher;
javax.crypto.KeyGenerator;
javax.crypto.SecretKey;
javax.crypto.spec.SecretKeySpec;

public class CryptoUtils {


public static final String AES = "AES";
/**
* encrypt a value and generate a keyfile
* if the keyfile is not found then a new one is created
* @throws GeneralSecurityException
* @throws IOException
*/
public static String encrypt(String value, File keyFile)
throws GeneralSecurityException, IOException
{
if (!keyFile.exists()) {
KeyGenerator keyGen = KeyGenerator.getInstance(CryptoUtils.AES);
keyGen.init(128);
SecretKey sk = keyGen.generateKey();
FileWriter fw = new FileWriter(keyFile);
fw.write(byteArrayToHexString(sk.getEncoded()));
fw.flush();
fw.close();
}
SecretKeySpec sks = getSecretKeySpec(keyFile);

14.4 Store a password in a properties file

Cipher cipher = Cipher.getInstance(CryptoUtils.AES);


cipher.init(Cipher.ENCRYPT_MODE, sks, cipher.getParameters());
byte[] encrypted = cipher.doFinal(value.getBytes());
return byteArrayToHexString(encrypted);
}
/**
* decrypt a value
* @throws GeneralSecurityException
* @throws IOException
*/
public static String decrypt(String message, File keyFile)
throws GeneralSecurityException, IOException
{
SecretKeySpec sks = getSecretKeySpec(keyFile);
Cipher cipher = Cipher.getInstance(CryptoUtils.AES);
cipher.init(Cipher.DECRYPT_MODE, sks);
byte[] decrypted = cipher.doFinal(hexStringToByteArray(message));
return new String(decrypted);
}

private static SecretKeySpec getSecretKeySpec(File keyFile)


throws NoSuchAlgorithmException, IOException
{
byte [] key = readKeyFile(keyFile);
SecretKeySpec sks = new SecretKeySpec(key, CryptoUtils.AES);
return sks;
}
private static byte [] readKeyFile(File keyFile)
throws FileNotFoundException
{
Scanner scanner =
new Scanner(keyFile).useDelimiter("\\Z");
String keyValue = scanner.next();
scanner.close();
return hexStringToByteArray(keyValue);
}

private 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();
}
private 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);
b[i] = (byte)v;
}
return b;
}

14.4 Store a password in a properties file

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


final String KEY_FILE = "c:/temp/howto.key";
final String PWD_FILE = "c:/temp/howto.properties";
String clearPwd= "my password is hello world";
Properties p1 = new Properties();
p1.put("user", "Real");
String encryptedPwd = CryptoUtils.encrypt(clearPwd, new File(KEY_FILE));
p1.put("pwd", encryptedPwd);
p1.store(new FileWriter(PWD_FILE), "");
// ==================
Properties p2 = new Properties();
p2.load(new FileReader(PWD_FILE));
encryptedPwd = p2.getProperty("pwd");
System.out.println(encryptedPwd);
System.out.println
(CryptoUtils.decrypt(encryptedPwd, new File(KEY_FILE)));
}
}

14.5 Create a checksumTag(s): Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0416.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();

14.5 Create a checksumTag(s): Security

return complete.digest();
}
// see this Howto 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("apachetomcat5.5.17.exe"));
// output :
// 0bb2827c5eacf570b6064e24e0e6653b
// ref :
// http://www.apache.org/dist/
//
tomcat/tomcat5/v5.5.17/bin
//
/apachetomcat5.5.17.exe.MD5
// 0bb2827c5eacf570b6064e24e0e6653b *apachetomcat5.5.17.exe
}
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 {
//
// returns 0 error
//
1 ok (create)
//
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]");
}
}

14.5 Create a checksumTag(s): Security

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);
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. However the CRC32 is not a very
strong way to make sure that a file is not altered.
14.5 Create a checksumTag(s): Security

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);
}
long cs = getChecksumValue(new CRC32(), args[0]);
System.out.println("crc32 " + args[0] + " : " + cs);
}
}

However, MD5 is not secure anymore because researchers have proven that it is possible to
manipulate the original data to get the same MD5 as the original. The alternative is to use SHA1
which is on 160bits (MD5 is 128bits). It's still not perfect but it is better than MD5.
import java.io.*;
import java.security.MessageDigest;
public class ChecksumSHA1 {
public static byte[] createChecksum(String filename) throws
Exception
{
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("SHA1");
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 Howto for a faster way to convert
// a byte array to a HEX string
public static String getSHA1Checksum(String filename) throws Exception {

14.5 Create a checksumTag(s): Security

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(getSHA1Checksum("c:/temp/isapi_redirect1.2.30.dll"));
// output :
// cca9176f72ff56beb1f76c21b1d7daa6be192890
// ref :
//
http://tomcat.apache.org/
//
dev/dist/tomcatconnectors/
//
jk/binaries/win32/jk1.2.30/
//
isapi_redirect1.2.30.dll.sha1
//
// cca9176f72ff56beb1f76c21b1d7daa6be192890 *isapi_redirect1.2.30.dll
}
catch (Exception e) {
e.printStackTrace();
}
}
}

MD5 or SHA1 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/SHA1 sum of the
result to the server.
3. On the server, do the same and compare the MD5/SHA1 sums.
4. If both MD5/SHA1 are identicals then the password is good.

14.6 Get the user nameTag(s): Applet Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0048.html
In application :
public class Test {
public static void main(String args[]) {
System.out.println( System.getProperty("user.name") );
}
}

will print the current user. You can't use this technique to secure your application since it is very to
spoof.
14.6 Get the user nameTag(s): Applet Security

You just need to specify a "user.name" from the command line.


> java Duser.name=Elvis Test
Elvis

As an alternative with 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());
System.out.println(NTSystem.getDomain());
}
}

In Applet there is no way unless you ask for it or use a signed applet. If you have access to a
serverside, something like an ASP page can be used to detect the current NT user name if the
client and the server are configured correcty (SSO).
See this related HowTo for a JSP hack!

14.7 Get username using NT Challenge (NTLM)Tag(s): Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0441.html
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("WWWAuthenticate", "NTLM");
return;
}
if (auth.startsWith("NTLM ")) {
byte[] msg =
new sun.misc.BASE64Decoder().decodeBuffer(auth.substring(5));
int off = 0, length, offset;

14.7 Get username using NT Challenge (NTLM)Tag(s): Security

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("WWWAuthenticate", "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)'>");
out.println(s + "</SPAN>");
}
%></BODY>
NOTES:
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.

A comment from A. Santana : It didn't work for Firefox, so I did a silly workaround in the midtime. I
removed everything is not a word or space... look: s.replaceAll("[^azAZ\s]","");
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
14.7 Get username using NT Challenge (NTLM)Tag(s): Security

14.8 Check if the current user belongs a specific Windows


group/roleTag(s): Security Powerscript
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb0227.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.

Current user is a member of group or role.

NULL

Either group or role is not valid.

14.9 Allow user:password in URLTag(s):


Networking Security Common problems WinAPI/Registry
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../pbdetails/pb0249.html
The following URL syntax is no longer supported in Internet Explorer or in Windows Explorer after
you install the MS04004 Cumulative Security Update for Internet Explorer (832894):
http(s)://username:password@server/resource.ext

This change in the default behavior is also implemented by security updates and service packs that
were released after the 832894 security update.
By default, this new default behavior for handling user information in HTTP or HTTPS URLs applies
only to Windows Explorer and Internet Explorer. To use this new behavior in other programs that
host the Web browser control, create a DWORD value named SampleApp.exe, where
SampleApp.exe is the name of the executable file that runs the program. Set the DWORD value's
value data to 1 in one of the following registry keys.
14.8 Check if the current user belongs a specific Windows group/roleTag(s): Security Powerscript

For all users of the program, set the value in the following registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE

For the current user of the program only, set the value in the following registry key:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE

To disable the new default behavior in Windows Explorer and Internet Explorer, create
iexplore.exe and explorer.exe DWORD values in one of the following registry keys and set their
value data to 0.
For all users of the program, set the value in the following registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE

For the current user of the program only, set the value in the following registry key:
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\
Main\FeatureControl\FEATURE_HTTP_USERNAME_PASSWORD_DISABLE
ref Microsoft Article ID : 834489

14.10 Prompt for password from the consoleTag(s): Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0375.html
A separate thread is used to send to the console the backspace character to erase the lasttyped
character.
import java.io.*;
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 ");
}
}

14.10 Prompt for password from the consoleTag(s): Security

public synchronized void halt() {


running = false;
}
}

Java SE6 provides a buiiltin 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) {
...
}

14.11 Prevent XSS exploitTag(s): Security


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0627.html
According to Wikipedia, XSS exploit is a type of computer security vulnerability found in web
applications which allow code injection by malicious web users into the web pages viewed by
other users. If your WebApp expects a URL like http://www.server.com/app?name=John then a
malicious user can build a special URL like http://www.server.com/app?name=<script> ...
</script> to "inject" his own script into your web app.
This can be be very dangerous if the data is stored into a database and displayed to other users.
Good document on the subject : XSS (Cross Site Scripting) Prevention Cheat Sheet
Here a list of XSS test cases : http://ha.ckers.org/xss.html
There are three ways to deal with this issue.

14.12 Sanitize the input by removing suspicious tags.


This is a naive approach because it's almost impossible to cover everything.
This regex function removes the obvious code to inject unwanted scripting.
public static String sanitize(String string) {
return string
.replaceAll("(?i)<script.*?>.*?</script.*?>", "")
// case 1
.replaceAll("(?i)<.*?javascript:.*?>.*?</.*?>", "") // case 2
.replaceAll("(?i)<.*?\\s+on.*?>.*?</.*?>", "");
// case 3
}

(?i) make it case insensitive


case 1 : <script> are removed
case 2 : javascript: call are removed
14.11 Prevent XSS exploitTag(s): Security

case 3 : remove on* attributes like onLoad or onClick


Nothing beats good validation but then make sure to sanitize the value if it fails before
redisplaying it.
While you can call yourself the method to sanitize the received parameters, you should consider
installing this process into a Java EE filter so the container will automatically do it for you. See this
page at
http://greatwebguy.com/programming/java/simplecrosssitescriptingxssservletfilter/.
You have to be careful. You don't want to remove legitimate string. An input like "prescription" can
be become "preion" if the filter is too strict!

14.13 Sanitize the input based on a policy file.


Based on a policy file, you allow only certain tags and discard everything else.
See http://www.owasp.org/index.php/AntiSamy for a ready to use library.

14.14 Sanitize the output by removing suspicious characters.


The idea is to sanitize a string before displaying it a user. This is done by replacing supicious
characters by the corresponding entity.
The JSTL taglib provides the tag <c:out ... > tag to display a string. This tag will sanitize a string
by default.
<c:out value="${foo}" escapeXml="true" />

The substitutions are :


This JSP will display the script code and the browser will not execute it.
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set var="test" scope="session">
<script>
alert("hello")
</script>
</c:set>
<h1>out with escapeXml=true</h1>
<c:out value="${test}" escapeXml="true" /><br>
<br />

This JSP will not display the script code and the browser execute it.
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<c:set var="test" scope="session">
<script>
alert("hello")
</script>
</c:set>
<h1>out with escapeXml=false</h1>
<c:out value="${test}" escapeXml="false" /><br>

14.13 Sanitize the input based on a policy file.

<br />

With JSF, the tag <h:outputtext ... > provides the same protection.
Also see Java Edition of the OWASP ESAPI Toolkit

14.15 Display a simple username/password Dialog from an


AppletTag(s): Security
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0128.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() {
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

14.15 Display a simple username/password Dialog from an AppletTag(s): Security

("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);
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){

14.15 Display a simple username/password Dialog from an AppletTag(s): Security

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 Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

14.15 Display a simple username/password Dialog from an AppletTag(s): Security

15 Swing
15.1 javaswing

15.2 * Read me *Tag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0193.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.

15.3 Change component default fontTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0335.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));

15 Swing

Swing UI default

15.4 Repaint problem under the mouse cursor (JDK1.2)Tag(s):


Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0206.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.

15.5 Set the LookAndFeelTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0207.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
Motif
Mac
Metal
Basic
Multi

com.sun.java.swing.plaf.windows (no change)


com.sun.java.swing.plaf.motif (no change)
com.sun.java.swing.plaf.mac (no change)
javax.swing.plaf.metal (new)
javax.swing.plaf.basic (new)
javax.swing.plaf.multi (new)

These packages are located in the rt.jar file.

15.4 Repaint problem under the mouse cursor (JDK1.2)Tag(s): Swing

15.6 Use any LookAndFeel on any plateformTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0208.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.
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 nonWindows environment
java Dos.name=windows MySwingApp

to activate Mac LookAndFeel on a nonMac 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 notsosure value.
try {
// sure look and feel
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
// notsosure 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();
}

15.6 Use any LookAndFeel on any plateformTag(s): Swing

15.7 Use a TimerTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0220.html
See this Howto.

15.8 Share ActionEvent handlerTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0212.html
In this example, a JMenu, JToolbar and JButtons on a JFrame are sharing common ActionEvent
handlers.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class
OpenAction
SaveAction
QuitAction

ShareAction extends JFrame {


openAction = new OpenAction();
saveAction = new SaveAction();
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);

15.7 Use a TimerTag(s): Swing

}
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);
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);
}
}

15.7 Use a TimerTag(s): Swing

15.9 Get default values for Swingbased user interfaceTag(s):


Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0507.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
import
import
import
import

java.util.Comparator;
java.util.Iterator;
java.util.Map;
java.util.Set;
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

15.9 Get default values for Swingbased user interfaceTag(s): Swing

15.10 Have a systray icon (Windows)Tag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0612.html
JDK 1.6 provides support for the Systray on the Windows plateform.
A small icon is located at the bottom right of the Desktop.

you can click on it to trigger an action or use this area to display notification.

Use this small image to run this demo :


import
import
import
import

java.awt.*;
java.awt.image.*;
java.awt.event.*;
javax.swing.*;

public class SysTrayDemo {


protected static TrayIcon trayIcon;
private static PopupMenu createTrayMenu() {
ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Bye from the tray");
System.exit(0);
}
};
ActionListener executeListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog
(null, "Popup from the action on the systray!",
"User action", JOptionPane.INFORMATION_MESSAGE);
trayIcon.displayMessage
("Done", "You can do it again if you want!",
TrayIcon.MessageType.INFO);
}
};
PopupMenu menu = new PopupMenu();
MenuItem execItem = new MenuItem("Action...");
execItem.addActionListener(executeListener);
menu.add(execItem);
MenuItem exitItem = new MenuItem("Exit");
exitItem.addActionListener(exitListener);
menu.add(exitItem);
return menu;
}
/**

15.10 Have a systray icon (Windows)Tag(s): Swing

* Loading the image from a file


*/
private static TrayIcon createTrayIconFromFile() {
Image image =
Toolkit.getDefaultToolkit().getImage("/temp/trayrealhowto.jpg");
PopupMenu popup = createTrayMenu();
TrayIcon ti = new TrayIcon(image, "Java System Tray Demo", popup);
ti.setImageAutoSize(true);
return ti;
}
/**
* Loading the image from the classpath
* if in a folder in a jar, remember to add the folder!
* ex. /img/realhowto.jpg
*/
private static TrayIcon createTrayIconFromResource()
throws java.io.IOException {
ClassLoader cldr = SysTrayDemo.class.getClassLoader();
java.net.URL imageURL = cldr.getResource("trayrealhowto.jpg");
Image image = Toolkit.getDefaultToolkit().getImage(imageURL);
PopupMenu popup = createTrayMenu();
TrayIcon ti = new TrayIcon(image, "Java System Tray Demo", popup);
ti.setImageAutoSize(true);
return ti;
}
/**
* using a builtin icon
* we need to convert the icon to an Image
*/
private static TrayIcon createTrayIconFromBuiltInIcon() {
Icon icon = UIManager.getIcon("OptionPane.warningIcon");
PopupMenu popup = createTrayMenu();
Image image = iconToImage(icon);
TrayIcon ti = new TrayIcon(image, "Java System Tray Demo", popup);
ti.setImageAutoSize(true);
return ti;
}
static Image iconToImage(Icon icon) {
if (icon instanceof ImageIcon) {
return ((ImageIcon)icon).getImage();
} else {
int w = icon.getIconWidth();
int h = icon.getIconHeight();
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gd.getDefaultConfiguration();
BufferedImage image = gc.createCompatibleImage(w, h);
Graphics2D g = image.createGraphics();
icon.paintIcon(null, g, 0, 0);
g.dispose();
return image;
}
}
public static void main(String[] args) throws Exception {
if (!SystemTray.isSupported()) {
System.out.println
("System tray not supported on this platform");
System.exit(1);

15.10 Have a systray icon (Windows)Tag(s): Swing

}
try {
SystemTray sysTray = SystemTray.getSystemTray();
trayIcon = createTrayIconFromFile();
//trayIcon = createTrayIconFromResource();
//trayIcon = createTrayIconFromBuiltInIcon();
sysTray.add(trayIcon);
trayIcon.displayMessage("Ready",
"Tray icon started and tready", TrayIcon.MessageType.INFO);
}
catch (AWTException e) {
System.out.println("Unable to add icon to the system tray");
System.exit(1);
}
}
}

This code can load the icon from a file, a file in the classpath (resource) or use a builtin icon in
the JDK.

15.11 Close a JFrame under conditionTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0340.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();
}

15.11 Close a JFrame under conditionTag(s): Swing

}
}
} );
pack();
setVisible( true );
}
public static void main(String args[]) {
new CloseOrNot();
}
}

15.12 Maximize a JFrameTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0479.html
import java.awt.*;
import javax.swing.*;
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);
}
}

15.13 Capture System.out into a JFrameTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0435.html
import java.awt.*;

15.12 Maximize a JFrameTag(s): Swing

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";
public static final String AUTHOR =
"Real Gagnon edited by William Denniss";

private
private
private
private
private
private

boolean catchErrors;
boolean logFile;
String fileName;
int width;
int height;
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

15.12 Maximize a JFrameTag(s): Swing

* @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
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();
}
}
}

15.12 Maximize a JFrameTag(s): Swing

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();
}
}

15.14 Remove the titlebar of JInternalFrameTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0333.html
((javax.swing.plaf.basic.BasicInternalFrameUI)
myInternalFrame.getUI()).setNorthPane(null);

15.15 Have borders on a JWindow/JFrameTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0204.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
import
import
import

javax.swing.*;
javax.swing.border.*;
java.awt.event.*;
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"));

15.14 Remove the titlebar of JInternalFrameTag(s): Swing

win.setSize(200,200);
win.setVisible(true);
}
}

15.16 Display HTML in a JScrollPaneTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0205.html
The JTextPane can display simple HTML page.
import
import
import
import

javax.swing.*;
java.awt.*;
java.awt.event.*;
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);
}
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"));
...

15.16 Display HTML in a JScrollPaneTag(s): Swing

15.17 Use a JOptionPaneTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0376.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
0
1
2

WINDOW CLOSED the X PRESSED


YES and OK
NO
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){
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 ?");

15.17 Use a JOptionPaneTag(s): Swing

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 );
}
}

15.18 Localize a JOptionPane dialogTag(s):


Internationalization Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0138.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=Voulezvous sauvegarder vos donnees

Then
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);

15.18 Localize a JOptionPane dialogTag(s): Internationalization Swing

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);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}

15.18 Localize a JOptionPane dialogTag(s): Internationalization Swing

15.19 Customize JOptionPane buttonsTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0310.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");
}

15.20 Localize a JFileChooserTag(s):


Internationalization Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0299.html
Modern Swing release have now builtin readytouse 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

15.19 Customize JOptionPane buttonsTag(s): Swing

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]
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);

15.19 Customize JOptionPane buttonsTag(s): Swing

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
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)

15.19 Customize JOptionPane buttonsTag(s): Swing

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);
}
}

15.21 Select a directory with a JFileChooserTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0370.html
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);

15.21 Select a directory with a JFileChooserTag(s): Swing

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 {
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);
}
}

15.22 Disable the JFileChooser's "New folder" buttonTag(s):


Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0569.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
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
java.util.*;

public class DemoJFileChooser extends JPanel

15.22 Disable the JFileChooser's "New folder" buttonTag(s): Swing

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);
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);

15.22 Disable the JFileChooser's "New folder" buttonTag(s): Swing

}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
}

15.23 Validate a filename from a JFileChooserTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0568.html
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);

15.23 Validate a filename from a JFileChooserTag(s): Swing

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("");
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);
}
}

15.24 Make a JFrame looks like a JDialogTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0582.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
import
import
import

java.awt.Dimension;
java.awt.event.WindowAdapter;
java.awt.event.WindowEvent;
java.awt.event.ActionListener;

import
import
import
import
import

javax.swing.JFrame;
javax.swing.JLabel;
javax.swing.JButton;
javax.swing.JRootPane;
javax.swing.SwingUtilities;

public class JFrameWithNoMinMax extends JFrame {

15.24 Make a JFrame looks like a JDialogTag(s): Swing

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);
}
});
}
}

15.25 Make a JFrame always visibleTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0638.html
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Test2 {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello!!");
frame.setAlwaysOnTop( true );
frame.setLocationByPlatform( true );
frame.add(new JLabel(" Always visible") );
frame.pack();
frame.setVisible(true);
}
}

15.25 Make a JFrame always visibleTag(s): Swing

15.26 Show a JFrame on a specific screen in a dual monitor


configuration Tag(s): Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javashowjframeonaspecificscreen.html
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DualMonitor {
public static void main(String ... args) {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] gs = ge.getScreenDevices();
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component)
null, "Found : " + gs.length, "screen detected ?",
javax.swing.JOptionPane.DEFAULT_OPTION);
for (int j = 0; j <gs.length; j++) {
GraphicsDevice gd = gs[j];
JFrame frame = new JFrame(gd.getDefaultConfiguration());
frame.setTitle("I'm on monitor #" + j);
frame.setSize(400,200);
frame.add(new JLabel("hello world"));
frame.setVisible(true);
}
}
}

15.27 Make a JFrame not visible in the the TaskBar Tag(s):


Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javamakeaframenotvisibleinthetaskbar.html
import javax.swing.JFrame;
public class NotInTaskbar extends JFrame {
NotInTaskbar() {
setType(Type.UTILITY); // ***
setVisible(true);
setSize(200, 200);
setTitle("Not Visible in the Taskbar");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

15.26 Show a JFrame on a specific screen in a dual monitor configuration Tag(s): Swing

public static void main(String[] args){


new NotInTaskbar();
}
}

or use a JDialog instead.


import javax.swing.JDialog;
public class NotInTaskbar extends JDialog {
NotInTaskbar() {
setVisible(true);
setSize(200, 200);
setTitle("Not Visible in the Taskbar");
}
public static void main(String[] args){
new NotInTaskbar();
}
}

15.28 Based on JTextField content, enable or disable a


JButtonTag(s): Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0196.html
import
import
import
import

java.awt.*;
javax.swing.*;
javax.swing.text.*;
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 {

15.28 Based on JTextField content, enable or disable a JButtonTag(s): Swing

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);
}
}

15.29 Apply special filter to a JtextFieldTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0197.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) {

15.29 Apply special filter to a JtextFieldTag(s): Swing

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) {
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));

15.29 Apply special filter to a JtextFieldTag(s): Swing

//
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);
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
import
import
import

java.awt.Container;
javax.swing.*;
javax.swing.text.*;
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);
}
}

15.29 Apply special filter to a JtextFieldTag(s): Swing

It's also possible to provide simple validation. For example, specify a field to accept only numeric
with a minimum and a maximum value. If the input is not valid then a warning beep is produced.
import
import
import
import

java.awt.Container;
javax.swing.*;
javax.swing.text.*;
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));
NumberFormatter nf = new NumberFormatter();
nf.setValueClass(Integer.class);
nf.setMinimum(new Integer(0));
nf.setMaximum(new Integer(100));
JFormattedTextField field = new JFormattedTextField(nf);
field.setBorder(BorderFactory.createLineBorder(Color.black));
content.add(field);
f.setSize(300, 100);
f.pack();
f.setVisible(true);
}
}

15.30 Limit JTextField input to a maximum lengthTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0198.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

15.30 Limit JTextField input to a maximum lengthTag(s): Swing

(int offset, String str, AttributeSet attr)


throws BadLocationException {
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));
}
}

15.31 Validate a value on the lostFocus eventTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0199.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());
//

15.31 Validate a value on the lostFocus eventTag(s): Swing

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);
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
import
import
import

java.awt.*;
java.util.*;
java.awt.event.*;
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 ();

15.31 Validate a value on the lostFocus eventTag(s): Swing

f.pack();
f.show();
}
}
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent e) {
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;
}
}
...

15.31 Validate a value on the lostFocus eventTag(s): Swing

15.32 Make sure that my jTextfield has the focus when a


JFrame is createdTag(s): Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0200.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.*;
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();
}
}

15.32 Make sure that my jTextfield has the focus when a JFrame is createdTag(s): Swing

15.33 Stop the beep on JFormattedTextFieldTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0427.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() {}
...
}

15.34 Right justified JTextfield contentTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0493.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);
// Rightjustify the text
textfield.setHorizontalAlignment(JTextField.RIGHT);
getContentPane().add(textfield);
}
}

15.35 Set the focus on a particuliar JTextFieldTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0510.html
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myJTextField.requestFocus();
}
});

15.33 Stop the beep on JFormattedTextFieldTag(s): Swing

15.36 Make JTextField unselectableTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0546.html
import
import
import
import

java.awt.*;
java.util.*;
java.awt.event.*;
javax.swing.*;

class UnselectableJTextField extends JFrame {


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);
}
}
}

15.36 Make JTextField unselectableTag(s): Swing

15.37 Disable copy paste functionality on JTextFieldTag(s):


Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0644.html
import
import
import
import

java.awt.event.KeyEvent;
java.awt.event.InputEvent;
java.awt.event.WindowAdapter;
java.awt.event.WindowEvent;

import
import
import
import
import
import

javax.swing.JFrame;
javax.swing.JTextField;
javax.swing.KeyStroke;
javax.swing.text.DefaultEditorKit;
javax.swing.text.JTextComponent;
javax.swing.text.Keymap;

public class Test {


private JFrame myFrame;
private JTextField myTextField;
public void doit() {
myFrame = new JFrame("no cut and paste");
myFrame.setSize(400, 200);
myFrame.setLocation(100, 100);
myFrame.setLayout(new java.awt.FlowLayout());
myTextField = new JTextField(20);
JTextComponent.KeyBinding[] newBindings = {
new JTextComponent.KeyBinding(
KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK),
DefaultEditorKit.beepAction),
new JTextComponent.KeyBinding(
KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK),
DefaultEditorKit.beepAction),
new JTextComponent.KeyBinding(
KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK),
DefaultEditorKit.beepAction)
};
Keymap k = myTextField.getKeymap();
JTextComponent.loadKeymap(k, newBindings, myTextField.getActions());
myFrame.add(myTextField);
myFrame.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
myTextField.requestFocus();
}
public void windowActivated( WindowEvent e ){
boolean focus = myTextField.requestFocusInWindow();
if(focus){
System.out.println("Focus successful");
}
else{
System.out.println("Focus unsuccessful");
}
}
}
);

15.37 Disable copy paste functionality on JTextFieldTag(s): Swing

myFrame.setVisible(true);
}
public static void main(String args[]) {
new Test().doit();
}
}

15.38 Use a JTree to navigate in a siteTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0209.html
This Howto 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;
}
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;

15.38 Use a JTree to navigate in a siteTag(s): Swing

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);
_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
import
import
import
import
import

javax.swing.*;
javax.swing.tree.*;
javax.swing.event.*;
java.awt.event.*;
java.awt.*;
java.util.*;

15.38 Use a JTree to navigate in a siteTag(s): Swing

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");
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) {

15.38 Use a JTree to navigate in a siteTag(s): Swing

// 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))
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")));

15.38 Use a JTree to navigate in a siteTag(s): Swing

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
(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();

15.38 Use a JTree to navigate in a siteTag(s): Swing

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.
[treedata.txt]
0 "Welcome | Bienvenue" "welcome.html"
0 "Java Howto" "" "0" "1"
1 "What's new" "javanew.html" "2" "2"
1 "General" "" "0" "1"
2 "part 1" "javag1.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">

15.38 Use a JTree to navigate in a siteTag(s): Swing

<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/xjavaapplet;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/plugininstall.html">
<NOEMBED>
No JDK 1.2 support for APPLET!!
</NOEMBED>
</EMBED>
</BODY></HTML>

Finally, you may want to grab these images used in this Howto .
root.gif

fclose.jpg

fopen.jpg

fpage.jpg

15.39 Expand or collapse a JTreeTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0210.html
import
import
import
import
import

javax.swing.*;
javax.swing.tree.*;
java.awt.event.*;
java.awt.*;
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);

15.39 Expand or collapse a JTreeTag(s): Swing

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);
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()) {

15.39 Expand or collapse a JTreeTag(s): Swing

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;
}
}
}

15.40 Have a popup attached to a JTreeTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0211.html
import
import
import
import

java.awt.event.ActionEvent;
java.awt.event.ActionListener;
java.awt.event.MouseAdapter;
java.awt.event.MouseEvent;

import javax.swing.JComponent;

15.40 Have a popup attached to a JTreeTag(s): Swing

import
import
import
import
import
import
import

javax.swing.JMenuItem;
javax.swing.JPopupMenu;
javax.swing.JTree;
javax.swing.tree.DefaultMutableTreeNode;
javax.swing.tree.DefaultTreeModel;
javax.swing.tree.TreeNode;
javax.swing.tree.TreePath;

public 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");
popup.add(mi);
mi = new JMenuItem("Remove this node");
mi.addActionListener(this);
mi.setActionCommand("remove");
popup.add(mi);
popup.setOpaque(true);
popup.setLightWeightPopupEnabled(true);
final JTree thisTree = this;
addMouseListener (
new MouseAdapter () {
public void mouseReleased( MouseEvent e ) {
// thanks to urbanq for the bug fix!
int row = thisTree.getRowForLocation(e.getX(), e.getY());
if(row == 1)
return;
thisTree.setSelectionRow(row);
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);
}

15.40 Have a popup attached to a JTreeTag(s): Swing

}
}
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
import javax.swing.tree.*;
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 WindowAdapter() {
public void windowClosing(WindowEvent e) {
Window win = e.getWindow();
win.setVisible(false);
System.exit(0);
}
});
}
}

15.41 Traverse a JTreeTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0313.html
15.41 Traverse a JTreeTag(s): Swing

import
import
import
import

javax.swing.*;
javax.swing.tree.*;
java.awt.event.*;
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);
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) {

15.41 Traverse a JTreeTag(s): Swing

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.");
}
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 );
}
}
}
}

15.42 Show dotted lines in a JTreeTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0325.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

15.42 Show dotted lines in a JTreeTag(s): Swing

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.

15.43 Explore directories with a JTreeTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0324.html
import
import
import
import
import
import

javax.swing.*;
javax.swing.tree.*;
java.awt.event.*;
java.awt.*;
java.util.*;
java.io.*;

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");

15.43 Explore directories with a JTreeTag(s): Swing

}
}
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());
}
}

15.44 Prevent JTree collapsingTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0339.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");
}
});

15.45 Single selection in a JTreeTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0395.html

15.44 Prevent JTree collapsingTag(s): Swing

myJTree.getSelectionModel().
setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);

Also you may want to disable the CTRLA 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");

15.46 Reduce JTree children indentationTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0398.html
BasicTreeUI basicTreeUI = (BasicTreeUI) myJTree.getUI();
basicTreeUI.setRightChildIndent(10);

15.47 Use + or for JTree IconsTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0517.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.

15.46 Reduce JTree children indentationTag(s): Swing

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
import
import
import
import

javax.swing.*;
javax.swing.tree.*;
java.awt.event.*;
java.awt.*;
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",
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);
}
}

15.46 Reduce JTree children indentationTag(s): Swing

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 :

15.48 Change the JTable header colorTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0334.html
import java.awt.*;
import javax.swing.*;
import javax.swing.table.JTableHeader;
public class SimpleJTable extends

JFrame {

private JPanel
topPanel;
private JTable
table;
private JScrollPane scrollPane;
SimpleJTable() {
setTitle( "Simple Table Application" );
setSize( 300, 200 );
topPanel = new JPanel();
topPanel.setLayout( new BorderLayout() );
getContentPane().add( topPanel );
Object[][] cellData = {
{"row1col1", "row1col2"},
{"row2col1", "row2col2"},
{"row3col1", "row3col2"},
{"row4col1", "row4col2"},
{"row5col1", "row5col2"}};
String[] columnNames = {"col1", "col2"};
table = new JTable(cellData, columnNames);

15.48 Change the JTable header colorTag(s): Swing

scrollPane = new JScrollPane( table );


topPanel.add( scrollPane, BorderLayout.CENTER );
JTableHeader anHeader = table.getTableHeader();
anHeader.setForeground(new Color(0).yellow);
anHeader.setBackground(new Color(0).black);

}
public static void main(String ... arg) {
SimpleJTable mainFrame = new SimpleJTable();
mainFrame.setVisible( true );
}
}

15.49 Double click on a JTableTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0336.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();

15.49 Double click on a JTableTag(s): Swing

}
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" );
}
}
} );
}
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();
}
}

15.49 Double click on a JTableTag(s): Swing

15.50 Read a data file into a JTableTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0213.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
import
import
import
import

javax.swing.*;
javax.swing.table.*;
javax.swing.event.*;
java.io.*;
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();
}

15.50 Read a data file into a JTableTag(s): Swing

}
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;
}
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
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
java.io.*;
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);

15.50 Read a data file into a JTableTag(s): Swing

}
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);
}
}

15.51 Disable row selection in a JTableTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0338.html
aTable.setRowSelectionAllowed(false);
aTable.setColumnSelectionAllowed(false);
aTable.setCellSelectionEnabled(false);

15.52 Read a data file into a JTable and reload if data file have
changedTag(s): Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0214.html
15.51 Disable row selection in a JTableTag(s): Swing

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 Howto. 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
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
java.io.*;
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());
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);

15.51 Disable row selection in a JTableTag(s): Swing

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
import
import
import

javax.swing.Timer;
java.awt.event.*;
java.io.*;
java.util.*;

public class DataFileWatchdog extends Observable


implements ActionListener {
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.

15.51 Disable row selection in a JTableTag(s): Swing

15.53 Hide a column in JTableTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0216.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)},
};
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);
}

15.53 Hide a column in JTableTag(s): Swing

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.expertsexchange.com/Programming/Programming_Languages/Java/Q_20394392.html

15.54 Scroll a JTable to the last rowTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0291.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();

15.54 Scroll a JTable to the last rowTag(s): Swing

setRowSelectionInterval(row, row);
getModel().fireTableDataChanged(); // notify the model
}

15.55 Transfer a ResultSet to a JTableTag(s): JDBC Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0309.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);

15.56 Have on a JScrollPane/JTable an horizontal


JScrollbarTag(s): Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0397.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);

15.55 Transfer a ResultSet to a JTableTag(s): JDBC Swing

15.57 Make a JList select an item on doubleclick or the ENTER


keyTag(s): Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0201.html
import javax.swing.*;
import java.awt.event.*;
public class ActionJList extends JList {
/*
** sends ACTION_PERFORMED event for doubleclick
** 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,
ob[0].toString()));
ke.consume();
}
}
});
this.setSelectedIndex(0);
}
public void addActionListener(ActionListener al){

15.57 Make a JList select an item on doubleclick or the ENTER keyTag(s): Swing

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);
}
}

15.58 Make a JList like a scrolling text displayTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0202.html
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
java.util.*;

15.58 Make a JList like a scrolling text displayTag(s): Swing

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);
}
}

15.59 Have images in a JListTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0203.html
This snippet uses these 2 images
import javax.swing.*;
import java.awt.*;

15.59 Have images in a JListTag(s): Swing

import java.util.*;
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 Howto use the default layout, so each line line in the JList are centered. The version
below is showing each line left justified instead.
import
import
import
import

javax.swing.*;
javax.swing.border.*;
java.awt.*;
java.util.*;

public class JListWithImages extends JList {

15.59 Have images in a JListTag(s): Swing

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(new FlowLayout(FlowLayout.LEFT));
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));
jp2.add(new JLabel(new ImageIcon("gumby.gif")));
jp2.add(new JLabel("Another line for Gumby"));
jp2.add(new JLabel(new ImageIcon("gumby2.gif")));

// NEW

// NEW

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;
}
}
}

15.60 Add a row and clear a JListTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0217.html
15.60 Add a row and clear a JListTag(s): Swing

import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
java.util.*;

public class ClearJList extends JPanel


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);
}
}

15.61 Sort a JListTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0218.html
15.61 Sort a JListTag(s): Swing

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{
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 ) {

15.61 Sort a JListTag(s): Swing

tmp = strArray[i];
strArray[i] = strArray[j];
strArray[j] = tmp;
}
}
}
}
public static void main(String s[]) {
JFrame frame = new JFrame("Sort JList");
SortJList panel = new SortJList();
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.getContentPane().add(panel,"Center");
frame.setSize(200,200);
frame.setVisible(true);
}
}

15.62 Double click on a JListTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0219.html
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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);

15.62 Double click on a JListTag(s): Swing

}
}
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);
System.out.println("Double clicked on " + item);
}
}
}

15.63 Have a PopUp on a JListTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0393.html
import
import
import
import

javax.swing.*;
java.awt.event.*;
java.awt.*;
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"));

15.63 Have a PopUp on a JListTag(s): Swing

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);
}
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);
}
}

15.64 Make a JLabel selectable with the mouseTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0296.html
Simulate the "look and feel" of a JLabel with a JTextfield.
15.64 Make a JLabel selectable with the mouseTag(s): Swing

import javax.swing.*;
import java.awt.*;
public class SelectableJLabel extends JPanel {
public SelectableJLabel() {
// a regular JLabel
add(new JLabel("You can't select me"));
// a lookalike 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);
}
}

15.65 Change JLabel background colorTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0304.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.setBackground(myColor)

15.65 Change JLabel background colorTag(s): Swing

15.66 Bold / Unbold a JLabelTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0349.html
JLabel label = new JLabel("I'm bold");
Font font = new Font("Courier", Font.BOLD,12);
label.setFont(font);

You can change the bold attribute after the creation.


Font f = label.getFont();
// bold
label.setFont(f.deriveFont(f.getStyle() | Font.BOLD));
// unbold
label.setFont(f.deriveFont(f.getStyle() &~Font.BOLD));
// toggle bold
label.setFont(f.deriveFont(f.getStyle() ^ Font.BOLD));
Thanks to S.Vespo for the bug fix.

15.67 Multiline JLabelTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0315.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>");

15.68 Underline a stringTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0326.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).
15.66 Bold / Unbold a JLabelTag(s): Swing

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();
}
}

15.69 Update a JLabelTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0392.html
myLabel.setText("Real's HowTo");
SwingUtilities.updateComponentTreeUI(myLabel);

15.69 Update a JLabelTag(s): Swing

15.70 Display a blinking JLabelTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0616.html
import
import
import
import

java.awt.Color;
java.awt.event.*;
javax.swing.*;
javax.swing.Timer;

public class BlinkLabel extends JLabel {


private static final long serialVersionUID = 1L;
private static final int BLINKING_RATE = 1000; // in ms
private boolean blinkingOn = true;
public BlinkLabel(String text) {
super(text);
Timer timer = new Timer( BLINKING_RATE , new TimerListener(this));
timer.setInitialDelay(0);
timer.start();
}
public void setBlinking(boolean flag) {
this.blinkingOn = flag;
}
public boolean getBlinking(boolean flag) {
return this.blinkingOn;
}

private class TimerListener implements ActionListener {


private BlinkLabel bl;
private Color bg;
private Color fg;
private boolean isForeground = true;
public TimerListener(BlinkLabel bl) {
this.bl = bl;
fg = bl.getForeground();
bg = bl.getBackground();
}
public void actionPerformed(ActionEvent e) {
if (bl.blinkingOn) {
if (isForeground) {
bl.setForeground(fg);
}
else {
bl.setForeground(bg);
}
isForeground = !isForeground;
}
else {
// here we want to make sure that the label is visible
// if the blinking is off.
if (isForeground) {
bl.setForeground(fg);
isForeground = false;
}
}

15.70 Display a blinking JLabelTag(s): Swing

}
}
// for testing
private static void createAndShowUI() {
JFrame frame = new JFrame("BlinkLabel");
final BlinkLabel bl = new BlinkLabel("I'm blinking!");
frame.getContentPane().setLayout(new java.awt.FlowLayout());
frame.getContentPane().add(bl);
JButton b = new JButton("toogle blink");
b.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ae) {
bl.blinkingOn = !bl.blinkingOn;
}
});
frame.getContentPane().add(b);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable(){
public void run(){
createAndShowUI();
}
});
}
//
}

15.71 Set the cursor position in a JTextAreaTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0332.html
To the top
myJTextArea.setCaretPosition(0);

To the end
myJTextArea.setCaretPosition(myJTextArea.getDocument().getLength());

15.71 Set the cursor position in a JTextAreaTag(s): Swing

15.72 Have Multiline string in a JToolTipTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0337.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>");

15.73 Change Tooltip colorTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0365.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.

15.74 Change a JTooltip fontTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0529.html
import
import
import
import

javax.swing.*;
javax.swing.plaf.*;
java.awt.event.*;
java.awt.*;

public class TooltipInSwing extends JFrame {


public TooltipInSwing() {
super("TooltipInSwing");

15.72 Have Multiline string in a JToolTipTag(s): Swing

setSize(400, 300);
getContentPane().setLayout(new FlowLayout());
// 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();
}
}

15.75 Keep a JTooltip visibleTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0528.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.

15.75 Keep a JTooltip visibleTag(s): Swing

ToolTipManager.sharedInstance().setDismissDelay(Integer.MAX_VALUE);
getContentPane().add(b1);
WindowListener wndCloser = new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
public static void main(String args[]){
new TooltipInSwing();
}
}

15.76 Display icon associated with an executableTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0439.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 :

15.76 Display icon associated with an executableTag(s): Swing

Second technique
import
import
import
import

java.io.*;
javax.swing.*;
java.awt.*;
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
import
import
import

java.io.*;
javax.swing.*;
java.awt.*;
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 :

15.76 Display icon associated with an executableTag(s): Swing

output for a file :

15.77 Have items in JMenubar at rightmost positionTag(s):


Swing
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0486.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));

15.77 Have items in JMenubar at rightmost positionTag(s): Swing

frame.setJMenuBar(menuBar);
frame.setSize(300,300);
frame.setVisible(true);
}
}

15.78 Have an JButton with an ImageTag(s): Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0548.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 :

15.78 Have an JButton with an ImageTag(s): Swing

15.79 Trigger a click on a ButtonTag(s): AWT Swing


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0468.html
In this example, when we click on a Button, we trigger the action attached to the another Button.
Regular AWT (applet)
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 (japplet)


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestEventSwing extends JApplet implements ActionListener {

15.79 Trigger a click on a ButtonTag(s): AWT Swing

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, we have visual effect on b1!
b1.doClick();
}
}
}

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

15.79 Trigger a click on a ButtonTag(s): AWT Swing

16 Thread
16.1 javathread

16.2 Pipe the output of a thread to the input of another


oneTag(s): Thread
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0140.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 |
++
(PRODUCE)

++
| thread B |
++
(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();
}

16 Thread

public abstract boolean dataConsumption();


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);
}

16 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) {}
}
}

16.3 Pipe the output of a thread to the input of other


threadsTag(s): Thread
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0141.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 |
++
(produce)

++
> | thread B |
|
++
|
(consume)
|
|
|
++
+ > | thread C |
++

(CONSUME)

The ProduceData.class and ConsumeData.class are the same as the previous JAVA Howto.
[AtomicInputStream.java]
import java.io.*;

16.3 Pipe the output of a thread to the input of other threadsTag(s): Thread

public class AtomicInputStream extends PipedInputStream {


int atom = 0;
AtomicInputStream(int atom) {
super();
this.atom = atom;
}
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;
}

16.3 Pipe the output of a thread to the input of other threadsTag(s): Thread

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]);
}
}
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.

16.4 Wait the for the completion of a threadTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0142.html
public class testThread implements Runnable {
int i;

16.4 Wait the for the completion of a threadTag(s): Thread

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");
}
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();
}
}
}

16.5 Control a thread from outsideTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0143.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) {}

16.5 Control a thread from outsideTag(s): Thread

}
if (state == STOP)
return false;
return true;
}
public void run() {
while true {
doSomething();
if (!checkState())
break;
}
}

16.6 Create a Timer objectTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0144.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.*;

16.6 Create a Timer objectTag(s): Thread

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());
}
}
}

16.7 Pause the executionTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0145.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");

16.7 Pause the executionTag(s): Thread

Wait.manySec(5);
System.out.println("Done");
}
}

16.8 Execute a method at a specified time intervalTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0146.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
import
import
import

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

public class AnnoyingPopUps extends Applet implements


ActionListener {
Button b1, b2;
DelayedMethod dm;
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

16.8 Execute a method at a specified time intervalTag(s): Thread

(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) {}
}
}
}
}

Want to Try it?


NOTE: Check this Howto to achieve to same goal by using the Timer object.

16.9 Execute a process at regular intervalTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0595.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;

16.9 Execute a process at regular intervalTag(s): Thread

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.");
}
}
}
}

16.10 Handle concurrent read/writeTag(s): Thread


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0373.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 {

16.10 Handle concurrent read/writeTag(s): 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)
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(;;){

16.10 Handle concurrent read/writeTag(s): Thread

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();
}
}
}
}

16.11 Communicate between threads using a QueueTag(s):


Thread
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0555.html
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 multithreaded 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;

16.11 Communicate between threads using a QueueTag(s): Thread

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 endofdata 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());
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());

16.11 Communicate between threads using a QueueTag(s): Thread

}
}
}

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
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread

p1
c1
c2
c3
c4
c5
c6
c7
c8
c9

=
=
=
=
=
=
=
=
=
=

new
new
new
new
new
new
new
new
new
new

Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new

PrepareProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
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.");
}
}

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 multithreaded 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.*;

16.11 Communicate between threads using a QueueTag(s): Thread

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());
// 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()

16.11 Communicate between threads using a QueueTag(s): Thread

+ " " + 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
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread

p1
c1
c2
c3
c4
c5
c6
c7
c8
c9

=
=
=
=
=
=
=
=
=
=

new
new
new
new
new
new
new
new
new
new

Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new
Thread(new

PrepareProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
DoProduction(q));
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.");
}
}

16.11 Communicate between threads using a QueueTag(s): Thread

16.12 Get a unique identifierTag(s): String/Number Thread Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0518.html

16.13 Using java.rmi.dgc.VMID


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
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

16.14 Using java.util.UUID


In 1.5, you have java.util.UUID which is less esotoric.
public class TestUUID {
public static void main(String arg[]) {
System.out.println(java.util.UUID.randomUUID());
// output : dedc3f576ce14504a92f640d8d9d23c9
}
}

This is probably the preferred method.


16.12 Get a unique identifierTag(s): String/Number Thread Varia

MiniFAQ on the subject : http://www.asciiarmor.com/post/33736615/javautiluuidminifaq

16.15 Using Apache commons


If you need compatibility with 1.4 then the org.apache.commons.id.uuid is an option.

16.16 Using java.util.concurrent.AtomicLong


A simple numerical id, start at zero and increment by one.
import java.util.concurrent.AtomicLong;
public class Descriptor {
private static final AtomicLong nextId = new AtomicLong();
private static long nextId() {
return nextId.getAndIncrement();
}
}

See also this HowTo for unique numerical id based on the system time.

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

16.15 Using Apache commons

17 Varia
17.1 javavaria

17.2 Use System time to generate unique IDTag(s): Date and


Time Date and Time Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0385.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

17.3 Get a unique identifierTag(s): String/Number Thread Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0518.html

17.4 Using java.rmi.dgc.VMID


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
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.

17 Varia

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

17.5 Using java.util.UUID


In 1.5, you have java.util.UUID which is less esotoric.
public class TestUUID {
public static void main(String arg[]) {
System.out.println(java.util.UUID.randomUUID());
// output : dedc3f576ce14504a92f640d8d9d23c9
}
}

This is probably the preferred method.


MiniFAQ on the subject : http://www.asciiarmor.com/post/33736615/javautiluuidminifaq

17.6 Using Apache commons


If you need compatibility with 1.4 then the org.apache.commons.id.uuid is an option.

17.7 Using java.util.concurrent.AtomicLong


A simple numerical id, start at zero and increment by one.
import java.util.concurrent.AtomicLong;
public class Descriptor {
private static final AtomicLong nextId = new AtomicLong();
private static long nextId() {
return nextId.getAndIncrement();
}
}

17.5 Using java.util.UUID

See also this HowTo for unique numerical id based on the system time.

17.8 Get the hard disk serial number or Motherboard serial


numberTag(s): Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0580.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 onthefly 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/enus/library/aa389273.aspx for complete list.

17.9 Motherboard serial number


import
import
import
import

java.io.File;
java.io.FileWriter;
java.io.BufferedReader;
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();

17.8 Get the hard disk serial number or Motherboard serial numberTag(s): Varia

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);
}
}

17.10 Hard disk serial number


This serial number is created by the OS where formatting the drive and it's not the manufacturer
serial number. It's unique, because it is created on the fly based on the current time information.
AFAIK, there is no API that return that the manufacturer SN. At best, the SN of the HD firmware can
be read but this will involve some very lowlevel API calls. Keep in mind that even if you get that
number, there is no warranty that it will be unique since each manufacturer can assign the SN as
they wish.
import
import
import
import

java.io.File;
java.io.FileWriter;
java.io.BufferedReader;
java.io.InputStreamReader;

public class DiskUtils {


private DiskUtils() { }
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;

17.10 Hard disk serial number

}
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 properties : objDrive.AvailableSpace/DriveType/FileSystem/IsReady

17.11 Sort an arrayTag(s): Language Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0008.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

17.11 Sort an arrayTag(s): Language Varia

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]);
}
}
}
public static class ASCIIComparer implements ArraySorter.Comparer {
public int compare(Object a, Object b) {
return ((String)a).compareTo((String)b);
}
}
}

JDK1.4 casesensitive
String[] myArray = new String[] {"foo","bar","baz"};
java.util.Arrays.sort(myArray);

caseinsensitive

17.11 Sort an arrayTag(s): Language Varia

String[] myArray = new String[] {"foo","Bar","baz"};


java.util.Arrays.sort(myArray, java.text.Collator.getInstance());

17.12 Sort a String arrayTag(s): Internationalization Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0343.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 {
static String [] words = { "Ral", "Real", "Raoul", "Rico" };
public static void main(String args[]) throws Exception {
try {
Writer w = getWriter();
w.write("Before :\n");
for (String s : words) {
w.write(s + " ");
}
java.util.Arrays.sort(words);
w.write("\nAfter :\n");
for (String s : words) {
w.write(s + " ");
}
w.flush();
w.close();
}
catch(Exception e){
e.printStackTrace();
}
}

17.12 Sort a String arrayTag(s): Internationalization Varia

// useful to output accentued characters to the console


public static Writer getWriter() throws UnsupportedEncodingException {
if (System.console() == null) {
Writer w =
new BufferedWriter
(new OutputStreamWriter(System.out, "Cp850"));
return w;
}
else {
return System.console().writer();
}
}
}

The output is :
Before :
Ral Real Raoul Rico
After :
Raoul Real Rico Ral

which is wrong since we expect to find "Ral" after "Real".


To solve the problem , replace
java.util.Arrays.sort(words);

by
java.util.Arrays.sort(words, java.text.Collator.getInstance(java.util.Locale.FRENCH));
// or
// java.util.Arrays.sort(words, java.text.Collator.getInstance());

and the output will be :


Before :
Ral Real Raoul Rico
After :
Raoul Real Ral Rico

Or you can do it the long way :


import java.util.Locale;
import java.text.Collator;
...
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];

17.12 Sort a String arrayTag(s): Internationalization Varia

strArray[j] = tmp;
}
}
}
}

See this HowTo

17.13 Do a selection sortTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0009.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;
}
}

17.13 Do a selection sortTag(s): Varia

17.14 Validate a Social Security Number (canadian)Tag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0033.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.length1; 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.length1) {
k = digit[i+1] * 2;
if (k>9) k = (k10) + 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.length1] + mod;
// if the checksum is divisible by 10 then it's valid
return ((checksum % 10) == 0);
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
else {
return false;
}
}
/**
* Check if number is valid
*/
public static boolean isNumber(String n) {
try {

17.14 Validate a Social Security Number (canadian)Tag(s): Varia

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."));
}
}

17.15 Validate a Credit Card NumberTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0034.html
import java.util.*;
import java.io.*;
public class CCUtils {
public static final int
public static final int
public static final int
public static final int
public static final int
public static final int

INVALID
VISA
MASTERCARD
AMERICAN_EXPRESS
EN_ROUTE
DINERS_CLUB

=
=
=
=
=
=

private static final String [] cardNames =


{
"Visa" ,
"Mastercard",
"American Express",
"En Route",
"Diner's CLub/Carte Blanche",
};

17.15 Validate a Credit Card NumberTag(s): Varia

1;
0;
1;
2;
3;
4;

/**
* 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
String
String
String

digit1
digit2
digit3
digit4

=
=
=
=

number.substring(0,1);
number.substring(0,2);
number.substring(0,3);
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
*/
else if (digit4.equals("2014") || digit4.equals("2149")) {
if (number.length() == 15)
valid = EN_ROUTE;
}

17.15 Validate a Credit Card NumberTag(s): Varia

/*
** 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.length1; i >= 0; i= 2) {
int k = 0;
if (i > 0) {
k = Integer.valueOf(s1[i1]).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;
}
else
checksum += Integer.valueOf(s1[0]).intValue();
}
return ((checksum % 10) == 0);

17.15 Validate a Credit Card NumberTag(s): Varia

}
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!");
}
}

17.16 Obtain from where a Class is loadedTag(s):


Language Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0300.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();
}

17.16 Obtain from where a Class is loadedTag(s): Language Varia

}
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);
}
}

The output
> java FromWhere
This class (FromWhere) is located at : file:/C:/temp/

See these related HowTo's : 1 2

17.17 Get the class name with or without the packageTag(s):


Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0389.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;
}

17.17 Get the class name with or without the packageTag(s): Varia

// 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);
}
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

17.17 Get the class name with or without the packageTag(s): Varia

17.18 See the generated bytecodeTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0495.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[]) {

17.18 See the generated bytecodeTag(s): Varia

int
new
new
new

i = 1;
Integer(i++);
Integer(i++);
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

17.18 See the generated bytecodeTag(s): Varia

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 opcodes more than the equivalent "i++".


Note this is very lowlevel optimization, the gain in performance is not very significative, the class is
little bit smaller.
Remember Premature optimization is the root of all evil

17.19 Self replicating programsTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0344.html
A 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
17.19 Self replicating programsTag(s): Varia

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));}}

Third example
author Daniel Pitts
[Q.java]
enum Q {a("enum Q{a(%c%s%c);Q(String t){System.out.printf(t,34,t,34);System.exit(0);}}");
Q(String t){System.out.printf(t,34,t,34);System.exit(0);}}

See also this HowTo

17.20 A curiosity (strange Java code)Tag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0356.html
A collection of weird Java code!
A really short Java program with a visual output and no main()!
public class J{static{System.out.print
("Real's JavaHowTo");System.exit(0);}}

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;
}

17.20 A curiosity (strange Java code)Tag(s): Varia

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)

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 (a long time ago...) is there!
+
Real Gagnon,
|
Universite de Montreal
|
xxxxxxx@xxx.xxxxxxxxx.xx |

#include
/* BC ok , Apollo NFG */
int main(void) { int i=0;
while(putchar(i++["\13Dl~fxym789\26xd"]i));
while(putchar((i)["\0\t+*)('}

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!

The above code is shown as an image to make sure that special characters are rendered correctly.
To see the actual code, download the source : Howto.java.
See also this HowTo

17.20 A curiosity (strange Java code)Tag(s): Varia

17.21 Classic bugsTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0361.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 ?");
}

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;}

17.22 Number of the beast!Tag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0477.html

17.21 Classic bugsTag(s): Varia

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[i1]);
}
// Since it's really "Bill Gates III"
System.out.println(k + 1 + 1 + 1);
// output : 666 :)
}
}

17.23 Use Java scripting engine (JDK 1.6)Tag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0629.html
import
import
import
import
import

java.util.List;
javax.script.ScriptEngineManager;
javax.script.ScriptEngine;
javax.script.ScriptEngineFactory;
javax.script.ScriptException;

public class Scripting {


public static void main(String[] args) {
try {
// dump available engines
ScriptEngineManager mgr = new ScriptEngineManager();
List<ScriptEngineFactory> engines = mgr.getEngineFactories();
for (ScriptEngineFactory engine : engines ) {
System.out.println(engine.getEngineName());
for ( String n: engine.getNames()) {
System.out.println("Short name : " + n);
}
}
/*
output :
Mozilla Rhino
Short name : js
Short name : rhino
Short name : JavaScript
Short name : javascript
Short name : ECMAScript
Short name : ecmascript
*/

17.23 Use Java scripting engine (JDK 1.6)Tag(s): Varia

// now execute a small script


ScriptEngine engine = mgr.getEngineByName("JavaScript");
String myJSCode = "function myFunction() {"
+ "
return (40 + 2);"
+ "}"
+"myFunction();";
System.out.println(engine.eval(myJSCode));
/*
output :
42
*/
}
catch (ScriptException ex) {
ex.printStackTrace();
}
}
}

How to use Rhino to reach beyond JavaScript into Java

17.24 Pass or retrieve values from a scripting engine


(jdk1.6)Tag(s): Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0640.html
These examples use the Rhino Javascript engine bundled with Java 6.
The documentation is at Mozilla Rhino site.
import
import
import
import
import

java.util.Arrays;
java.util.List;
javax.script.ScriptEngineManager;
javax.script.ScriptEngine;
javax.script.ScriptException;

public class Scripting01 {


public static void main(String[] args) {
ScriptEngineManager mgr = new ScriptEngineManager();
// we are using the rhino javascript engine
ScriptEngine engine = mgr.getEngineByName("javascript");
// pass a Java collection to javascript
List <String> list1 = Arrays.asList
("Homer", "Bart", "Marge", "Maggie", "Lisa");
engine.put("list1", list1);
String jsCode =
"var index; "
+ "var values =list1.toArray();"
+ "println('*** Java object to Javascript');"
+ "for(index in values) {"

17.24 Pass or retrieve values from a scripting engine (jdk1.6)Tag(s): Varia

+ " println(values[index]);"
+ "}";
try {
engine.eval(jsCode);
}
catch (ScriptException se) {
se.printStackTrace();
}
// pass a collection from javascript to java
jsCode =
"importPackage(java.util);"
+ "var list2 = Arrays.asList(['Moe', 'Barney', 'Ned']); ";
try {
engine.eval(jsCode);
}
catch (ScriptException se) {
se.printStackTrace();
}
List <String> list2 = (List<String>) engine.get("list2");
System.out.println("*** Javascript object to Java");
for (String val : list2) {
System.out.println(val);
}
}
}
/*
output :
*** Java object to Javascript
Homer
Bart
Marge
Maggie
Lisa
*** Javascript object to Java
Moe
Barney
Ned
*/

The next example uses an external file containing the javascript code. The .JS file is loaded from
the classpath.
[scripting02.js]
importPackage(java.util);
var list1 = Arrays.asList
(['Homer', 'Bart', 'Marge', 'Maggie', 'Lisa']);
var listObject = {
list2 : Arrays.asList
(['Moe', 'Barney', 'Ned']),
getList2 : function() {
return listObject.list2;
}
};
import java.io.InputStreamReader;
import java.util.List;
import javax.script.Invocable;

17.24 Pass or retrieve values from a scripting engine (jdk1.6)Tag(s): Varia

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class Scripting02 {
public static void main(String[] args) throws Exception{
ScriptEngineManager mgr = new ScriptEngineManager();
// we are using the rhino javascript engine
ScriptEngine engine = mgr.getEngineByName("javascript");
// the .js is in the classpath
engine.eval(new InputStreamReader
(Scripting02.class.getResourceAsStream("scripting02.js")));
// retreive a javascript object directly
List <String> list1 = (List <String>)engine.get("list1");
if (list1 != null) {
for (String s : (List<String>) list1) {
System.out.println(s);
}
}
System.out.println("***");
// call a javascript function to retrieve an object
if (engine instanceof Invocable){
Invocable engineInv = (Invocable)engine;
Object obj = engine.get("listObject");
Object list2 = engineInv.invokeMethod(obj, "getList2");
if (list2 != null) {
for (String s : (List<String>) list2) {
System.out.println(s);
}
}
}
}
}
/*
output :
Homer
Bart
Marge
Maggie
Lisa
***
Moe
Barney
Ned
*/

17.25 Preventing multiple instances of an applicationTag(s):


Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0288.html

17.25 Preventing multiple instances of an applicationTag(s): Varia

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
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);

17.25 Preventing multiple instances of an applicationTag(s): Varia

}
catch (Exception e) {
sds = new JustOneServer();
sds.start();
}
while(true) {
try { System.out.print("."); Thread.sleep(5 * 60); }
catch(Exception e) { e.printStackTrace(); }
}
}
}

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() {

17.25 Preventing multiple instances of an applicationTag(s): Varia

// destroy the lock when the JVM is closing


public void run() {
closeLock();
deleteFile();
}
});
return false;
}
catch (Exception e) {
closeLock();
return true;
}
}
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) { }
}
}
}

17.25 Preventing multiple instances of an applicationTag(s): Varia

17.26 Trap JVM shutdownTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0459.html
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last nondaemon 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
systemwide event, such as user logoff or system shutdown.
JDK1.3
public class TrapBreak {
public static void main(String args[]) throws Exception{
new TrapBreak().doit();
}
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 upperright X.


Now check the out.log file, you will find "*** END ***" written by our ShutdownHook.
..................*** END ***

17.27 Minimize all programs on Windows to show the


DesktopTag(s): Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0637.html
public class Test2 {
public static void main(String args[]) throws Exception{

17.26 Trap JVM shutdownTag(s): Varia

Runtime.getRuntime().exec
(new String[] {
"cmd.exe",
"/c",
"\"" + System.getenv("APPDATA") +
"\\Microsoft\\Internet Explorer\\Quick Launch\\Show Desktop.scf" + "\""});
}
}

.scf is a special file that contains a command for the Windows Explorer.
This command file can be localized for Windows in a different language, for the french Windows, it's
"Bureau.scf". It may be a good to make a copy of it under a different (and known) name and
location.

17.28 Display a progress indicator in the consoleTag(s): Varia


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0666.html
Display a rotating bar or a more traditional progress bar in a text console.
import java.io.*;
public class ConsoleProgressBar {
public static void main(String[] argv) throws Exception{
System.out.println("Rotating progress bar");
ProgressBarRotating pb1 = new ProgressBarRotating();
pb1.start();
int j = 0;
for (int x =0 ; x <2000 ; x++){
// do some activities
FileWriter fw = new FileWriter("c:/temp/x.out", true);
fw.write(j++);
fw.close();
}
pb1.showProgress = false;
System.out.println("\nDone " + j);
System.out.println("Traditional progress bar");
ProgressBarTraditional pb2 = new ProgressBarTraditional();
pb2.start();
j = 0;
for (int x =0 ; x < 2000 ; x++){
// do some activities
FileWriter fw = new FileWriter("c:/temp/x.out", true);
fw.write(j++);
fw.close();
}
pb2.showProgress = false;
System.out.println("\nDone " + j);
}
}

17.28 Display a progress indicator in the consoleTag(s): Varia

class ProgressBarRotating extends Thread {


boolean showProgress = true;
public void run() {
String anim= "|/\\";
int x = 0;
while (showProgress) {
System.out.print("\r Processing " + anim.charAt(x++ % anim.length()));
try { Thread.sleep(100); }
catch (Exception e) {};
}
}
}
class ProgressBarTraditional extends Thread {
boolean showProgress = true;
public void run() {
String anim = "=====================";
int x = 0;
while (showProgress) {
System.out.print("\r Processing "
+ anim.substring(0, x++ % anim.length())
+ " ");
try { Thread.sleep(100); }
catch (Exception e) {};
}
}
}

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

17.28 Display a progress indicator in the consoleTag(s): Varia

18 XML
18.1 javaxml

18.2 Read meTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0405.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.
XSLT (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.
XMLFOP (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 eventdriven 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.

18 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

18.3 Display XML using plain HTMLTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0406.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>

18.3 Display XML using plain HTMLTag(s): XML

<TD><SPAN datafld="url"></SPAN></TD>
</TR>
</TABLE>
</BODY>
</HTML>

See the result here (IE only).

18.4 Transform XML into HTML using XSLTTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0407.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:foreach select="howto/topic">
<tr>
<td><xsl:valueof select="title"/></td>
<td><xsl:valueof select="url"/></td>

18.4 Transform XML into HTML using XSLTTag(s): XML

</tr>
</xsl:foreach>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>

[HowToXSLT.java]
// jdk1.4.1
import javax.xml.transform.*;
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.

18.5 Parse using SAX or DOMTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0408.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"?>

18.5 Parse using SAX or DOMTag(s): XML

<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>

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;
}
}
}

18.5 Parse using SAX or DOMTag(s): XML

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]
// 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 "?";
}
}

18.5 Parse using SAX or DOMTag(s): XML

18.6 Parse an XML stringTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0573.html
Using DOM and a StringReader.
import
import
import
import

javax.xml.parsers.*;
org.xml.sax.InputSource;
org.w3c.dom.*;
java.io.*;

public class ParseXMLString {


public static void main(String arg[]) {
String xmlRecords =
"<data>" +
" <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

18.6 Parse an XML stringTag(s): XML

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 "?";
}
}

18.7 Create an XML document with DOMTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0530.html
import
import
import
import
import

org.w3c.dom.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
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

18.7 Create an XML document with DOMTag(s): XML

(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO88591");
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "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="ISO88591"?>
<howto>
<java url="http://www.ragagnon.com/howto.html"/>
</howto>
/*
}
}

18.8 Attach a stylesheet to an XML fileTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0450.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="ISO88591"?>
<?xmlstylesheet 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>

18.8 Attach a stylesheet to an XML fileTag(s): XML

</data>

bruce.xsl
<?xml version="1.0" encoding="ISO88591"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table>
<xsl:foreach select="data/guynamedbruce">
<tr>
<td>
<xsl:valueof select="FirstName"/>
</td>
<td>
<xsl:valueof select="LastName"/>
</td>
</tr>
</xsl:foreach>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Try it here

18.9 Create an XML file and attach an XSLTag(s): XML XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0577.html
import java.io.*;
import
import
import
import
import

org.w3c.dom.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
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);

18.9 Create an XML file and attach an XSLTag(s): XML XML

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/javaxml.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,"ISO88591");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is
<?xml version="1.0" encoding="ISO88591"?>
<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/javaxml.html</URL>
</TOPIC>
</HOWTOS>

And now to attach an XSL


18.9 Create an XML file and attach an XSLTag(s): XML XML

import java.io.*;
import
import
import
import
import

org.w3c.dom.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
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
("xmlstylesheet", "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/javaxml.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

18.9 Create an XML file and attach an XSLTag(s): XML XML

(OutputKeys.OMIT_XML_DECLARATION, "no");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING,"ISO88591");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is
<?xml version="1.0" encoding="ISO88591"?>
<?xmlstylesheet type="text/xsl" href="howto.xsl"?>
<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/javaxml.html</URL>
</TOPIC>
</HOWTOS>

18.10 Nicely display WEB.XML informationsTag(s):


Servlet/JSP XML Jaguar/EAServer
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0451.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="UTF8"?>
<?xmlstylesheet type="text/xsl" href="treeview.xsl"?>
...

or do the transformation in Java, for a hint see this Howto.


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
18.10 Nicely display WEB.XML informationsTag(s): Servlet/JSP XML Jaguar/EAServer

will need this XSL).


<META httpequiv="ContentType" content="text/html; charset=ISO88591">
<%@ 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/treeview2.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 );
}
%

18.10 Nicely display WEB.XML informationsTag(s): Servlet/JSP XML Jaguar/EAServer

18.11 Serialize an object using XMLTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0470.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 =
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

18.11 Serialize an object using XMLTag(s): XML

}
}

Just for fun, here the resulting XML file (with my installation)
<?xml version="1.0" encoding="UTF8"?>
<java version="1.5.0beta" class="java.beans.XMLDecoder">
<object class="Foo">
<void property="foo">
<string>bar</string>
</void>
</object>
/JAVA

18.12 Convert a flat file to XML (SAX)Tag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0482.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) :


<?xml version="1.0" encoding="ISO88591"?>
<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.*;

18.12 Convert a flat file to XML (SAX)Tag(s): XML

// SAX classes.
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import
import
import
import

javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
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(); }
}

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,"ISO88591");
// pretty XML output
serializer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "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());

18.12 Convert a flat file to XML (SAX)Tag(s): XML

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(); }
}

18.13 Convert a flat file to XML (DOM)Tag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0481.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) :


<?xml version="1.0" encoding="ISO88591"?>
<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.*;

18.13 Convert a flat file to XML (DOM)Tag(s): XML

import
import
import
import
import

org.w3c.dom.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
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
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);
}

18.13 Convert a flat file to XML (DOM)Tag(s): XML

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,"ISO88591");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "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();
*/
}
}

18.14 Convert a ResultSet to XMLTag(s): JDBC XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0511.html
import
import
import
import
import
import

java.sql.Connection;
java.sql.Statement;
java.sql.Driver;
java.sql.DriverManager;
java.sql.ResultSet;
java.sql.ResultSetMetaData;

import
import
import
import
import
import
import

javax.xml.parsers.DocumentBuilder;
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.transform.*;
javax.xml.transform.stream.*;
javax.xml.transform.dom.*;
org.w3c.dom.Document;
org.w3c.dom.Element;

class JDBCapp

static Connection con;


public static void main (String args[]) {
ResultSet rs = null;
Statement stmt = null;

18.14 Convert a ResultSet to XMLTag(s): JDBC XML

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));
}
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,"ISO88591");
// we want to pretty format the XML output
// note : this is broken in jdk1.5 beta!
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//

18.14 Convert a ResultSet to XMLTag(s): JDBC XML

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");
*/
}
}

18.15 Parse with XPathTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0550.html
[J2SE 1.5]
Consider the following XML data file (howto.xml)
<?xml version="1.0"?>
<howto>
<topic name="Java">
<url>http://www.rgagnon.com/topics/javaxml.html</url>
</topic>
<topic name="PowerBuilder">
<url>http://www.rgagnon.com/topics/pbcommon.html</url>
<url>http://www.rgagnon.com/topics/pbpfc.html</url>
</topic>
<topic name="Javascript">
<url>http://www.rgagnon.com/topics/jslanguage.html</url>
</topic>
<topic name="VBScript">
<url>http://www.rgagnon.com/topics/wshvbs.html</url>
</topic>
</howto>

To list the topics :


import java.io.File;

18.15 Parse with XPathTag(s): XML

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
*/
}
}

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.com/topics/pbcommon.html
http://www.rgagnon.com/topics/pbpfc.html
*/
// display only the "url" nodes for PowerBuidler
NodeList urls = nodes.item(0).getChildNodes();

18.15 Parse with XPathTag(s): XML

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.com/topics/pbcommon.html
url :http://www.rgagnon.com/topics/pbpfc.html
*/
}
}

If your XML is in a String (not in a File) then you need to get an InputStream from it.
import java.io.ByteArrayInputStream;
import java.io.InputStream;
...
String xml = "<?xml version="1.0"?>"
+ " <howto>"
+ "
<topic name="Java">"
...
+ "</howto>";

InputStream is = new ByteArrayInputStream(xml.getBytes());


XPath xpath = XPathFactory.newInstance().newXPath();
String xpathExpression = "/howto/topic[@name='PowerBuilder']";
InputSource inputSource = new InputSource(is);
NodeList nodes = (NodeList) xpath.evaluate
(topicExpression, inputSource, XPathConstants.NODESET);
...

You may need to pass the required encoding to the String.getBytes() method. See this HowTo
Consider this XML :
<?xml version="1.0" encoding="UTF8"?>
<UDSObjectList>
<UDSObject>
<Handle>chg_tpl:400004</Handle>
<Attributes>
<Attribute DataType="2001">
<AttrName>id</AttrName>
<AttrValue>400004</AttrValue>
</Attribute>
<Attribute DataType="2002">
<AttrName>persistent_id</AttrName>
<AttrValue>chg_tpl:400004</AttrValue>
</Attribute>
</Attributes>
</UDSObject>
</UDSObjectList>

If we want the Handle text value then we don't need to retrieve the NODESET, only the TEXT.
import
import
import
import

java.io.ByteArrayInputStream;
java.io.InputStream;
javax.xml.xpath.XPath;
javax.xml.xpath.XPathFactory;

18.15 Parse with XPathTag(s): XML

import org.xml.sax.InputSource;
...
String xml = "<?xml version="1.0" encoding="UTF8"?>"
+ "<UDSObjectList>"
...
+ "</UDSObjectList>";
...
InputStream is = new ByteArrayInputStream(xml.getBytes("UTF8"));
XPath xpath = XPathFactory.newInstance().newXPath();
String xpathExpression = "/UDSObjectList/UDSObject/Handle";
InputSource inputSource = new InputSource(is);
String handle = xpath.evaluate(xpathExpression, inputSource);
System.out.println(handle);
/*
output :
chg_tpl:400004
*/

One last example. Suppose we have an XML file containing SQL Statements.
<queries>
<query id="getUserByName">select * from users where name=?</query>
<query id="getUserByEmail">select * from users where email=?</query>
</queries>

To retrieve a SELECT
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.xml.sax.InputSource;
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(getQuery("getUserByName"));
System.out.println(getQuery("getUserByEmail"));
}
public static String getQuery (String id) throws Exception {
XPath xpath = XPathFactory.newInstance().newXPath();
// in this example, sql.xml is loaded from the classpath
InputSource is = new InputSource(Test.class.getResourceAsStream("/sql.xml"));
return xpath.evaluate("/queries/query[@id='" + id +"']", is);
}
}
/* output :
select * from users where name=?
select * from users where email=?
*/

18.15 Parse with XPathTag(s): XML

18.16 Strip extra spaces in a XML stringTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0563.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);
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>
*/
}
}

18.17 Create an XML file and attach an XSLTag(s): XML XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0577.html
import java.io.*;
import
import
import
import
import

org.w3c.dom.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
javax.xml.transform.dom.*;

public class CreateXML

public static void main (String args[]) {


new CreateXML().doit();
}

18.16 Strip extra spaces in a XML stringTag(s): XML

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/javaxml.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,"ISO88591");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is
<?xml version="1.0" encoding="ISO88591"?>
<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>

18.16 Strip extra spaces in a XML stringTag(s): XML

<URL>http://www.rgagnon/topics/javaxml.html</URL>
</TOPIC>
</HOWTOS>

And now to attach an XSL


import java.io.*;
import
import
import
import
import

org.w3c.dom.*;
javax.xml.parsers.*;
javax.xml.transform.*;
javax.xml.transform.stream.*;
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
("xmlstylesheet", "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/javaxml.html");
e2.appendChild(n2);
e0.appendChild(e1);
e0.appendChild(e2);
root.appendChild(e0);
}
public void writeXML(Document xmldoc, StreamResult out)

18.16 Strip extra spaces in a XML stringTag(s): XML

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,"ISO88591");
// we want to pretty format the XML output
transformer.setOutputProperty
("{http://xml.apache.org/xslt}indentamount", "4");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
//
transformer.transform(domSource, out);
}
}

The result is
<?xml version="1.0" encoding="ISO88591"?>
<?xmlstylesheet type="text/xsl" href="howto.xsl"?>
<HOWTOS>
<TOPIC>
<TITLE>Java</TITLE>
<URL>http://www.rgagnon/topics/javaxml.html</URL>
</TOPIC>
</HOWTOS>

18.18 Use XML with PropertiesTag(s): Language XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0578.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");

18.18 Use XML with PropertiesTag(s): Language XML

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="UTF8"?>
<!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>

18.19 Change a particular node in XMLTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0625.html
Consider this XML file.
<data>
<employee>
<name>John</name>
<title>Manager</title>
</employee>
<employee>
<name>Sara</name>
<title>Clerk</title>
</employee>
</data>

We want to change employee named "John" to "John Paul"


You locate the element to change with an XPath query. You change the text and then save back the
data.
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;

18.19 Change a particular node in XMLTag(s): XML

import
import
import
import
import
import
import

javax.xml.transform.Transformer;
javax.xml.transform.TransformerFactory;
javax.xml.transform.dom.DOMSource;
javax.xml.transform.stream.StreamResult;
javax.xml.xpath.XPath;
javax.xml.xpath.XPathConstants;
javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class XMLReplaceDemo {
static String inputFile = "C:/temp/data.xml";
static String outputFile = "C:/temp/data_new.xml";
public static void main(String[] args) throws Exception {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder().parse(new InputSource(inputFile));
// locate the node(s)
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xpath.evaluate
("//employee/name[text()='John']", doc, XPathConstants.NODESET);
// make the change
for (int idx = 0; idx < nodes.getLength(); idx++) {
nodes.item(idx).setTextContent("John Paul");
}
// save the result
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform
(new DOMSource(doc), new StreamResult(new File(outputFile)));
}
}

The result
<?xml version="1.0" encoding="UTF8" standalone="no"?><data>
<employee>
<name>John Paul</name>
<title>Manager</title>
</employee>
<employee>
<name>Sara</name>
<title>Clerk</title>
</employee>
</data>

18.20 Validate XML using a DTDTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0668.html
18.20 Validate XML using a DTDTag(s): XML

Consider this XML file howto.xml :


<?xml version="1.0" encoding="ISO88591"?>
<!DOCTYPE howto SYSTEM "howto.dtd">
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/javaxml.html</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon.com/topics/pbpowerscript.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon.com/topics/jslanguage.html</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon.com/topics/wshvbs.html</url>
</topic>
</howto>

A referenced to the external DTD file howto.dtd is present.


The external howto.dtd :
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT

howto (topic*)>
topic (title,url)>
title (#PCDATA)>
url (#PCDATA)>

NOTE : The DTD can be inside the XML document.


<?xml version="1.0" encoding="ISO88591"?>
<!DOCTYPE howto [
<!ELEMENT howto (topic*)>
<!ELEMENT topic (title,url)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT url (#PCDATA)>
]>
<howto>
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/javaxml.html</url>
</topic>
...
</howto>

The code to validate an XML file using the declared DTD :


import
// DOM
import
import
// SAX
import
import
import

java.io.IOException;
javax.xml.parsers.DocumentBuilder;
javax.xml.parsers.DocumentBuilderFactory;
javax.xml.parsers.SAXParser;
javax.xml.parsers.SAXParserFactory;
org.xml.sax.XMLReader;

import javax.xml.parsers.ParserConfigurationException;

18.20 Validate XML using a DTDTag(s): XML

import
import
import
import

org.xml.sax.ErrorHandler;
org.xml.sax.SAXException;
org.xml.sax.SAXParseException;
org.xml.sax.InputSource;

public class XMLUtils {


private XMLUtils() {}
// validate using DOM (DTD as defined in the XML)
public static boolean validateWithDTDUsingDOM(String xml)
throws ParserConfigurationException, IOException
{
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(
new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {
System.out.println("WARNING : " + e.getMessage()); // do nothing
}
public void error(SAXParseException e) throws SAXException {
System.out.println("ERROR : " + e.getMessage());
throw e;
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("FATAL : " + e.getMessage());
throw e;
}
}
);
builder.parse(new InputSource(xml));
return true;
}
catch (ParserConfigurationException pce) {
throw pce;
}
catch (IOException io) {
throw io;
}
catch (SAXException se){
return false;
}
}

// validate using SAX (DTD as defined in the XML)


public static boolean validateWithDTDUsingSAX(String xml)
throws ParserConfigurationException, IOException
{
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);
SAXParser parser = factory.newSAXParser();

18.20 Validate XML using a DTDTag(s): XML

XMLReader reader = parser.getXMLReader();


reader.setErrorHandler(
new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {
System.out.println("WARNING : " + e.getMessage()); // do nothing
}
public void error(SAXParseException e) throws SAXException {
System.out.println("ERROR : " + e.getMessage());
throw e;
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("FATAL : " + e.getMessage());
throw e;
}
}
);
reader.parse(new InputSource( xml ));
return true;
}
catch (ParserConfigurationException pce) {
throw pce;
}
catch (IOException io) {
throw io;
}
catch (SAXException se){
return false;
}
}
public static void main (String args[]) throws Exception{
System.out.println(XMLUtils.validateWithDTDUsingDOM("c:/temp/howto.xml"));
System.out.println(XMLUtils.validateWithDTDUsingSAX("c:/temp/howto.xml"));
/*
output :
true
true
*/
}
}

NOTES :
The DOM is faster than SAX but DOM reads the entire structure in memory so the memory
consumption is bigger.
DTD is the old way to validate an XML structure. The preferred way is to use an XML schema
(XSD) which provides a more complete validation process.
To validate using an XML Schema (XSD), see this HowTo

18.20 Validate XML using a DTDTag(s): XML

18.21 Validate XML using a XSD (XML Schema)Tag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0669.html
Consider this XML file howto.xml :
<?xml version="1.0" encoding="ISO88591"?>
<howto xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/javaxml.html</url>
</topic>
<topic>
<title>PowerBuilder</title>
<url>http://www.rgagnon.com/topics/pbpowerscript.htm</url>
</topic>
<topic>
<title>Javascript</title>
<url>http://www.rgagnon.com/topics/jslanguage.html</url>
</topic>
<topic>
<title>VBScript</title>
<url>http://www.rgagnon.com/topics/wshvbs.html</url>
</topic>
</howto>

The external howto.xsd :


<?xml version="1.0" encoding="ISO88591"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="howto">
<xs:complexType>
<xs:sequence>
<xs:element name="topic" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="url" type="httpURI"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:simpleType name="httpURI">
<xs:restriction base="xs:anyURI">
<xs:pattern value="http://.*" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

The code (using SAX parser) to validate an XML file using a given external XSD.
import java.io.IOException;
// SAX

18.21 Validate XML using a XSD (XML Schema)Tag(s): XML

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.XMLReader;
//SAX and external XSD
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.SchemaFactory;
import
import
import
import
import

javax.xml.parsers.ParserConfigurationException;
org.xml.sax.ErrorHandler;
org.xml.sax.SAXException;
org.xml.sax.SAXParseException;
org.xml.sax.InputSource;

public class XMLUtils {


private XMLUtils() {}
// validate SAX and external XSD
public static boolean validateWithExtXSDUsingSAX(String xml, String xsd)
throws ParserConfigurationException, IOException
{
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(true);

SchemaFactory schemaFactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSche


SAXParser parser = null;
try {
factory.setSchema(schemaFactory.newSchema(new Source[] {new StreamSource( xsd )}));
parser = factory.newSAXParser();
}
catch (SAXException se) {
System.out.println("SCHEMA : " + se.getMessage()); // problem in the XSD itself
return false;
}
XMLReader reader = parser.getXMLReader();
reader.setErrorHandler(
new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {
System.out.println("WARNING: " + e.getMessage()); // do nothing
}
public void error(SAXParseException e) throws SAXException {
System.out.println("ERROR : " + e.getMessage());
throw e;
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("FATAL : " + e.getMessage());
throw e;
}
}
);
reader.parse(new InputSource(xml));
return true;
}
catch (ParserConfigurationException pce) {
throw pce;
}

18.21 Validate XML using a XSD (XML Schema)Tag(s): XML

catch (IOException io) {


throw io;
}
catch (SAXException se){
return false;
}
}
public static void main (String args[]) throws Exception{
System.out.println
(XMLUtils.validateWithExtXSDUsingSAX
("c:/temp/howto.xml", "c:/temp/howto.xsd"));
/*
output :
true
*/
}
}

The XML can contain a reference to the XSD to be used.


<?xml version="1.0" encoding="ISO88591"?>
<howto xsi:noNamespaceSchemaLocation="howto.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<topic>
<title>Java</title>
<url>http://www.rgagnon.com/topics/javaxml.html</url>
</topic>
...
</howto>

The code (using DOM parser) to validate an XML file using the referenced XSD :
import java.io.IOException;
// DOM
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import
import
import
import
import

javax.xml.parsers.ParserConfigurationException;
org.xml.sax.ErrorHandler;
org.xml.sax.SAXException;
org.xml.sax.SAXParseException;
org.xml.sax.InputSource;

public class XMLUtils {


private XMLUtils() {}
// validate DOM and internal XSD
public static boolean validateWithIntXSDUsingDOM(String xml)
throws ParserConfigurationException, IOException
{
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setNamespaceAware(true);
factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(
new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {

18.21 Validate XML using a XSD (XML Schema)Tag(s): XML

System.out.println("WARNING: " + e.getMessage()); // do nothing


}
public void error(SAXParseException e) throws SAXException {
System.out.println("ERROR: " + e.getMessage());
throw e;
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("FATAL: " + e.getMessage());
throw e;
}
}
);
builder.parse(new InputSource(xml));
return true;
}
catch (ParserConfigurationException pce) {
throw pce;
}
catch (IOException io) {
throw io;
}
catch (SAXException se){
return false;
}
}
public static void main (String args[]) throws Exception{
System.out.println
(XMLUtils.validateWithIntXSDUsingDOM
("c:/temp/howto.xml"));
}
}

The code (using SAX parser) to validate an XML file using the referenced XSD :
import
// SAX
import
import
import

java.io.IOException;

import
import
import
import
import

javax.xml.parsers.ParserConfigurationException;
org.xml.sax.ErrorHandler;
org.xml.sax.SAXException;
org.xml.sax.SAXParseException;
org.xml.sax.InputSource;

javax.xml.parsers.SAXParser;
javax.xml.parsers.SAXParserFactory;
org.xml.sax.XMLReader;

public class XMLUtils {


private XMLUtils() {}
// validate SAX and internal XSD
public static boolean validateWithIntXSDWithSAX(String xml)
throws ParserConfigurationException, IOException
{
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(true);

18.21 Validate XML using a XSD (XML Schema)Tag(s): XML

factory.setNamespaceAware(true);
SAXParser parser = factory.newSAXParser();
parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
XMLReader reader = parser.getXMLReader();
reader.setErrorHandler(
new ErrorHandler() {
public void warning(SAXParseException e) throws SAXException {
System.out.println("WARNING: " + e.getMessage()); // do nothing
}
public void error(SAXParseException e) throws SAXException {
System.out.println("ERROR: " + e.getMessage());
throw e;
}
public void fatalError(SAXParseException e) throws SAXException {
System.out.println("FATAL: " + e.getMessage());
throw e;
}
}
);
reader.parse(new InputSource(xml));
return true;
}
catch (ParserConfigurationException pce) {
throw pce;
}
catch (IOException io) {
throw io;
}
catch (SAXException se){
return false;
}
}
public static void main (String args[]) throws Exception{
System.out.println(XMLUtils.validateWithIntXSDWithSAX("c:/temp/howto.xml"));
}
}

This HowTo uses the builtin XML parser, you can switch JAXP in debug mode by passing a
special switch on the JVM commandline.
java Djaxp.debug=1 ...
or
java Djaxp.debug ...

JAXP will produce log entries about its activities :


JAXP:
JAXP:
JAXP:
JAXP:
...

found null in $java.home/jaxp.properties


no METAINF/services/javax.xml.validation.SchemaFactory file was found
attempting to use the platform default XML Schema validator
createInstance(com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory)

NOTES :

18.21 Validate XML using a XSD (XML Schema)Tag(s): XML

The DOM is faster than SAX but DOM reads the entire structure in memory so the memory
consumption is bigger.
See http://en.wikibooks.org/wiki/XML_Schema for more infos about XSD.
To validate using an DTD, see this HowTo.

18.22 Sanitize XML String Tag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javasanitizexmlstring.html
The following lists the range of valid XML characters. Any character not in the range is not
allowed.
Hexidecimal
#x9
#xA
#xD
#x20#xD7FF
#xE000#xFFFD
#x10000#x10FFFF

Decimal
#9
#10
#13
#32#55295
#57344#65533
#10000#1114111

any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
ref : http://www.w3.org/TR/RECxml/#charsets.
The exception to this rule is that CDATA sections may contain any character, including ones not in the above range.

For example, if data is coming from a Cut&Paste operation from a Microsoft Word document, you
may end up with 0x1a characters. Later, when the XML data is parsed, an Exception
"hexadecimal value 0x1A, is an invalid character" will be thrown.
The following methods will remove all invalid XML characters from a given string (the special
handling of a CDATA section is not supported).
Using Regex
public static String sanitizeXmlChars(String xml) {
if (xml == null || ("".equals(xml))) return "";
// ref : http://www.w3.org/TR/RECxml/#charsets
// jdk 7
Pattern xmlInvalidChars =
Pattern.compile(
"[^\\u0009\\u000A\\u000D\\u0020\\uD7FF\\uE000\\uFFFD\\x{10000}\\x{10FFFF}]"
);
return xmlInvalidChars.matcher(xml).replaceAll("");
}

18.22 Sanitize XML String Tag(s): XML

Using StringBuilder and forloop


public static String sanitizeXmlChars(String in) {
StringBuilder out = new StringBuilder();
char current;
if (in == null || ("".equals(in))) return "";
for (int i = 0; i < in.length(); i++) {
current = in.charAt(i);
if ((current == 0x9) ||
(current == 0xA) ||
(current == 0xD) ||
((current >= 0x20) && (current <= 0xD7FF)) ||
((current >= 0xE000) && (current <= 0xFFFD)) ||
((current >= 0x10000) && (current <= 0x10FFFF)))
out.append(current);
}
return out.toString();
}

18.23 Produce HTML entities when using XSLTTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaproduceHTMLentitieswhenusingXSLT.html
You disable the automatic output escaping and use the &amp; entity to build the actual entity.
<P><span style="borderstyle:solid;borderwidth:1px;">
<a href="{link}">
<xsl:text disableoutputescaping="yes">&amp;nbsp;&amp;rArr;</xsl:text>
Read the article</a>.
<xsl:text disableoutputescaping="yes">&amp;nbsp;</xsl:text>
</span>
</P>

will produce
Read the article.

18.24 Create a RSS feed (part 1)Tag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0556.html

18.23 Produce HTML entities when using XSLTTag(s): XML

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.

18.24.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="utf8"?>
<?xmlstylesheet 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/realhowtoleft.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/js0129.html</link>
<pubDate>23 May 2007 00:00:00 GMT</pubDate>
<guid>http://www.rgagnon.com/jsdetails/js0129.html</guid>
</item>
</channel>
</rss>

18.24.1 RSS 2.0

18.24.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="utf8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Example Feed</title>
<subtitle>A subtitle.</subtitle>
<link href="http://example.org/"/>
<updated>20031213T18:30:02Z</updated>
<author>
<name>John Doe</name>
<email>johndoe@example.com</email>
</author>
<id>urn:uuid:60a76c80d39911d9b91C0003939e0af6</id>
<entry>
<title>AtomPowered Robots Run Amok</title>
<link href="http://example.org/2003/12/13/atom03"/>
<id>urn:uuid:1225c695cfb84ebbaaaa80da344efa6a</id>
<updated>20031213T18:30:02Z</updated>
<summary>Some text.</summary>
</entry>
</feed>

18.24.2 Atom

18.24.3 Creating a feed


To create a RSS feed without using external librairies, see this HowTo.
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.

18.24.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
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 commonsdigesterrss.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
import
import
import

java.io.File;
java.io.FileInputStream;
java.io.FileOutputStream;
java.io.IOException;

import
import
import
import

java.util.ArrayList;
java.util.Collection;
java.util.Date;
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");
newChannel.setPubDate(today);

18.24.3 Creating a feed

Item item = new Item();


item.setTitle("Real's HowTo");
item.setLink("http://www.rgagnon.com/javadetails/");
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/rss0.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/javadetails/</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!

18.24.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.
ROME requires JDOM 1.0 (http://www.jdom.org/).
18.24.5 Creating a feed with Rome

import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.SyndFeedOutput;
import
import
import
import
import
import

java.io.FileWriter;
java.io.Writer;
java.text.DateFormat;
java.text.SimpleDateFormat;
java.util.ArrayList;
java.util.List;

public class CreateRSSFeedUsingRome {


private static final DateFormat DATE_PARSER =
new SimpleDateFormat("yyyyMMdd");
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/javadetails/");
entry.setPublishedDate(DATE_PARSER.parse("20040608"));
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="UTF8"?>
<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/22rdfsyntaxns#"
xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/howto.html</link>

18.24.5 Creating a feed with Rome

<description>Useful Java code examples</description>


<item>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com/javadetails/</link>
<description>Cool java snippet!</description>
<pubDate>Tue, 08 Jun 2004 04:00:00 GMT</pubDate>
<guid>http://www.rgagnon.com/javadetails/</guid>
<dc:date>20040608T04:00:00Z</dc:date>
</item>
</channel>
</rss>

18.25 Creating an RSS Feed (part 2)Tag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0608.html
To create a RSS feed using external librairies, see this HowTo
RSS Feed are XML files. They are easy to create, you can do it yourself.
First we need a bean representing the header
package com.rgagnon.howto.rss;
public class RSSHeader {
private String title = "";
private String description = "";
private String link = "";
private String language = "";
private String copyright = "";
private String author = "";
private String guid = "";
private String pubdate ="";
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;

18.25 Creating an RSS Feed (part 2)Tag(s): XML

}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getCopyright() {
return copyright;
}
public void setCopyright(String copyright) {
this.copyright = copyright;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
public String getPubDate() {
return pubdate;
}
public void setPubDate(String pubdate) {
this.pubdate = pubdate;
}
}

Next we need a bean representing an entry


package com.rgagnon.howto.rss;
public class RSSEntry {
private String title = "";
private String link = "";
private String description = "";
private String language = "";
private String copyright = "";
private String pubDate = "";
private String guid = "";
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;

18.25 Creating an RSS Feed (part 2)Tag(s): XML

}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getCopyright() {
return copyright;
}
public void setCopyright(String copyright) {
this.copyright = copyright;
}
public String getPubDate() {
return pubDate;
}
public void setPubDate(String pubDate) {
this.pubDate = pubDate;
}
public String getGuid() {
return guid;
}
public void setGuid(String guid) {
this.guid = guid;
}
}

Then a class to contain the header plus the entries


package com.rgagnon.howto.rss;
import
import
import
import

java.text.SimpleDateFormat;
java.util.Calendar;
java.util.List;
java.util.Locale;

public class RSSFeed {


private RSSHeader header;
private List<RSSEntry> entries;
public void setHeader(RSSHeader header){
this.header = header;
}
public void setEntries(List entries){
this.entries = entries;
}
public RSSHeader getHeader() {
return header;
}
public List<RSSEntry> getEntries() {
return entries;
}
public static String formatDate(Calendar cal) {
SimpleDateFormat sdf = new SimpleDateFormat(
"EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
return sdf.format(cal.getTime());
}
}

18.25 Creating an RSS Feed (part 2)Tag(s): XML

A class to build the XML


package com.rgagnon.howto.rss;
import java.io.FileOutputStream;
import java.util.Iterator;
import
import
import
import
import
import
import
import
import

javax.xml.stream.XMLEventFactory;
javax.xml.stream.XMLEventWriter;
javax.xml.stream.XMLOutputFactory;
javax.xml.stream.XMLStreamException;
javax.xml.stream.events.Characters;
javax.xml.stream.events.EndElement;
javax.xml.stream.events.StartDocument;
javax.xml.stream.events.StartElement;
javax.xml.stream.events.XMLEvent;

public class RSSWriter {


private static String XML_BLOCK = "\n";
private static String XML_INDENT = "\t";
public static void write(RSSFeed rssfeed, String xmlfile) throws Exception {
XMLOutputFactory output = XMLOutputFactory.newInstance();
XMLEventWriter writer = output.createXMLEventWriter
(new FileOutputStream(xmlfile));
XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent endSection = eventFactory.createDTD(XML_BLOCK);
StartDocument startDocument = eventFactory.createStartDocument();
writer.add(startDocument);
writer.add(endSection);
StartElement rssStart = eventFactory.createStartElement("", "", "rss");
writer.add(rssStart);
writer.add(eventFactory.createAttribute("version", "2.0"));
writer.add(endSection);
writer.add(eventFactory.createStartElement("", "", "channel"));
writer.add(endSection);
RSSHeader header = rssfeed.getHeader();
createNode(writer, "title", header.getTitle());
createNode(writer, "link", header.getLink());
createNode(writer, "description", header.getDescription());
createNode(writer, "language", header.getLanguage());
createNode(writer, "copyright", header.getCopyright());
createNode(writer, "pubDate", header.getPubDate());
Iterator<RSSEntry> iterator = rssfeed.getEntries().iterator();
while (iterator.hasNext()) {
RSSEntry entry = iterator.next();
writer.add(eventFactory.createStartElement("", "", "item"));
writer.add(endSection);
createNode(writer, "title", entry.getTitle());
createNode(writer, "description", entry.getDescription());
createNode(writer, "link", entry.getLink());
createNode(writer, "guid", entry.getGuid());
createNode(writer, "pubDate", entry.getPubDate());
writer.add(eventFactory.createEndElement("", "", "item"));
writer.add(endSection);
}
writer.add(endSection);
writer.add(eventFactory.createEndElement("", "", "channel"));
writer.add(endSection);

18.25 Creating an RSS Feed (part 2)Tag(s): XML

writer.add(eventFactory.createEndElement("", "", "rss"));


writer.add(endSection);
writer.add(eventFactory.createEndDocument());
writer.close();
}
private static void createNode
(XMLEventWriter eventWriter, String name, String value)
throws XMLStreamException {
XMLEventFactory eventFactory = XMLEventFactory.newInstance();
XMLEvent endSection = eventFactory.createDTD(XML_BLOCK);
XMLEvent tabSection = eventFactory.createDTD(XML_INDENT);
StartElement sElement = eventFactory.createStartElement("", "", name);
eventWriter.add(tabSection);
eventWriter.add(sElement);
Characters characters = eventFactory.createCharacters(value);
eventWriter.add(characters);
EndElement eElement = eventFactory.createEndElement("", "", name);
eventWriter.add(eElement);
eventWriter.add(endSection);
}
}

Finally, an example on how to generate a file


package com.rgagnon.howto.rss;
import java.util.ArrayList;
import java.util.Calendar;
public class TestRSSWriter {
private static String RSSFEED = "c:/temp/feed.xml";
public static void main(String[] args) {
System.out.println("Creation RSS Feed (" + RSSFEED + ")");
RSSFeed feed = new RSSFeed();
RSSHeader header = new RSSHeader();
header.setCopyright("Copyright by Real Gagnon");
header.setTitle("Real's HowTo");
header.setDescription("Useful code snippets for Java");
header.setLanguage("en");
header.setLink("http://www.rgagnon.com");
header.setPubDate(RSSFeed.formatDate(Calendar.getInstance()));
feed.setHeader(header);

ArrayList<RSSEntry> entries = new ArrayList<RSSEntry>();


RSSEntry entry = new RSSEntry();
entry.setTitle("The PDF are updated");
entry.setDescription("Java (756 pages), Powerbuilder (197), Javascript (99) and VBS (32
entry.setGuid("http://64.18.163.122/rgagnon/download/index.htm");
entry.setLink("http://64.18.163.122/rgagnon/download/index.htm");
entry.setPubDate(RSSFeed.formatDate(Calendar.getInstance()));
entries.add(entry);
entry = new RSSEntry();
entry.setTitle("Java : Display a TIF");
entry.setDescription("Using JAI, how to display a TIF file");

18.25 Creating an RSS Feed (part 2)Tag(s): XML

entry.setGuid("http://www.rgagnon.com/javadetails/java0605.html");
entry.setLink("http://www.rgagnon.com/javadetails/java0605.html");
entry.setPubDate(RSSFeed.formatDate(Calendar.getInstance()));
entries.add(entry);
feed.setEntries(entries);
try {
RSSWriter.write(feed, TestRSSWriter.RSSFEED);
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("Done.");
}
}

The result is

<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>Real's HowTo</title>
<link>http://www.rgagnon.com</link>
<description>Useful code snippets for Java</description>
<language>en</language>
<copyright>Copyright by Real Gagnon</copyright>
<pubDate>Mon, 23 Jun 2008 11:15:31 0400</pubDate>
<item>
<title>The PDF are updated</title>
<description>Java (756 pages), Powerbuilder (197), Javascript (99) and VBS (32)</descript
<link>http://64.18.163.122/rgagnon/download/index.htm</link>
<guid>http://64.18.163.122/rgagnon/download/index.htm</guid>
<pubDate>Mon, 23 Jun 2008 11:15:31 0400</pubDate>
</item>
<item>
<title>Java : Display a TIF</title>
<description>Using JAI, how to display a TIF file</description>
<link>http://www.rgagnon.com/javadetails/java0605.html</link>
<guid>http://www.rgagnon.com/javadetails/java0605.html</guid>
<pubDate>Mon, 23 Jun 2008 11:15:31 0400</pubDate>
</item>
</channel>
</rss>

18.26 Parse a RSS XML fileTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0557.html

18.26 Parse a RSS XML fileTag(s): XML

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.

18.26.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;
...
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/js0129.html
Using the onLoad event, resize the IFRAME according to its content
Java: Communicate between threads using a Queue
http://www.rgagnon.com/javadetails/java0555.html
BlockingQueue (Java 5) is designed to work in a multithreaded world
JDBC: Escape special character in a LIKE clause
http://www.rgagnon.com/javadetails/java0554.html
How to use LIKE clause wildcards as literals
...

18.26.1 Parsing a feed with Apache Commons Digester

18.26.2 Parsing a feed with ROME


NOTE: See this HowTo for the required jars.

import
import
import
import

com.sun.syndication.feed.synd.*;
com.sun.syndication.feed.synd.SyndFeed;
com.sun.syndication.io.SyndFeedInput;
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);
SyndFeedInput input = new SyndFeedInput();
SyndFeed sf = input.build(new XmlReader(fis));
*/
}
}

18.26.3 RSSUTIL.TLD
A Sun article about a JSP Tag Library to parse a RSS feed.
http://java.sun.com/developer/technicalArticles/javaserverpages/rss_utilities/

18.26.2 Parsing a feed with ROME

18.27 Add a Live bookmarkTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0558.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">

18.28 Validate a RSS feedTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0559.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.

18.29 Attach a CSS to RSS feedTag(s): XML


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0560.html
Browser (ex. IE7/FF) may apply their own style when displaying a RSS Feed so even if you
specify a stylesheet it will be ignored.
18.27 Add a Live bookmarkTag(s): XML

You add a directive to the XML file.


<?xml version="1.0" encoding="utf8"?>
<?xmlstylesheet 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 {
borderwidth: 1px 1px 1px 1px;
borderspacing: 2px;
borderstyle: solid solid solid solid;
bordercolor: blue blue blue blue;
bordercollapse: separate;
backgroundcolor: 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/realhowtoleft.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="rssurl"/>
</div>
<br/>
<xsl:foreach select="item">
<h4><xsl:valueof select="title"/></h4>
<i><xsl:valueof select="pubDate"/></i><br/>
<xsl:valueof select="description"/><br/>
<a HREF="{link}"><xsl:valueof select="link"/></a>
<p/>
</xsl:foreach>
<p/>
<hr/>
<div align="center">
Written and compiled by Real Gagnon 19982007<br/>
[<A HREF="http://www.rgagnon.com/" TARGET="_top"> home </A>]
</div>
</body></html>

18.27 Add a Live bookmarkTag(s): XML

</xsl:template>
</xsl:stylesheet>

See the result.

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

18.27 Add a Live bookmarkTag(s): XML

19 DEPRECATED
19.1 javadeprecated

19.2 * Read me * (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0186.html
These examples works only in a Microsoft JVM and are very Windowsoriented 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.

19.3 Keep the console open after execution (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0187.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();
}

19 DEPRECATED

19.4 Read the Registry (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0188.html
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]);
}
}
}
}

19.4 Read the Registry (this howto is deprecated)Tag(s): DEPRECATED

See also this Howto for a solution using the Sun's JVM and the REG utility.

19.5 Call a Win API (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0189.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').
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 nonexistent 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);

19.5 Call a Win API (this howto is deprecated)Tag(s): DEPRECATED

// 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.

19.6 Display a BMP image (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0190.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 BMPencoded image (see this Howto), in
a Microsoftoriented 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()));
}

19.6 Display a BMP image (this howto is deprecated)Tag(s): DEPRECATED

19.7 Play a WAV audio file (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0191.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();
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...");
}
}

19.7 Play a WAV audio file (this howto is deprecated)Tag(s): DEPRECATED

19.8 Detect if the MS JVM is used (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0192.html
While the Microsoft Java Virtual Machine can run "almost" any 100% pure Java classes, the other
way is not true, nonMS JVM are not able to run classes that used Microsoftspecific classes
(com.ms.*). Check this Howto for some techniques to detect Virtual machine in use.

19.9 Get the latest MS JVM (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0386.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.

19.10 Uninstalling the MS JVM (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0509.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

19.8 Detect if the MS JVM is used (this howto is deprecated)Tag(s): DEPRECATED

19.11 Wrap a Java class in a COM object (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0044.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"

19.11 Wrap a Java class in a COM object (this howto is deprecated)Tag(s): DEPRECATED

strFromJava = objJava.Say("Displayed by VbScript via a Java object")


MsgBox strFromJava, _
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

See also Sun's Javabeans bridge for ActiveX.

19.12 Sign an applet (this howto is deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
19.12 Sign an applet (this howto is deprecated)Tag(s): DEPRECATED

http://www.rgagnon.com/javadetails/../javadetails/java0122.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.
Signing an Applet means signing the JAR containing the Applet. To sign a JAR, you need tools
provided by Netscape. Zigbert is a commandline utility. Also a GUI JAR packager can be used to
sign JARS. You may look at this JAVA Howto 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;

19.13 Bypass the need for a certificate (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0123.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.

19.13 Bypass the need for a certificate (this howto is deprecated)Tag(s): DEPRECATED

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
Java Custom settings
select the permissions given to unsigned content.

Be careful with this because this can be a huge security breach.

19.14 Start an executable on the client (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0124.html
(with Netscape capabilities classes)

import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
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);

19.14 Start an executable on the client (this howto is deprecated)Tag(s): DEPRECATED

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");
}
}
}
}

19.15 Get rid of the message "Warning unsigned applet


window" (this howto is deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0125.html
Before opening the new Frame or Window, use (with Netscape capabilities classes)
PrivilegeManager.enablePrivilege("UniversalTopLevelWindow");

19.16 Read/write a local file from an Applet (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0126.html
(with Netscape capabilities classes)

19.15 Get rid of the message "Warning unsigned applet window" (this howto is deprecated)Tag(s): DEPRE

import
import
import
import
import

java.applet.*;
java.awt.*;
java.awt.event.*;
java.io.*;
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 {
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();
}
}

19.15 Get rid of the message "Warning unsigned applet window" (this howto is deprecated)Tag(s): DEPRE

else {
getAppletContext().showStatus("security not installed");
}
}
}
}

19.17 Write "otherbrowserfriendly" code when using the


Netscape Capabilities package (this howto is deprecated)Tag(s):
DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0127.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
*/
}

19.18 Disable the JIT compiler in Netscape or IE (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0155.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.

19.17 Write "otherbrowserfriendly" code when using the Netscape Capabilities package (this howto is dep

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
g:none
g:{lines,vars,source}

Generate all debugging info


Generate no debugging info
Generate only some debugging info

19.19 Start automatically JAVA when opening Netscape (this


howto is deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0156.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

19.20 Use Netscape Java Console hidden commands (this


howto is deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0152.html
19.19 Start automatically JAVA when opening Netscape (this howto is deprecated)Tag(s): DEPRECATED

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"
09: set applet debug level to <n>

19.21 Avoid the Netscape "Couldn't connect to '' with origin


from 'localclasspathclasses'" message. (this howto is
deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0162.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

19.22 Get the client IP address (deprecated)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0095.html
With modern java plugin installation, only "127.0.0.1" is displayed.

19.21 Avoid the Netscape "Couldn't connect to '' with origin from 'localclasspathclasses'" message. (this h

The only reliable way is to get this information from the serverside.
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".

Using a Servlet, this can be done with :


public void service(HttpServletRequest req, HttpServletResponse res)
throws IOException {
String IP = req.getRemoteAddr();
}

19.23 Detect the browser/JVM type (deprecated)Tag(s):


Environment DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0160.html
This HowTo is obsolete. Check this one instead : Detect browser type from an Applet
One way is to instanciate a known browserspecific method and catch the Exception if not found
import java.applet.*;
public class BrowserDetector extends Applet {
public void init() {
if ( isNetscape() )

19.23 Detect the browser/JVM type (deprecated)Tag(s): Environment DEPRECATED

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";
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";
}

19.23 Detect the browser/JVM type (deprecated)Tag(s): Environment DEPRECATED

For example, our MyApplet.class exists in three versions. One is using Microsoftspecific classes,
the other is a JDK1.1 applet and finally a version for JDK102only 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>
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.

19.24 Post a message on a newsserver using NNTP protocol


(this howto is deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0087.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

19.24 Post a message on a newsserver using NNTP protocol (this howto is deprecated)Tag(s): DEPRECAT

**
eg. java NttpPost news.server.com
*/
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.

19.25 Read messages from a newsserver (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0088.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;

19.25 Read messages from a newsserver (this howto is deprecated)Tag(s): DEPRECATED

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);
}
}
catch (NntpProtocolException e) {
/*
** probably a cancelled article, just skip it
*/
}
}
}
}

19.26 Get a list of headers from a newsgroup (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0089.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) {
/*

19.26 Get a list of headers from a newsgroup (this howto is deprecated)Tag(s): DEPRECATED

** probably a cancelled article, just skip it


*/
}
}
}
}

19.27 Get a list of all available newsgroup from a newsserver


(this howto is deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0090.html
This snippet uses an undocumented Sun package [JDK1.1]

import
import
import
import

sun.net.nntp.*;
sun.net.*;
java.io.*;
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);
}
}
}

19.27 Get a list of all available newsgroup from a newsserver (this howto is deprecated)Tag(s): DEPRECAT

19.28 Detect if Swing is installed (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0194.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

19.29 Make Swing always available from Netscape (this howto is


deprecated)Tag(s): DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0195.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 preJava 2 Swing.
With that version you need the Java plugin to be able to use the swing classes.

19.28 Detect if Swing is installed (this howto is deprecated)Tag(s): DEPRECATED

19.30 Send email with attachment (DEPRECATED)Tag(s):


DEPRECATED
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../jsdetails/js0013.html
Netscape only
<FORM ACTION="mailto:someone@somewhere.com?subject=REPORT"
METHOD="POST" ENCTYPE="multipart/formdata">
<INPUT TYPE="FILE" NAME="myReportFile" SIZE="70"><BR>
<INPUT TYPE="SUBMIT">
</FORM>

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

19.30 Send email with attachment (DEPRECATED)Tag(s): DEPRECATED

20 String/Number
20.1 javastringnumber

20.2 * Read me *Tag(s): Language String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0290.html
If you have difficulty to find what you are your are looking for, try do use search on this site using
Google.
Enter your search terms
www.rgagnon.com

Web

Submit search form


If you can't find then you may want to look at these other sites :
Java Glossary
Many subjects covered in depth.
The Java Developers Almanac 1.4 (exampledepot.com)
Contains many code examples.
Sun Developers Online Community
You need to register first (free). Be sure to search the forums first before asking a question because
regular posters can be a little bit rude if you don't!
Stack Overflow
A site where you can ask question (not restricted to Java), really innovative in the way it works.
Participants are really cool.
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

20 String/Number

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

20.3 Convert from type X to type YTag(s):


String/Number String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0004.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.toString(f);

String to integer :
str = "25";
int i = Integer.valueOf(str).intValue();
or
int i = Integer.parseInt(str);

String to double :
20.3 Convert from type X to type YTag(s): String/Number String/Number

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 Howto
hexadecimal (String) to integer :
int i = Integer.valueOf("B8DA3", 16).intValue();
or
int i = Integer.parseInt("B8DA3", 16);

char to String
String s = String.valueOf('c');

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;

20.3 Convert from type X to type YTag(s): String/Number String/Number

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, use the try/catch mechanism :
try{
i = Integer.parseInt(aString);
}
catch(NumberFormatException e) {
...
}

20.4 Strip certain characters from a StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0018.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;
}

20.4 Strip certain characters from a StringTag(s): String/Number

}
NOTE: You may want to look at Howto 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 ) {
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
*/
}
}

20.5 Replace/remove character in a StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0030.html
To replace all occurences of a given character :
20.5 Replace/remove character in a StringTag(s): String/Number

String

tmpString = myString.replace( '\'', '*' );

System.out.println( "Original = " + myString );


System.out.println( "Result
= " + tmpString );

The String class offers the replaceAll() method that can be used with String or char (JDK1.4+).
replaceAll() accepts a regex as argument so it can be very powerful.
To delete all nondigit in a String
System.out.println(
"@*1#^2$@!34#5ajs67>?<{8_(9SKJDH".replaceAll("\\D", ""));
// output : 123456789

If your project already depends on Apache Commons then StringUtils provides many methods to
manipulate String objects, no need to reinvent the wheel!
import org.apache.commons.lang.StringUtils;
...
foo = StringUtils.replace(foo, "bar", "baz");
// replace in foo the occurrence of bar" by "baz"

To replace a character at a specified position :


public static String replaceCharAt(String s, int pos, char c) {
StringBuffer buf = new StringBuffer( s );
buf.setCharAt( pos, c );
return buf.toString( );
}

To remove a character :
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();
}

To remove a character at a specified position:


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 Optimize Howto for String handling techniques.

20.5 Replace/remove character in a StringTag(s): String/Number

20.6 Replace every occurences of a string within a stringTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0320.html
String.replaceAll() replaces each substring of this String that matches the given regular expression
with the given replacement. Remember that StringreplaceAll() returns a new String so keep the
result!
[JDK1.4]
public class Test{
public static void main(String[] args){
String text = "hello world from www.rgagnon.com : hello world";
// replace all
String result = text.replaceAll("(?:hello world)", "bonjour le monde");
System.out.println(result);
// replace only the first match
result = text.replaceFirst("(?:hello world)", "bonjour le monde");
System.out.println(result);
/*
output :
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. 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.
public class Test {
public static void main(String[] args){
String text = "\\\\server\\apps\\file.txt";
System.out.println("original : " + text);
System.out.println("converted : " + text.replaceAll("\\\\","\\\\\\\\"));
/*
output :
original : \\server\apps\file.txt
converted : \\\\server\\apps\\file.txt
*/
}
}

Since replaceAll() is based on a regex expression, it is very easy to make the substituion case
insensitive.
20.6 Replace every occurences of a string within a stringTag(s): String/Number

public class Test {


public static void main(String[] args) {
String test = "Real's hoWTo";
System.out.println("original : " + test);
test= test.replaceAll("(?i)howto", "HowTo");
System.out.println("converted : " + test); // output : Real's HowTo
}
}

[ < JDK1.4]
String,replaceAll() is not available with Java version older than 1.4, you need to code the
substitution. This snippet provides a simple replacesAll() equivalent.
public static String replaceAll(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();
}

20.7 "Tokenize" a stringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0015.html
import java.util.*;
...
StringTokenizer st =
new StringTokenizer
("This is the string to be tokenized", " ");
while(st.hasMoreTokens()){
String s=st.nextToken();
System.out.println(s);
}
/*

20.7 "Tokenize" a stringTag(s): String/Number

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;
}
// 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);
}

20.7 "Tokenize" a stringTag(s): String/Number

/**
* 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);
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();

20.7 "Tokenize" a stringTag(s): String/Number

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();
}
}
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() {

20.7 "Tokenize" a stringTag(s): String/Number

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) {
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 =

20.7 "Tokenize" a stringTag(s): String/Number

new EnhancedStringTokenizer(
testStr,
"|",
EnhancedStringTokenizer.NO_CONSECUTIVE_DELIMS);
while (st.hasMoreTokens()) {
String aux = st.nextToken();
System.out.print(aux.length());
System.out.println(">"+aux+"<");
}
}
}

See also this HowTo to split a given String into an array based on a specific separator.
For JDK1.4+, you may want to look at the String.split() method. See this HowTo.

20.8 Split a string using String.split()Tag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0438.html
The String class has a split() (since 1.4) method that will return a String array.
public class StringSplit {
public static void main(String args[]) throws Exception{
String testString = "RealHowTo";
System.out.println(
java.util.Arrays.toString(
testString.split("")
));
// 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 :
public class StringSplit {
public static void main(String args[]) throws Exception{
String testString = "Real.How.To";
// bad
System.out.println(java.util.Arrays.toString(
testString.split(".")
));
// output : []
// good
System.out.println(java.util.Arrays.toString(

20.8 Split a string using String.split()Tag(s): String/Number

testString.split("\\.")
));
// output : [Real, How, To]
}
}

And
public class StringSplit {
public static void main(String args[]) throws Exception{
String testString = "Real|How|To";
// bad
System.out.println(java.util.Arrays.toString(
testString.split("|")
));
// output : [, R, e, a, l, |, H, o, w, |, T, o]
// good
System.out.println(java.util.Arrays.toString(
testString.split("\\|")
));
// output : [Real, How, To]
}
}

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 "\" !
Consider this example
public class StringSplit {
public static void main(String args[]) throws Exception{
String testString = "Real|How|To|||";
System.out.println(
java.util.Arrays.toString(
testString.split("\\|")
));
// output : [Real, How, To]
}
}

The result does not include the empty strings between the "|" separator. To keep the empty strings :
public class StringSplit {
public static void main(String args[]) throws Exception{
String testString = "Real|How|To|||";
System.out.println(
java.util.Arrays.toString(
testString.split("\\|", 1)
));
// output : [Real, How, To, , , ]
}
}

See split(String.int).
String.split() is only available since JDK 1.4.

20.8 Split a string using String.split()Tag(s): String/Number

With previous version, java.util.StringTokeniser can be used.


See this HowTo
Some notes from A. Gonzales about String.split()

Special cases using String.split():


public class StringSplit {
public static void main(String args[]) throws Exception{
System.out.println(
java.util.Arrays.toString(
" s".split(" ")
));
// output : [, , s]
System.out.println(
java.util.Arrays.toString(
"".split("")
));
// output : []
System.out.println(
java.util.Arrays.toString(
" ".split(" ")
));
// output : []
System.out.println(
java.util.Arrays.toString(
"
".split(" ")
));
// output : []
System.out.println(
java.util.Arrays.toString(
" s ".split(" ")
));
// output : [, s]
}
}

It's 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{
String testString = "Real How To"; // extra space
System.out.println(
java.util.Arrays.toString(
testString.split(" ")
));
// output : [Real, , How, To]
}

20.8 Split a string using String.split()Tag(s): String/Number

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{
String testString = "Real How To";
System.out.println(
java.util.Arrays.toString(
testString.split("\\s+")
));
// output : [Real, How, To]
}
}

Since String.split() is based on regular expression, you can make some complex operations with a
simple call!
String testString = "{RealHowto}{java0438.html}{usage of String.split()}";
System.out.println(java.util.Arrays.toString(
testString.split("[{}]")
));
// output : [, RealHowto, , java0438.html, , usage of String.split()]
// note : extra empty elements :(

To split a long string into into fixedlength parts. In this example, we split in groups of 3 characters :
String testString = "012345678901234567890";
System.out.println(java.util.Arrays.toString(
testString.split("(?<=\\G.{3})")
));
// output : [012, 345, 678, 901, 234, 567, 890]

To split but keep the separator :


String testString = "RealHowto!java0438.html!usage of String.split()!";
System.out.println(java.util.Arrays.toString(
testString.split("(?<=[!])")
));
// output : [RealHowto!, java0438.html!, usage of String.split()!]
}

20.9 Optimize String operationsTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0129.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.
20.9 Optimize String operationsTag(s): String/Number

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( );

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 Howto, 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 Howto, 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.

20.9 Optimize String operationsTag(s): String/Number

20.9.1 StringBuilder (JDK1.5)


The StringBuilder class, introduced in J2SE 5.0, differs from StringBuffer in that it is
unsynchronized. When only a single thread at a time will access the object (the most common
case), using a StringBuilder is more efficient than using a StringBuffer.
The code
StringBuffer sb = new StringBuffer(300);
for (int i = 0; i < 100; i++) {
sb.append(i).append('\n');
}

is less efficient (in singlethread context) than


StringBuilder sb = new StringBuilder(300);
for (int i = 0; i < 100; i++) {
sb.append(i).append('\n');
}

20.10 Remove spaces from a stringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0352.html
Remove all spaces
public String removeSpaces(String s) {
StringTokenizer st = new StringTokenizer(s," ",false);
String t="";
while (st.hasMoreElements()) t += st.nextElement();
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.
public class BlankRemover {
private BlankRemover () {}
/* remove leading whitespace */
public static String ltrim(String source) {
return source.replaceAll("^\\s+", "");
}

20.9.1 StringBuilder (JDK1.5)

/* 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 =
"[121212121212121212121212]";
String newStr = oldStr.replaceAll("", " ");
System.out.println(newStr);
System.out.println("*" + BlankRemover.ltrim(newStr) + "*");
System.out.println("*" + BlankRemover.rtrim(newStr) + "*");
System.out.println("*" + BlankRemover.itrim(newStr) + "*");
System.out.println("*" + BlankRemover.lrtrim(newStr) + "*");
}
/*
output :
[1 2 1 2 1 2 1 2 1 2 1
2 1 2 1 2 1 2 1 2 1 2 1 2]
*[1 2 1 2 1 2 1 2 1 2 1
2 1 2 1 2 1 2 1 2 1 2 1 2]
*
*
[1 2 1 2 1 2 1 2 1 2 1
2 1 2 1 2 1 2 1 2 1 2 1 2]*
*
[1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2]
*
*[1 2 1 2 1 2 1 2 1 2 1
2 1 2 1 2 1 2 1 2 1 2 1 2]*
*/
}

Thanks to jsanza for the tip!

20.11 Test if a String starts with a digit or uppercase


letterTag(s): String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0430.html
With JDK1.4, regex expression can be handled directly.
import java.util.regex.Pattern;

20.11 Test if a String starts with a digit or uppercase letterTag(s): String/Number

boolean startsWithDigitOrUpper(String s) {
return Pattern.compile("^[AZ09]").matcher(s).find();
}

20.12 Get InputStream from a StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0442.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

20.13 Easy String paddingTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0448.html
[JDK 1.5]
Since 1.5, String.format() can be used to left/right pad a given string.
public class StringUtils {
private StringUtils() {}
// pad with " " to the right to the given length (n)
public static String padRight(String s, int n) {
return String.format("%1$" + n + "s", s);
}
// pad with " " to the left to the given length (n)
public static String padLeft(String s, int n) {
return String.format("%1$" + n + "s", s);
}
public static void main(String args[]) throws Exception {
System.out.println(StringUtils.padRight("Howto", 20) + "*");
System.out.println(StringUtils.padLeft("Howto", 20) + "*");
}
/* output

20.12 Get InputStream from a StringTag(s): String/Number

Howto

*
Howto*

*/
}

These oneliners are useful to pad to a fix length with a given character.
public class Test {
public static void main(String args[]) throws Exception {
System.out.println(String.format("%10s", "howto").replace(' ', '*'));
System.out.println(String.format("%10s", "howto").replace(' ', '*'));
}
/*

output

*****howto
howto*****
*/
}

To mask a password in a log file :


public class Test {
public static void main(String args[]) throws Exception {
String password = "howto";
System.out.println(password);
System.out.println(String.format("%"+password.length()+"s", "").replace(' ', '*'));
}
/* output
howto
*****
*/
}

[JDK1.4 or less]
/**
* Pads a String <code>s</code> to take up <code>n</code>
* characters, padding with char <code>c</code> on the
* left (<code>true</code>) or on the right (<code>false</code>).
* Returns <code>null</code> if passed a <code>null</code>
* String.
**/
public static String paddingString(String s, int n, char c,
boolean paddingLeft) {
if (s == null) {
return s;
}
int add = n s.length(); // may overflow int size... should not be a problem in real life
if(add <= 0){
return s;
}
StringBuffer str = new StringBuffer(s);

20.12 Get InputStream from a StringTag(s): String/Number

char[] ch = new char[add];


Arrays.fill(ch, c);
if(paddingLeft){
str.insert(0, ch);
} else {
str.append(ch);
}
return str.toString();
}

Thanks to P. Buluschek for this snippet.

20.14 Replace \r\n with the <br> tagTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0454.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>");

20.15 Unaccent lettersTag(s): Internationalization String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0456.html

20.14 Replace \r\n with the <br> tagTag(s): String/Number

The following snippets remove from a String accented letters and replace them by their regular
ASCII equivalent.
These can be useful before inserting data into a database to made sorting easier.

20.15.1 Using java.text.Normalizer


It's a simple using the java.text.Normalizer class.
We are calling the normalize(). If we pass , the method returns a + ` . Then using a regular
expression, we clean up the string to keep only valid USASCII characters.
import java.text.Normalizer;
import java.util.regex.Pattern;
public class StringUtils {
private StringUtils() {}
public static String unAccent(String s) {
//
// JDK1.5
//
use sun.text.Normalizer.normalize(s, Normalizer.DECOMP, 0);
//
String temp = Normalizer.normalize(s, Normalizer.Form.NFD);
Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
return pattern.matcher(temp).replaceAll("");
}
public static void main(String args[]) throws Exception{
String value = " _ @";
System.out.println(StringUtils.unAccent(value));
// output : e a i _ @
}
}

20.15.2 Using String.replaceAll()


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
s
s
s

=
=
=
=
=

s.replaceAll("[]","e");
s.replaceAll("[]","u");
s.replaceAll("[]","i");
s.replaceAll("[]","a");
s.replaceAll("","o");

s
s
s
s
s

=
=
=
=
=

s.replaceAll("[]","E");
s.replaceAll("[]","U");
s.replaceAll("[]","I");
s.replaceAll("[]","A");
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
}
}

20.15.1 Using java.text.Normalizer

20.15.3 The String.indexOf()


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
+ "AaOoNn"
// tilde
+ "AaEeIiOoUuYy" // umlaut
+ "Aa"
// ring
+ "Cc"
// cedilla
+ "OoUu"
// double acute
;
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\u00D1\u00F1"
+ "\u00C4\u00E4\u00CB\u00EB\u00CF\u00EF\u00D6\u00F6\u00DC\u00FC\u0178\u00FF"
+ "\u00C5\u00E5"
+ "\u00C7\u00E7"
+ "\u0150\u0151\u0170\u0171"
;
// private constructor, can't be instanciated!
private AsciiUtils() { }
// remove accentued from a string and replace with ascii equivalent
public static String convertNonAscii(String s) {
if (s == null) return null;
StringBuilder sb = new StringBuilder();
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
}
}

20.15.3 The String.indexOf()

Thanks to MV Bastos for the "tilde" bug fix


Thanks to L.. Tama for the missing !
Thanks to T. Hague for the missing "double acute";

As a bonus, here a method to convert a given string to uppercase with no accent. This can be
useful in a database field to simplify name searching with accent or not.

public class StringUtils {


private StringUtils() {}
private static final String UPPERCASE_ASCII =
"AEIOU" // grave
+ "AEIOUY" // acute
+ "AEIOUY" // circumflex
+ "AON" // tilde
+ "AEIOUY" // umlaut
+ "A" // ring
+ "C" // cedilla
+ "OU" // double acute
;
private static final String UPPERCASE_UNICODE =
"\u00C0\u00C8\u00CC\u00D2\u00D9"
+ "\u00C1\u00C9\u00CD\u00D3\u00DA\u00DD"
+ "\u00C2\u00CA\u00CE\u00D4\u00DB\u0176"
+ "\u00C3\u00D5\u00D1"
+ "\u00C4\u00CB\u00CF\u00D6\u00DC\u0178"
+ "\u00C5"
+ "\u00C7"
+ "\u0150\u0170"
;
public static String toUpperCaseSansAccent(String txt) {
if (txt == null) {
return null;
}
String txtUpper = txt.toUpperCase();
StringBuilder sb = new StringBuilder();
int n = txtUpper.length();
for (int i = 0; i < n; i++) {
char c = txtUpper.charAt(i);
int pos = UPPERCASE_UNICODE.indexOf(c);
if (pos > 1){
sb.append(UPPERCASE_ASCII.charAt(pos));
}
else {
sb.append(c);
}
}
return sb.toString();
}

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


String s =
"The result : ,,,,,,,,,,,,,,,,,,,,,,";
System.out.println(
StringUtils.toUpperCaseSansAccent(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
}
}

20.15.3 The String.indexOf()

20.16 Apply a mask to StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0457.html
JDK1.4
public class TestMF {
public static String value = "A1234B567Z";
public static String mask = "AAAAAAAAAA";
public static void main(String args[]) {
try {
System.out.println(formatString(value,mask));
// output : A1234B567Z
}
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
#
'
U
L
A
?
*
H

Description
Any valid number, uses Character.isDigit .
Escape character, used to escape any of
the special formatting characters.
Any character ( Character.isLetter ).
All lowercase letters are mapped to upper case.
Any character ( Character.isLetter ).
All upper case letters are mapped to lower case.
Any character or number
( Character.isLetter or Character.isDigit )
Any character ( Character.isLetter ).
Anything.
Any hex character (09, af or AF).

20.16 Apply a mask to StringTag(s): String/Number

20.17 Format a String (JDK1.5)Tag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0463.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");
System.out.println(s);
// 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);
System.out.println(s);
// output : Welcome Real's HowTo at http://www.rgagnon.com (2010 06 26)

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));
}
}

20.17 Format a String (JDK1.5)Tag(s): String/Number

Output:
|FirstName
|Real
|John
|John

|Init.
|
|D
|F.

|LastName
|Gagnon
|Doe
|Kennedy

|
|
|
|

To align numbers :
String format = "%10.2f\n"; // width == 10 and 2 digits after the dot
float [] floats = {123.45f, 99.0f, 23.2f, 45.0f};
for(int i=0; i<floats.length; i++) {
float value = floats[i];
System.out.format(format, value);
}

Output :
123.45
99.00
23.20
45.00

20.18 Replace a "\" by "\\"Tag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0476.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
public class Test {
public static void main(String[] args){
String text = "\\\\server\\apps\\file.txt";
System.out.println("original : " + text);
System.out.println("converted : " + text.replaceAll("\\\\","\\\\\\\\"));
/*
output :
original : \\server\apps\file.txt
converted : \\\\server\\apps\\file.txt
*/
}
}

See also this HowTo.

20.18 Replace a "\" by "\\"Tag(s): String/Number

20.19 Substitute tokens in a StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0494.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.

20.20 Compare accentuated lettersTag(s):


Internationalization String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0496.html
From the 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.

In this code, we have 2 strings, "tat" and "famille". We expect that "tat" is before "famille". But
String.compareTo() will return that "famille" is before "tat".
class Test {
public static void main(String args[]) {
String s1 = "tat";
String s2 = "famille";
// here we are expecting "" < "f"
if (s1.compareTo(s2) > 0) {
if (s1.compareTo(s2) > 0) {
// s1 lexicographically follows s2 which is not true!
System.out.println("not ok " + s1 + " > " + s2 );
}
}

20.19 Substitute tokens in a StringTag(s): String/Number

/*
output :
not ok tat > famille
*/
}

The fix is to use java.text.Collator.compareTo(). From the 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.
import java.text.Collator;
public class Test {
public static void main(String args[]) {
String s1 = "tat";
String s2 = "famille";
// Collator c = Collator.getInstance(java.util.Locale.FRANCE);
Collator c = Collator.getInstance();
c.setStrength(Collator.PRIMARY);
if (c.compare(s1, s2) < 0) {
// s2 lexicographically follows s1
System.out.println("ok " + s1 + " < " + s2);
}
}
/*
output :
ok tat < famille
*/
}

Equality
To compare without taking into account the presence of accentued so that "" == "e", we use a
Collator.
import java.text.Collator;
// import java.util.Locale;
public class TextTest {
public static void main(String ... args) {
String a = "Real";
String b = "Ral";
System.out.println(a + " and " + b + " equals? " +
check(a,b));
/*
* output :
* Real and Ral equals? true
*/
}

public static boolean check(String a, String b) {

20.19 Substitute tokens in a StringTag(s): String/Number

// Collator c = Collator.getInstance(Locale.US);
//
// accent and upper/lowercase not taken into account
Collator c = Collator.getInstance();
c.setStrength(Collator.PRIMARY);
return (c.compare(a,b) == 0 );
}
}

See this HowTo.

20.21 Create a String with fixed length and filled with a specific
characterTag(s): String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0512.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);
}
}

20.22 Unquote a StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0522.html
We use the fact that the Properties unquote a String, so we simply simulate a Property read with our
20.21 Create a String with fixed length and filled with a specific characterTag(s): String/Number

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
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");
}
}

20.23 Escape HTML special characters from a StringTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0306.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;

20.23 Escape HTML special characters from a StringTag(s): String/Number

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;
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 (nonbreaking 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 nonbreaking 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;

20.23 Escape HTML special characters from a StringTag(s): String/Number

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;");
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();
}

20.24 Unescape HTML special characters from a StringTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0307.html

20.25 Using HashMap


import java.util.*;
public class StringUtils {
private StringUtils() {}

20.24 Unescape HTML special characters from a StringTag(s): String/Number

private static HashMap<String,String> 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");
}
/*
Here the original recursive version.
It is fine unless you pass a big string then a Stack Overflow is possible :(

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, i + 1); // recursive call
}
}
}
return source;
}
M. McNeely Jr. has sent a version with do...while()loop which is more robust.
Thanks to him!
*/
public static final String unescapeHTML(String source) {
int i, j;
boolean continueLoop;
int skip = 0;

20.24 Unescape HTML special characters from a StringTag(s): String/Number

do {
continueLoop = false;
i = source.indexOf("&", skip);
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 = source.substring(0, i)
+ value + source.substring(j + 1);
continueLoop = true;
}
else if (value == null){
skip = i+1;
continueLoop = true;
}
}
}
} while (continueLoop);
return source;
}
public static void main(String args[]) throws Exception {
// to see accented character to the console (Windows DOS Shell)
java.io.PrintStream ps = new java.io.PrintStream(System.out, true, "Cp850");
String test = "&copy; 2007 R&eacute;al Gagnon &lt;www.rgagnon.com&gt;";
ps.println(test + "\n>\n" +unescapeHTML(test));
/*
output ((Windows DOS Shell):
&copy; 2007 R&eacute;al Gagnon &lt;www.rgagnon.com&gt;
>
2007 Ral Gagnon <www.rgagnon.com>
*/
}
}

20.26 Using Array


public class StringUtils {
private 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;"

20.26 Using Array

,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,

">" } ,
"\"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,
"" } ,

{
{
{
{
{
{
};

"&Ugrave;"
"&Ucirc;"
"&Uuml;"
"&copy;"
"&reg;"
"&euro;"

,
,
,
,
,
,

"" } ,
"" } ,
"" } ,
"\u00a9"
"\u00ae"
"\u20a0"

{ "&ucirc;"
{ "&uuml;"
{ "&nbsp;"
} ,
} ,
}

, "" } ,
, "" } ,
, " " } ,

public static final String unescapeHTML(String s, int start){


int i, j, k;
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, i); // recursive call
}
}
}
return s;
}
public static void main(String args[]) throws Exception {
// to see accented character to the console
java.io.PrintStream ps = new java.io.PrintStream(System.out, true, "Cp850");
String test = "&copy; 2000 R&eacute;al Gagnon &lt;www.rgagnon.com&gt;";
ps.println(test + "\n>\n" +unescapeHTML(test, 0));
/*
output :
&copy; 2000 R&eacute;al Gagnon &lt;www.rgagnon.com&gt;
>
2000 Ral 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

20.26 Using Array

20.27 Detect nonASCII character in a StringTag(s):


Internationalization String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0536.html
import
import
import
import
import

java.nio.ByteBuffer;
java.nio.CharBuffer;
java.nio.charset.Charset;
java.nio.charset.CharsetDecoder;
java.nio.charset.CharacterCodingException;

public class StringUtils {


public static boolean isPureAscii(String v) {
byte bytearray [] = v.getBytes();
CharsetDecoder d = Charset.forName("USASCII").newDecoder();
try {
CharBuffer r = d.decode(ByteBuffer.wrap(bytearray));
r.toString();
}
catch(CharacterCodingException e) {
return false;
}
return true;
}
public static void main (String args[])
throws Exception {
String test = "Ral";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
/*
* output :
*
Ral isPureAscii() : false
*
Real isPureAscii() : true
*/
}
}

A different (and simpler) approach is to take a given string and check if it's possible to encode it into
ASCII.
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
public class StringUtils {
static CharsetEncoder asciiEncoder =
Charset.forName("USASCII").newEncoder(); // or "ISO88591" for ISO Latin 1

20.27 Detect nonASCII character in a StringTag(s): Internationalization String/Number

public static boolean isPureAscii(String v) {


return asciiEncoder.canEncode(v);
}
public static void main (String args[])
throws Exception {
String test = "Ral";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
test = "Real";
System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
/*
* output :
*
Ral isPureAscii() : false
*
Real isPureAscii() : true
*/
}
}

Another way is to use a regular expression, see this Javascript HowTo for a hint!
To simply strip any nonascii characters form a string
public class Test {
public static void main(String args[]){
String input = "ea";
String output = input.replaceAll("[^\\p{ASCII}]", "");
System.out.println(output);
/*
* output : ea
*/
}
}

See also Unaccent letters.

20.28 Remove HTML tags from a file to extract only the


TEXTTag(s): IO String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0424.html

20.29 Using regular expression


A special regular expression is used to strip out anything between a < and > .
import java.io.*;
public class Html2TextWithRegExp {
private Html2TextWithRegExp() {}

20.28 Remove HTML tags from a file to extract only the TEXTTag(s): IO String/Number Networking

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


StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new FileReader("javanew.html"));
String line;
while ( (line=br.readLine()) != null) {
sb.append(line);
// or
// sb.append(line).append(System.getProperty("line.separator"));
}
String nohtml = sb.toString().replaceAll("\\<.*?>","");
System.out.println(nohtml);
}
}

However if any Javascript is present, the script will be seen as text. Also you may need to add some
logic during the reading to take into account only what is inside the <BODY> tag.

20.30 Using javax.swing.text.html.HTMLEditorKit


In most cases, the HTMLEditorKit is used with a JEditorPane text component but it can be also
used directly to extract text from an HTML page.
import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.util.List;
java.util.ArrayList;

import
import
import
import

javax.swing.text.html.parser.ParserDelegator;
javax.swing.text.html.HTMLEditorKit.ParserCallback;
javax.swing.text.html.HTML.Tag;
javax.swing.text.MutableAttributeSet;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String> extractText(Reader reader) throws IOException {
final ArrayList<String> list = new ArrayList<String>();
ParserDelegator parserDelegator = new ParserDelegator();
ParserCallback parserCallback = new ParserCallback() {
public void handleText(final char[] data, final int pos) {
list.add(new String(data));
}
public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos) { }
public void handleEndTag(Tag t, final int pos) { }
public void handleSimpleTag(Tag t, MutableAttributeSet a, final int pos) { }
public void handleComment(final char[] data, final int pos) { }
public void handleError(final java.lang.String errMsg, final int pos) { }
};
parserDelegator.parse(reader, parserCallback, true);
return list;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader("javanew.html");
List<String> lines = HTMLUtils.extractText(reader);
for (String line : lines) {
System.out.println(line);
}

20.30 Using javax.swing.text.html.HTMLEditorKit

}
}

Note that the HTMLEditorKit can be easily confused if the HTML to be parsed is not wellformed.

20.31 Using an HTML parser


This is maybe the best solution (if the choosen parser is good !).
There are many parsers available on the net. In this HowTo, I will use the OpenSource package
Jsoup.
Jsoup is entirely self contained and has no dependencies which is a good thing.
import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.io.BufferedReader;
org.jsoup.Jsoup;

public class HTMLUtils {


private HTMLUtils() {}
public static String extractText(Reader reader) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(reader);
String line;
while ( (line=br.readLine()) != null) {
sb.append(line);
}
String textOnly = Jsoup.parse(sb.toString()).text();
return textOnly;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader
("C:/RealHowTo/topics/javalanguage.html");
System.out.println(HTMLUtils.extractText(reader));
}
}

20.32 Using Apache Tika


Apache Tika
import java.io.FileInputStream;
import java.io.InputStream;
import
import
import
import
import
import

org.apache.tika.metadata.Metadata;
org.apache.tika.parser.AutoDetectParser;
org.apache.tika.parser.ParseContext;
org.apache.tika.parser.Parser;
org.apache.tika.sax.BodyContentHandler;
org.xml.sax.ContentHandler;

public class ParseHTMLWithTika {


public static void main(String args[]) throws Exception {
InputStream is = null;

20.31 Using an HTML parser

try {
is = new FileInputStream("C:/Temp/javax.html");
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
Parser parser = new AutoDetectParser();
parser.parse(is, contenthandler, metadata, new ParseContext());
System.out.println(contenthandler.toString());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (is != null) is.close();
}
}
}

See Extract text from a PDF using Apache Tika, Get Mime Type from a file.
See also Extract links from an HTML page

20.33 Extract links from an HTML pageTag(s):


String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0639.html

20.34 Using javax.swing.text.html.HTMLEditorKit


import
import
import
import
import

java.io.IOException;
java.io.FileReader;
java.io.Reader;
java.util.List;
java.util.ArrayList;

import
import
import
import
import

javax.swing.text.html.parser.ParserDelegator;
javax.swing.text.html.HTMLEditorKit.ParserCallback;
javax.swing.text.html.HTML.Tag;
javax.swing.text.html.HTML.Attribute;
javax.swing.text.MutableAttributeSet;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String> extractLinks(Reader reader) throws IOException {
final ArrayList<String> list = new ArrayList<String>();
ParserDelegator parserDelegator = new ParserDelegator();
ParserCallback parserCallback = new ParserCallback() {
public void handleText(final char[] data, final int pos) { }
public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos) {

20.33 Extract links from an HTML pageTag(s): String/Number Networking

if (tag == Tag.A) {
String address = (String) attribute.getAttribute(Attribute.HREF);
list.add(address);
}
}
public
public
public
public

void
void
void
void

handleEndTag(Tag t, final int pos) { }


handleSimpleTag(Tag t, MutableAttributeSet a, final int pos) { }
handleComment(final char[] data, final int pos) { }
handleError(final java.lang.String errMsg, final int pos) { }

};
parserDelegator.parse(reader, parserCallback, false);
return list;
}
public final static void main(String[] args) throws Exception{
FileReader reader = new FileReader("javanew.html");
List<String> links = HTMLUtils.extractLinks(reader);
for (String link : links) {
System.out.println(link);
}
}
}

20.35 Using an HTML parser


In this HowTo, I will use the OpenSource package Jsoup.
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import
import
import
import

org.jsoup.Jsoup;
org.jsoup.nodes.Document;
org.jsoup.nodes.Element;
org.jsoup.select.Elements;

public class HTMLUtils {


private HTMLUtils() {}
public static List<String>extractLinks(String url) throws IOException {
final ArrayList<String> result = new ArrayList<String>();
Document doc = Jsoup.connect(url).get();
Elements links = doc.select("a[href]");
Elements media = doc.select("[src]");
Elements imports = doc.select("link[href]");
// href ...
for (Element link : links) {
result.add(link.attr("abs:href"));
}
// img ...
for (Element src : media) {
result.add(src.attr("abs:src"));
}
// js, css, ...
for (Element link : imports) {
result.add(link.attr("abs:href"));
}

20.35 Using an HTML parser

return result;
}

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


String site = "http://www.rgagnon.com/topics/javalanguage.html";
List<String> links = HTMLUtils.extractLinks(site);
for (String link : links) {
System.out.println(link);
}
}
}

See also how to extract text from an HTML page.

20.36 Convert a byte array to a Hex stringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0596.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)'0',
(byte)'4',
(byte)'8',
(byte)'c',
};

byte[] HEX_CHAR_TABLE
(byte)'1', (byte)'2',
(byte)'5', (byte)'6',
(byte)'9', (byte)'a',
(byte)'d', (byte)'e',

= {
(byte)'3',
(byte)'7',
(byte)'b',
(byte)'f'

public static String getHexString(byte[] raw)


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];

20.36 Convert a byte array to a Hex stringTag(s): String/Number

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
*/
}
}

A more elegant (based on a suggestion by Lew on usenetcljp)


static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
if ( raw == null ) {
return null;
}
final StringBuilder hex = new StringBuilder( 2 * raw.length );
for ( final byte b : raw ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}

20.37 Apply proper uppercase and lowercase on a StringTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0594.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
("([az])([az]*)",Pattern.CASE_INSENSITIVE).matcher(str);
while (m.find()) {
m.appendReplacement(sb, m.group(1).toUpperCase()

20.37 Apply proper uppercase and lowercase on a StringTag(s): String/Number

+ m.group(2).toLowerCase()) ;
}
str = m.appendTail(sb).toString();
return str;
}
public static void main(String [] args) {
System.out.println(StringUtils.upperCaseWordFirst(" #600howto"));
System.out.println(StringUtils.upperCaseWordFirst("ELVis preSLEY"));
System.out.println(StringUtils.upperCaseWordFirst("john o'connor &steeve mcmillan"));
/*
output :
#600HowTo
Elvis Presley
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...
*/
}
}

20.38 Encode/Decode to/from Base64Tag(s):


String/Number Networking
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0598.html
As seen in this HowTo, the sun.misc.BASE64Encoder/Decoder or creating your own Base64
handling are the more common way to deal with Base64 encoding/decoding.
Here some alternatives which are maybe easier (and safer) to use.

20.39 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];

20.38 Encode/Decode to/from Base64Tag(s): String/Number Networking

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
*/
}
}

20.40 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();
}
}
}

20.40 Using Apache Commons Codec

20.41 MiGBase64
MiGBase64 is a very fast Base64 Codec written in Java. http://migbase64.sourceforge.net/.

20.42 Justify a string with wordwrapTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0013.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);

20.41 MiGBase64

/*
output :

01234567890123456789

01234567890123456789
01234567890 0123
4565789

01234567890 0123

4565789

*/
}
}

20.43 Shorten a long pathTag(s): IO String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0661.html
It can be useful to have a short version of a long path only for display purpose.
I propose 2 versions to shorten a given path depending of your need.
The first version makes a path shorter according to a limit. If the limit is 4, the returned path will
contain 4 parts (directories) then ellipse and finally the filename.
ex :
C:\1\2\3\4\5\test.txt == C:\1\2\3\4\...\test.txt
\\server\p1\p2\p3\p4\p5\p6 == \\server\p1\p2\p3\p4\...\p6
http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html == http://p1/p2/p3/p4/.../pb.html

The second accepts a limit corresponding to the total length of the path. If the limit is 20, the path
beginning will be truncated then ellipse and finally the filename. The result is similar to the Win32
API PathCompactPathExA.
ex :
C:\1\2\3\4\5\test.txt
== C:\1\2\3\...test.txt
\\server\p1\p2\p3\p4\p5\p6
== \\server\p1\p2...p6
http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html == http://www...pb.html
public class FileUtils {
public
public
public
public
public
public

static
static
static
static
static
static

final
final
final
final
final
final

int DEFAULT_SHORTENER_THRESHOLD = 4;
String SHORTENER_BACKSLASH_REGEX = "\\\\";
String SHORTENER_SLASH_REGEX = "/";
String SHORTENER_BACKSLASH = "\\";
String SHORTENER_SLASH = "/";
String SHORTENER_ELLIPSE = "...";

public static String pathShortener(String path) {

20.43 Shorten a long pathTag(s): IO String/Number

return pathShortener(path, FileUtils.DEFAULT_SHORTENER_THRESHOLD);


}

/**
* Return shorter path based on the limited threshold
* ex. C:/1/2/test.txt return C:/1/.../test.txt if threshold is 1
* @param path
* @param threshold
* @return
*/
public static String pathShortener(String path, int threshold) {
String regex = SHORTENER_BACKSLASH_REGEX;
String sep = SHORTENER_BACKSLASH;
if (path.indexOf("/") > 0) {
regex = SHORTENER_SLASH_REGEX;
sep = SHORTENER_SLASH;
}
String pathtemp[] = path.split(regex);
// remove empty elements
int elem = 0;
{
String newtemp [] = new String [pathtemp.length];
int j = 0;
for (int i=0; i < pathtemp.length; i++) {
if (!pathtemp[i].equals("")) {
newtemp [j++] = pathtemp[i];
elem++;
}
}
pathtemp = newtemp;
}

if (elem > threshold) {


StringBuilder sb = new StringBuilder();
int index = 0;
// drive or protocol
int pos2dots = path.indexOf(":");
if (pos2dots > 0) {
// case c:\ c:/ etc.
sb.append(path.substring(0, pos2dots + 2));
index++;
// case http:// ftp:// etc.
if (path.indexOf(":/") > 0 && pathtemp[0].length() > 2) {
sb.append(SHORTENER_SLASH);
}
}
else {
boolean isUNC = path.substring(0,2).equals(SHORTENER_BACKSLASH_REGEX);
if (isUNC) {
sb.append(SHORTENER_BACKSLASH).append(SHORTENER_BACKSLASH);
}
}
for (; index <= threshold; index++) {
sb.append(pathtemp[index]).append(sep);
}

20.43 Shorten a long pathTag(s): IO String/Number

if (index == (elem 1)) {


sb.append(pathtemp[elem 1]);
}
else {
sb.append(SHORTENER_ELLIPSE)
.append(sep)
.append(pathtemp[elem 1]);
}
return sb.toString();
}
return path;
}
/**
* Compact a path into a given number of characters. Similar to the
* Win32 API PathCompactPathExA
* @param path
* @param limit
* @return
*/
public static String pathLengthShortener(String path, int limit) {
if (path.length() <= limit) {
return path;
}
char shortPathArray[] = new char [limit];
char pathArray [] = path.toCharArray();
char ellipseArray [] = SHORTENER_ELLIPSE.toCharArray();
int pathindex = pathArray.length 1 ;
int shortpathindex = limit 1;

// fill the array from the end


int i = 0;
for (; i < limit ; i++) {
if (pathArray[pathindex i] != '/' &pathArray[pathindex i] != '\\') {
shortPathArray[shortpathindex i] = pathArray[pathindex i] ;
}
else {
break;
}
}
// check how much space is left
int free = limit i;
if (free < SHORTENER_ELLIPSE.length()) {
// fill the beginning with ellipse
for(int j = 0; j < ellipseArray.length; j++) {
shortPathArray[j] = ellipseArray[j] ;
}
}
else {
// fill the beginning with path and leave room for the ellipse
int j = 0;
for(; j + ellipseArray.length < free; j++) {
shortPathArray[j] = pathArray[j] ;
}
// ... add the ellipse
for(int k = 0; j + k < free;k++) {
shortPathArray[j + k] = ellipseArray[k] ;

20.43 Shorten a long pathTag(s): IO String/Number

}
}
return new String(shortPathArray);
}

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

String t = "C:\\Documents and Settings\\All Users\\Application Data\\Apple Computer\\iTun


System.out.println(pathShortener(t));
System.out.println(pathShortener(t, 5));
System.out.println(pathShortener("C:\\temp"));
System.out.println(pathShortener("C:\\1\\2\\3\\4\\5\\test.txt"));
System.out.println(pathShortener("C:/1/2/test.txt"));
System.out.println(pathShortener("C:/1/2/3/4/5/test.txt"));
System.out.println(pathShortener("\\\\server\\p1\\p2\\p3\\p4\\p5\\p6"));
System.out.println(pathShortener("\\\\server\\p1\\p2\\p3"));
System.out
.println(pathShortener("http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html"));
System.out.println("");
System.out.println(pathLengthShortener(t,20));
System.out.println(pathLengthShortener("C:\\temp", 20));
System.out.println(pathLengthShortener("C:\\1\\2\\3\\4\\5\\test.txt", 20));
System.out.println(pathLengthShortener("C:/1/2/testfile.txt", 15));
System.out.println(pathLengthShortener("C:/1/2/3/4/5/test.txt", 15));
System.out.println(pathLengthShortener("\\\\server\\p1\\p2\\p3\\p4\\p5\\p6", 20));
System.out
.println(pathLengthShortener("http://www.rgagnon.com/p1/p2/p3/p4/p5/pb.html", 20));
/*

output :
C:\Documents and Settings\All Users\Application Data\Apple Computer\iTunes\...\SC Info.
C:\temp
C:\1\2\3\4\...\test.txt
C:/1/2/test.txt
C:/1/2/3/4/.../test.txt
\\server\p1\p2\p3\p4\...\p6
\\server\p1\p2\p3
http://www.rgagnon.com/p1/p2/p3/.../pb.html

C:\Doc...SC Info.txt
C:\temp
C:\1\2\3\...test.txt
...testfile.txt
C:/1...test.txt
\\server\p1\p2\...p6
http://www...pb.html
*/
}
}

See also this HowTo : Ellipse a String.

20.43 Shorten a long pathTag(s): IO String/Number

20.44 Ellipse a StringTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaellipseastring.html
You "ellipse" a String when you want to display a long String using a shorter representation
because of the available space.

public class StringUtils {


public static final String ELLIPSE = "...";
public static String toEllipsis(String input, int maxCharacters, int charactersAfterEllipse
if (input == null || input.length() < maxCharacters) {
return input;
}
return input.substring(0, maxCharacters charactersAfterEllipse)
+ ELLIPSE
+ input.substring(input.length() charactersAfterEllipse);
}

public static void main (String args[])


throws Exception {
String s = "Real's HowTo @ www.rgagnon.com";
System.out.println(s);
// max length is 15 with the last six characters.
System.out.println(StringUtils.toEllipsis(s, 15, 6));
// max length is 15 with no character at the end.
System.out.println(StringUtils.toEllipsis(s, 15, 0));
/*
* output :
*
Real's HowTo @ www.rgagnon.com
*
Real's Ho...on.com
*
Real's HowTo @ ...
*/
}
}

Unicode has a special character to show an ellipsis (to use one character instead of 3) :
public static final String ELLIPSE = "\u2026";

The HTML entity to represent an ellipsis is &hellip; :


See also this HowTo : Shorten a long path.

20.44 Ellipse a StringTag(s): String/Number

20.45 Display Ascii Banner Tag(s): String


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadisplayasciibanner.html
Draw a string to an Image and then examine the Image created and output " ", "#" or "*"
depending of the pixel value.
import
import
import
import
import
import
import

java.awt.Font;
java.awt.Graphics;
java.awt.Graphics2D;
java.awt.RenderingHints;
java.awt.image.BufferedImage;
java.io.File;
java.io.IOException;

import javax.imageio.ImageIO;
public class AsciiBanner {

public static void main (String ... args) throws IOException {


BufferedImage image = new BufferedImage(144, 32, BufferedImage.TYPE_INT_RGB); // need to
Graphics g = image.getGraphics();
g.setFont(new Font("Dialog", Font.PLAIN, 20));
Graphics2D graphics = (Graphics2D) g;
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.drawString("Real's HowTo", 6, 24); // the banner text may affect width and heig
ImageIO.write(image, "png", File.createTempFile("AsciiBanner.png", null));
for (int y = 0; y <32; y++) { // need to adjust for width and height
StringBuilder sb = new StringBuilder();
for (int x = 0; x <144; x++) // need to adjust for width and height
sb.append(image.getRGB(x, y) == 16777216 ? " " : image.getRGB(x, y) == 1 ? "#"
if (sb.toString().trim().isEmpty()) continue;
System.out.println(sb);
}
}
}

Output is :
######***
#########*
##
**#*
##
*#*
##
*#*
##
**#*
########**
######***
## ****
##
*#**
##
*#*
##
*##*
##
*#*
##
**#*
##
*#*

*******
*#####**
*#** **#*
*#*
*#*
*#######*
*#######*
*#*
*#*
*#** **#*
**#####**
*******

*******
*######*
*#****#*
#*
****##
**######
*#****##
*#* *##
*#* **##*
*#######*
*******#*

20.45 Display Ascii Banner Tag(s): String

##
##
##
##
##
##
##
##
##
##
##
##
##
##
##

##
##
**
**
**

******
*######*
*#****#*
*#*
*##****
***###**
****#*
*#*
*#****#*
*######*
******

##
##
##
##
##
##
##
##
##
##
##
##
###########
###########
##
##
##
##
##
##
##
##
##
##
##
##
##
##

******* *#*
**#####** ***
*#** **#* *#*
*#*
*#* *#*
*#*
*#* *#
*#
#* *#
*#*
*#* **
*#*
*#*
*
*#** **#*
*
**#####**
*******

20.46 Convert from type X to type YTag(s):


String/Number String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0004.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.toString(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 :

20.46 Convert from type X to type YTag(s): String/Number String/Number

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 Howto
hexadecimal (String) to integer :
int i = Integer.valueOf("B8DA3", 16).intValue();
or
int i = Integer.parseInt("B8DA3", 16);

char to String
String s = String.valueOf('c');

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, use the try/catch mechanism :
20.46 Convert from type X to type YTag(s): String/Number String/Number

try{
i = Integer.parseInt(aString);
}
catch(NumberFormatException e) {
...
}

20.47 Type conversion (JDK1.5)Tag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0464.html
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;
System.out.println(i);

// mix Integer and ints

// 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();

20.47 Type conversion (JDK1.5)Tag(s): String/Number

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.

20.48 Round a doubleTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0016.html
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();
}
}

JDK1.0.2
public class TestRound102 {
public static void main(String
double d = 3.1537;
// output is 3.2
System.out.println(d + " : "
// output is 3.15
System.out.println(d + " : "
// output is 3.154
System.out.println(d + " : "
d= 9.155;
// output is 9.2
System.out.println(d + " : "
// output is 9.16
System.out.println(d + " : "

args[]){

+ round(d, 1));
+ round(d, 2));
+ round(d, 3));

+ round(d, 1));
+ round(d, 2));

20.48 Round a doubleTag(s): String/Number

// output is 3.155
System.out.println(d +
d= 1234.156789;
// output is 1234.2
System.out.println(d +
// output is 1234.16
System.out.println(d +
// output is 1234.157
System.out.println(d +
// output is 1234.1568
System.out.println(d +
d= 1.5;
// output is 2
System.out.println(d +

" : " + round(d, 3));

" : " + round(d, 1));


" : " + round(d, 2));
" : " + round(d, 3));
" : " + round(d, 4));

" : " + round(d, 0));

}
// positive value only.
public static double round(double value, int decimalPlace)
{
double power_of_ten = 1;
// floating point arithmetic can be very tricky.
// that's why I introduce a "fudge factor"
double fudge_factor = 0.05;
while (decimalPlace > 0) {
power_of_ten *= 10.0d;
fudge_factor /= 10.0d;
}
return Math.round((value + fudge_factor)* power_of_ten) / power_of_ten;
}
}

20.49 Display numbers with commasTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0019.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");
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.*;

20.49 Display numbers with commasTag(s): String/Number

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));
}
}

JDK1.5
System.out.println() directly supports formatting so it's possible to give a known Locale (with the
right decimal separator) to bypass the current Locale.
System.out.printf(Locale.UK, "%6.2f%n", 123456.78) ;

20.50 Display numbers in scientific notationTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0020.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 {

20.50 Display numbers in scientific notationTag(s): String/Number

public static void main(String args[]) {


new TestScientific().doit();
}
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.2345E1
formatter = new DecimalFormat("000000E0");
System.out.println(formatter.format(d)); // 12345E6
}
}

20.51 Display numbers with leading zeroesTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0021.html
jdk1.5
Using String.format()
public class NumberUtils {
public static String formatLong(long n, int digits) {
/*
we create a format :
%% : % the first % is to escape the second %
0 : 0 zero character
%d :
how many '0' we want (specified by digits)
d : d the number to format

20.51 Display numbers with leading zeroesTag(s): String/Number

*/
String format = String.format("%%0%dd", digits);
return String.format(format, n);
}
public static void main(String[] args) throws Exception{
System.out.println(NumberUtils.formatLong(123456L, 10));
/* output : 0000123456
*/
}
}

jdk1.2
Using DecimalFormat.format()
import java.util.Arrays;
import java.text.DecimalFormat;
public class NumberUtils {
public static String formatLong(long n, int digits) {
char[] zeros = new char[digits];
Arrays.fill(zeros, '0');
DecimalFormat df = new DecimalFormat(String.valueOf(zeros));
return df.format(n);
}
public static void main(String[] args) throws Exception{
System.out.println(NumberUtils.formatLong(123456L, 10));
/* output : 0000123456
*/
}
}

prejdk1.1
public class DemoNumber {
public static void main(String args[]) {
long n = 123456;
String mask = "00000000000";
String ds = Long.toString(n); // double to string
String z = mask.substring(0 , mask.length() ds.length()) + ds;
System.out.println(z);
/* output : 0000123456
*/
}
}

20.51 Display numbers with leading zeroesTag(s): String/Number

20.52 Get a random numberTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0017.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);

20.53 Convert an UNSIGNED byte to a JAVA typeTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0026.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

20.52 Get a random numberTag(s): String/Number

128
255
*/
}
public static int unsignedByteToInt(byte b) {
return (int) b & 0xFF;
}
}

Therefore for an array of 4 bytes (buf[]), which represents an integer :


int i = 0;
int pos = 0;
i += unsignedByteToInt(buf[pos++])
i += unsignedByteToInt(buf[pos++])
i += unsignedByteToInt(buf[pos++])
I += unsignedByteToInt(buf[pos++])

<<
<<
<<
<<

24;
16;
8;
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 bigendian vs littleendian format. See
this Howto

20.54 Deal with bigendian and littleendian orderTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0007.html
Java virtual machine always used bigendian, Intel x86 used littleendian.
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));
}
}

20.54 Deal with bigendian and littleendian orderTag(s): String/Number

NOTE: to convert UNSIGNED byte to integer, look at this Howto

20.55 Pass an integer by referenceTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0035.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];
a[0] = 1;
add2(a);
// a[0] now = 3
...
void add2(int[] a) {
a[0] = a[0] + 2;
}

20.56 Pass floats as string literals to a methodTag(s):


String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0050.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);

20.55 Pass an integer by referenceTag(s): String/Number

20.57 Get random numbersTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0419.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
10
10
6
10
8.13013058393518
0.6631286078928067
4.382003543427801
7.2768144451559795
7.312852816962123
8.69257797289748
2.4967782036871657
4.451145854389913
1.82517092998838

20.58 Convert number into wordsTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0426.html
English
20.57 Get random numbersTag(s): String/Number

import java.text.DecimalFormat;
public class EnglishNumberToWords {
private static final String[] tensNames = {
"",
" ten",
" twenty",
" thirty",
" forty",
" fifty",
" sixty",
" seventy",
" eighty",
" ninety"
};
private static final String[] numNames = {
"",
" one",
" two",
" three",
" four",
" five",
" six",
" seven",
" eight",
" nine",
" ten",
" eleven",
" twelve",
" thirteen",
" fourteen",
" fifteen",
" sixteen",
" seventeen",
" eighteen",
" nineteen"
};
private static 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 static String convert(long number) {


// 0 to 999 999 999 999
if (number == 0) { return "zero"; }

20.57 Get random numbersTag(s): String/Number

String snumber = Long.toString(number);


// pad with "0"
String mask = "000000000000";
DecimalFormat df = new DecimalFormat(mask);
snumber = df.format(number);
// XXXnnnnnnnnn
int billions = Integer.parseInt(snumber.substring(0,3));
// nnnXXXnnnnnn
int millions = Integer.parseInt(snumber.substring(3,6));
// nnnnnnXXXnnn
int hundredThousands = Integer.parseInt(snumber.substring(6,9));
// nnnnnnnnnXXX
int thousands = Integer.parseInt(snumber.substring(9,12));
String tradBillions;
switch (billions) {
case 0:
tradBillions = "";
break;
case 1 :
tradBillions = convertLessThanOneThousand(billions)
+ " billion ";
break;
default :
tradBillions = convertLessThanOneThousand(billions)
+ " billion ";
}
String result = tradBillions;
String tradMillions;
switch (millions) {
case 0:
tradMillions = "";
break;
case 1 :
tradMillions = convertLessThanOneThousand(millions)
+ " million ";
break;
default :
tradMillions = convertLessThanOneThousand(millions)
+ " million ";
}
result = result + tradMillions;
String tradHundredThousands;
switch (hundredThousands) {
case 0:
tradHundredThousands = "";
break;
case 1 :
tradHundredThousands = "one thousand ";
break;
default :
tradHundredThousands = convertLessThanOneThousand(hundredThousands)
+ " thousand ";
}
result = result + tradHundredThousands;
String tradThousand;
tradThousand = convertLessThanOneThousand(thousands);
result = result + tradThousand;

20.57 Get random numbersTag(s): String/Number

// remove extra spaces!


return result.replaceAll("^\\s+", "").replaceAll("\\b\\s{2,}\\b", " ");
}
/**
* testing
* @param args
*/
public static void main(String[] args) {
System.out.println("*** " + EnglishNumberToWords.convert(0));
System.out.println("*** " + EnglishNumberToWords.convert(1));
System.out.println("*** " + EnglishNumberToWords.convert(16));
System.out.println("*** " + EnglishNumberToWords.convert(100));
System.out.println("*** " + EnglishNumberToWords.convert(118));
System.out.println("*** " + EnglishNumberToWords.convert(200));
System.out.println("*** " + EnglishNumberToWords.convert(219));
System.out.println("*** " + EnglishNumberToWords.convert(800));
System.out.println("*** " + EnglishNumberToWords.convert(801));
System.out.println("*** " + EnglishNumberToWords.convert(1316));
System.out.println("*** " + EnglishNumberToWords.convert(1000000));
System.out.println("*** " + EnglishNumberToWords.convert(2000000));
System.out.println("*** " + EnglishNumberToWords.convert(3000200));
System.out.println("*** " + EnglishNumberToWords.convert(700000));
System.out.println("*** " + EnglishNumberToWords.convert(9000000));
System.out.println("*** " + EnglishNumberToWords.convert(9001000));
System.out.println("*** " + EnglishNumberToWords.convert(123456789));
System.out.println("*** " + EnglishNumberToWords.convert(2147483647));
System.out.println("*** " + EnglishNumberToWords.convert(3000000010L));
/*
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
**
***
**
***
**/

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 millions
three millions two hundred
seven hundred thousand
nine millions
nine millions one thousand
one hundred twenty three millions four hundred
fifty six thousand seven hundred eighty nine
two billion one hundred forty seven millions
four hundred eighty three thousand six hundred forty seven
three billion ten

}
}

Franais
Quite different than the english version but french is a lot more difficult!
package com.rgagnon.howto;

20.57 Get random numbersTag(s): String/Number

import java.text.*;
class FrenchNumberToWords {
private static final String[] dizaineNames = {
"",
"",
"vingt",
"trente",
"quarante",
"cinquante",
"soixante",
"soixante",
"quatrevingt",
"quatrevingt"
};
private static final String[] uniteNames1 = {
"",
"un",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf",
"dix",
"onze",
"douze",
"treize",
"quatorze",
"quinze",
"seize",
"dixsept",
"dixhuit",
"dixneuf"
};
private static final String[] uniteNames2 = {
"",
"",
"deux",
"trois",
"quatre",
"cinq",
"six",
"sept",
"huit",
"neuf",
"dix"
};
private static String convertZeroToHundred(int number) {
int laDizaine = number / 10;
int lUnite = number % 10;
String resultat = "";
switch
case 1
case 7
case 9

(laDizaine) {
:
:
:

20.57 Get random numbersTag(s): String/Number

lUnite = lUnite + 10;


break;
default:
}
// sparateur "" "et" ""
String laLiaison = "";
if (laDizaine > 1) {
laLiaison = "";
}
// cas particuliers
switch (lUnite) {
case 0:
laLiaison = "";
break;
case 1 :
if (laDizaine == 8) {
laLiaison = "";
}
else {
laLiaison = " et ";
}
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 static 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;

20.57 Get random numbersTag(s): String/Number

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;
}
public static String convert(long number) {
// 0 999 999 999 999
if (number == 0) { return "zro"; }
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;

20.57 Get random numbersTag(s): String/Number

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;
String tradMille;
tradMille = convertLessThanOneThousand(lesMille);
resultat = resultat + tradMille;
return resultat;
}
public static void main(String[] args) {
System.out.println("*** " + FrenchNumberToWords.convert(0));
System.out.println("*** " + FrenchNumberToWords.convert(9));
System.out.println("*** " + FrenchNumberToWords.convert(19));
System.out.println("*** " + FrenchNumberToWords.convert(21));
System.out.println("*** " + FrenchNumberToWords.convert(28));
System.out.println("*** " + FrenchNumberToWords.convert(71));
System.out.println("*** " + FrenchNumberToWords.convert(72));
System.out.println("*** " + FrenchNumberToWords.convert(80));
System.out.println("*** " + FrenchNumberToWords.convert(81));
System.out.println("*** " + FrenchNumberToWords.convert(89));
System.out.println("*** " + FrenchNumberToWords.convert(90));
System.out.println("*** " + FrenchNumberToWords.convert(91));
System.out.println("*** " + FrenchNumberToWords.convert(97));
System.out.println("*** " + FrenchNumberToWords.convert(100));
System.out.println("*** " + FrenchNumberToWords.convert(101));
System.out.println("*** " + FrenchNumberToWords.convert(110));
System.out.println("*** " + FrenchNumberToWords.convert(120));
System.out.println("*** " + FrenchNumberToWords.convert(200));
System.out.println("*** " + FrenchNumberToWords.convert(201));
System.out.println("*** " + FrenchNumberToWords.convert(232));
System.out.println("*** " + FrenchNumberToWords.convert(999));
System.out.println("*** " + FrenchNumberToWords.convert(1000));
System.out.println("*** " + FrenchNumberToWords.convert(1001));
System.out.println("*** " + FrenchNumberToWords.convert(10000));
System.out.println("*** " + FrenchNumberToWords.convert(10001));
System.out.println("*** " + FrenchNumberToWords.convert(100000));
System.out.println("*** " + FrenchNumberToWords.convert(2000000));
System.out.println("*** " + FrenchNumberToWords.convert(3000000000L));
System.out.println("*** " + FrenchNumberToWords.convert(2147483647));
/*
*** OUTPUT
*** zro
*** neuf
*** dixneuf
*** vingt et un

20.57 Get random numbersTag(s): String/Number

***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
***
**
*/

vingthuit
soixante et onze
soixantedouze
quatrevingt
quatrevingtun
quatrevingtneuf
quatrevingtdix
quatrevingtonze
quatrevingtdixsept
cent
cent un
cent dix
cent vingt
deux cents
deux cent un
deux cent trentedeux
neuf cent quatrevingtdixneuf
mille
mille un
dix mille
dix mille un
cent mille
deux millions
trois milliards
deux milliards cent quarantesept millions
quatre cent quatrevingttrois mille six cent quarantesept

}
}

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 = "$ " + EnglishNumberToWords.convert( dollars ) + " and "
+ EnglishNumberToWords.convert( cent ) + " cents" ;

Another way to use a builtin 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 SEVENTYTHREE


SQL>

'JSP' means :
J : the Julian format.
SP : spells the word for the number passed to to_date

20.57 Get random numbersTag(s): String/Number

20.59 Arithmetic with doubleTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0474.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 floatingpoint number representation
is not well suited for that kind of operation.
The easiest way to solve this limitation is to the BigDecimal class :
import java.math.BigDecimal;
...
System.out.println
(BigDecimal.valueOf(1.33).subtract(BigDecimal.valueOf(1.3)));

20.60 Detect even/odd numberTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0488.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) {

20.59 Arithmetic with doubleTag(s): String/Number

// odd
}

20.61 Convert bytes to megabytesTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0540.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());
System.out.println(bytesToMeg(f.length()) + " Mb");
}
private static final long

MEGABYTE = 1024L * 1024L;

public static long bytesToMeg(long bytes) {


return bytes / MEGABYTE ;
}
}

20.62 Validate a numberTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0599.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) {

20.61 Convert bytes to megabytesTag(s): String/Number

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 ? "
System.out.println("42.1 valid ? "
System.out.println("42.1 valid ? "
System.out.println("42.1a valid ? "

+
+
+
+

NumberUtils.isNumeric("42"));
NumberUtils.isNumeric("42.1"));
NumberUtils.isNumeric("42.1"));
NumberUtils.isNumeric("42.1a"));

System.out.println("42.10 valid ? "


System.out.println("42.101 valid ? "
System.out.println("42,10 valid ? "
System.out.println("42 valid ? "

+
+
+
+

NumberUtils.isNumberWith2Decimals("42.10"));
NumberUtils.isNumberWith2Decimals("42.101"));
NumberUtils.isNumberWith2Decimals("42,10"));
NumberUtils.isNumberWith2Decimals("42"));

/*
* output
* 42.1 valid ?
* 42
valid ?
*
* 42.1
valid
* 42.1 valid
* 42.1a valid
*
* 42.10 valid
* 42.101 valid
* 42,10 valid
* 42
valid
*/

false
true
? true
? true
? false
?
?
?
?

true
false
false
false

}
}

20.63 Get a unique identifierTag(s):


String/Number Thread Varia
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0518.html

20.64 Using java.rmi.dgc.VMID


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 constructed by pairing a UID instance with a unique host identifier, such as an
IP address.
20.63 Get a unique identifierTag(s): String/Number Thread Varia

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

20.65 Using java.util.UUID


In 1.5, you have java.util.UUID which is less esotoric.
public class TestUUID {
public static void main(String arg[]) {
System.out.println(java.util.UUID.randomUUID());
// output : dedc3f576ce14504a92f640d8d9d23c9
}
}

This is probably the preferred method.


MiniFAQ on the subject : http://www.asciiarmor.com/post/33736615/javautiluuidminifaq

20.66 Using Apache commons


If you need compatibility with 1.4 then the org.apache.commons.id.uuid is an option.

20.67 Using java.util.concurrent.AtomicLong


A simple numerical id, start at zero and increment by one.
import java.util.concurrent.AtomicLong;
public class Descriptor {
private static final AtomicLong nextId = new AtomicLong();
private static long nextId() {
return nextId.getAndIncrement();

20.65 Using java.util.UUID

}
}

See also this HowTo for unique numerical id based on the system time.

20.68 Validate/Convert a number using the current


Locale()Tag(s): Internationalization String/Number
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0139.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().
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class NumberUtils {
public static double getDoubleValue(String value) throws ParseException {
// use the default locale
return NumberUtils.getDoubleValue(Locale.getDefault(), value);
}
public static double getDoubleValue(Locale loc, String value)
throws ParseException
{
// use the default locale
return NumberFormat.getInstance(loc).parse(value).doubleValue();
}
public static String convertStringAsStringNumberUnLocalized(String value)
throws ParseException
{
// use the default locale
return convertStringAsStringNumberUnLocalized(Locale.getDefault(), value);
}
public static String convertStringAsStringNumberUnLocalized
(Locale loc, String value)
throws ParseException
{
double d = NumberUtils.getDoubleValue(loc, value);
return NumberFormat.getInstance(new Locale("us")).format(d);
}

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


System.out.println(Locale.getDefault());

20.68 Validate/Convert a number using the current Locale()Tag(s): Internationalization String/Number

System.out.println(NumberUtils.getDoubleValue("42,24"));
System.out.println(NumberUtils.getDoubleValue("42.24"));
System.out.println(NumberUtils.convertStringAsStringNumberUnLocalized
(new Locale("fr"), "42,24"));
/*
* output
* fr_CA
* 42.24
* 42.0
* 42.24
*/
}
}

20.69 Convert a fraction to a DoubleTag(s): String/Number


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaconvertfractiontodouble.html
import java.math.BigDecimal;
import java.math.MathContext;
import java.text.ParseException;
public class NumberUtils {
public static Double fractionToDouble(String fraction)
throws ParseException {
Double d = null;
if (fraction != null) {
if (fraction.contains("/")) {
String[] numbers = fraction.split("/");
if (numbers.length == 2) {
BigDecimal d1 = BigDecimal.valueOf(Double.valueOf(numbers[0]));
BigDecimal d2 = BigDecimal.valueOf(Double.valueOf(numbers[1]));
BigDecimal response = d1.divide(d2, MathContext.DECIMAL128);
d = response.doubleValue();
}
}
else {
d = Double.valueOf(fraction);
}
}
if (d == null) {
throw new ParseException(fraction, 0);
}
return d;
}
public static void main(String[] args) throws Exception{
System.out.println(NumberUtils.fractionToDouble("1/2"));
System.out.println(NumberUtils.fractionToDouble("2/3"));
System.out.println(NumberUtils.fractionToDouble("4/6"));

20.69 Convert a fraction to a DoubleTag(s): String/Number

System.out.println(NumberUtils.fractionToDouble("4/5"));
System.out.println(NumberUtils.fractionToDouble("3/9"));
/*
* 0.5
* 0.6666666666666666
* 0.6666666666666666
* 0.8
* 0.3333333333333333
*/
}
}

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

20.69 Convert a fraction to a DoubleTag(s): String/Number

21 Open Source
21.1 javaos

21.2 Call Windows API (Open source solution)Tag(s): JNI Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0497.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/

21.3 Call COM objectTag(s): Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0498.html

21.4 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) {

21 Open Source

IFileSystem3 fs = ClassFactory.createFileSystemObject();
for( String file : args )
System.out.println(fs.getFileVersion(file));
}
}

https://com4j.dev.java.net/

21.5 jinterop
Implementation of DCOM wire protocol (MSRPC) to enable development of Pure BiDirectional,
NonNative Java applications which can interoperate with any COM component. The
implementation is itself purely in Java and does not use JNI to provide COM access.
http://sourceforge.net/projects/jinterop

21.6 jxchange
Pure java implementation of the entire Collaboration Data Objects (CDO 1.21) library for accessing
Microsoft Exchange Server in a platform independent manner.
http://sourceforge.net/projects/jxchange/
See also this HowTo for an alternative package to access a COM package from Java.

21.7 Run JAVA as a Windows serviceTag(s): Environment Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0151.html
A solution adapted to Java, is YAJSW( Yet Another Java Service Wrapper ) (
http://yajsw.sourceforge.net/ ) (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 Xtendedswitch) 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.
21.5 jinterop

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.

21.8 Create entityrelation diagramTag(s): Open Source Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0584.html
Linguine Maps is an opensource Java library that conducts programmatic visualization of various
text files, generating from them easytounderstand entityrelation 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.

21.9 Java Remote desktop toolTag(s): Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0583.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 JavaRDP131.1.jar some.machine.local

For more option, from a command shell


21.8 Create entityrelation diagramTag(s): Open Source Open Source

javaw jar JavaRDP141.1.jar

There is a port for OpenVMS called JavaRDP for OpenVMS at


http://vmsfree.free.fr/freen/index.php?id=38

21.10 Create entityrelation diagramTag(s): Open Source Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0584.html
Linguine Maps is an opensource Java library that conducts programmatic visualization of various
text files, generating from them easytounderstand entityrelation 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.

21.11 Launch a java program as a Windows EXE fileTag(s):


Open Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0588.html

21.12 WinRun4J
http://winrun4j.sourceforge.net/
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.
Builtin icon replacer for custom icon.
Windows NT Service wrapper.
Windows EventLog API
21.10 Create entityrelation diagramTag(s): Open Source Open Source

and more ...


The launcher is designed to be used as follows:
1. Rename WinRun4J.exe to [YourApp].exe
2. Create [YourApp].ini (in the same directory)
3. Customize [YourApp].ini
4. Create [YourApp].ico (in the same directory)
5. Run [YourApp].exe WinRun4J:SetIcon (this will inject your icon into the executable).
6. Launch [YourApp].exe

21.13 JSmooth
http://jsmooth.sourceforge.net/
JSmooth is a Java Executable Wrapper. It creates native Windows launchers (standard .exe) for
your java applications.
When no VM is available, the wrapper can automatically download and install a suitable JVM, or
simply display a message or redirect the user to a web site.
A Swingbased project editor allows you to easily configure the executable binary for your software.
All the parameters are configured with a GUI, just click and compile the project.

21.14 Launch4J
http://launch4j.sourceforge.net/
Launch4j is a crossplatform tool for wrapping Java applications distributed as jars in lightweight
Windows native executables. The executable can be configured to search for a certain JRE version
or use a bundled one.
Supports GUI and console apps.
Supports Vista manifests and XP visual style manifests.
JVM options: set system properties, tweak the garbage collection...
Runtime JVM options from an .l4j.ini file.
Custom version information shown by Windows Explorer.
GUI, command line interface, Ant task and Maven plugin.

21.15 Handle CSV fileTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0591.html

21.13 JSmooth

21.16 com.Ostermiller.util CSV Utils


CSVPrinter/CSVParser/ExcelCSVPrinter/ExcelCSVParser
http://ostermiller.org/utils/CSV.html

21.17 opencsv
A simple csv parser library for Java
http://opencsv.sourceforge.net/

21.18 ServingXML
Framework for flat/XML data transformations. Supported transformations : flatXML,
XMLflat, flatflat, and XMLXML
http://servingxml.sourceforge.net/

21.19 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/

21.20 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

21.21 CSVFile
A simple set of Java classes used to handle CSV
http://sourceforge.net/projects/csvfile

21.22 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/

21.23 CSVJDBC
CsvJdbc is a simple readonly JDBC driver that uses Comma Separated Value (CSV) files
as database tables.
http://csvjdbc.sourceforge.net/

21.24 FFP
FFP Flat file parsing library, is used to parse text files where lines can be interpreted
21.16 com.Ostermiller.util CSV Utils

according to positional patterns. The library can handle both multiline formats and files
containing lines have different known formats ("mixed format" files).
http://jffp.sourceforge.net/

21.25 Handle Excel filesTag(s): IO JDBC Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0516.html
There are many solutions to read or write Excel spreadsheets from Java. This HowTo is only
about OpenSource (and free) solutions.

21.26 JDBCODBC 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 JDBCODBC
bridge is used to access the Excel DSN.
See this HowTo for an example.

21.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
import
import
import

javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import
import
import
import

jxl.Workbook;
jxl.write.Label;
jxl.write.WritableSheet;
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.msexcel");

21.25 Handle Excel filesTag(s): IO JDBC Open Source

response.setHeader
("ContentDisposition", "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/

21.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.
Latest POI version seems to support the .XLSX format.
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/

21.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
21.28 POI

code to invoke jXLS engine passing XLS template and the exported data as parameters.
Example :
The XLS Template
Employees
Name
${employee.name}

Age
Payment
Bonus
${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
Derek
35
Else
28

Payment Bonus
3000
30,00%
1500
15,00%
4500

Reading values from an XLS with jXLS is very simple. Suppose we have a worksheet with
policy numbers in the first column. We read and process them one by one.
import java.io.File;
import jxl.Cell;
import jxl.Sheet;
import jxl.Workbook;

public void doit() throws Exception {


Workbook workbook = Workbook.getWorkbook(new File("policies.xls"));
Sheet sheet = workbook.getSheet(0);
Cell policies[] = sheet.getColumn(0);
for (Cell policy : policies) {
String nopolicy = policy.getContents();
// do something : process(nopolicy);
}
}

See http://jxls.sourceforge.net/

21.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
21.30 xlSQL

"zeroadmin" mySQL database. The documentation is minimal at this time.


See http://xlsql.sourceforge.net/

21.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
import
import
import

jp.ne.so_net.ga2.no_ji.jcom.excel8.*;
jp.ne.so_net.ga2.no_ji.jcom.*;
java.io.File;
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" );

21.31 JCOM

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.

21.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
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_"

21.32 OpenXLS Java Spreadsheet SDK

+ 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);
}
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());

21.32 OpenXLS Java Spreadsheet SDK

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.

21.33 Browse a Queue (JMS/MQ)Tag(s): Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0472.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.

21.34 Convert a .class to .java file (decompiler)Tag(s): Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0330.html

21.35 Jad
Jad, the fast JAva Decompiler, is a program that reads one or more Java class files and
converts them into Java source files which can be compiled again.
Jad is a 100% pure C++ program and it generally works several times faster than
decompilers written in Java. Jad doesn't use the Java runtime for its functioning, therefore
no special setup is required (like changes to the CLASSPATH variable).
Jad is not open source but it is free to use.

21.33 Browse a Queue (JMS/MQ)Tag(s): Open Source

Make sure to download the GUI interface, FrontEnd Plus .


On Windows, a file association with the .class extension is made so if you click on a class
file then the decompiled is shown in FrontEnd Plus right away.
http://www.kpdus.com/jad.html
JAD is good but outdated, the new class format introduced with JDK1.5 is not well
supported.

21.36 JadClipse
JadClipse is a plugin that seamlessly integrates Jad (the fast Java decompiler) with
Eclipse.
Normally, when opening a class file the Class File Viewer will show a brief API outline of the
class. If you install this plugin, however, the Class File Viewer will be replaced with the
JadClipse Class File Viewer that shows the decompiled source of the class.
http://jadclipse.sourceforge.net/wiki/index.php/Main_Page

21.37 JD Java decompiler


The Java Decompiler project aims to develop tools in order to decompile and analyze Java 5
byte code and the later versions.
JD is Open Source and free to use.
Also available is JDGUI, a standalone graphical utility that displays Java source codes of
.class files, and JDEclipse, a plugin for the Eclipse platform.
http://java.decompiler.free.fr/

21.38 JarPlug
By default, the support for viewing and editing JAR file in Eclipse is very limited.
With JarPlug, it is possible delete or update items stored in a JAR.
http://jarplug.sourceforge.net/

21.36 JadClipse

21.39 Deploy an application as only 1 jarTag(s): Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0609.html

21.40 OneJar
Any nontrivial Java application is going to rely on any number of supporting Jar files. So
your deployment will include your application jar plus the supporting jars (ex. Apache
Commons, Log4j,...).
Unfortunately it's not possible to include a jar into another jar because the Java classloader
does not know how to load classes from a Jar inside a Jar.
OneJar is special classloader able to do this. The OneJAR JarClassLoader looks for a
main program inside a main directory in the Jar file, and looks for supporting Jar files inside
a lib directory.
The kit includes a special ANT task to simplify the process of preparing your application to
be distributed as a OneJar application.
http://onejar.sourceforge.net/

21.41 Fat Jar


The Fat Jar Eclipse PlugIn is a DeploymentTool which deploys an Eclipse javaproject
into one executable jar.
http://fjep.sourceforge.net/

21.42 Read an Outlook MSG fileTag(s): Networking Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0613.html
When Outlook Express saves an email, it uses the EML format which is a good thing
because the format is a standard.
You read them with Javamail easily, see this HowTo.

21.39 Deploy an application as only 1 jarTag(s): Open Source

But Outlook (not the Express but the one with Office) can only save an email with the MSG
format which is Microsoft specific.

21.43 Apache POI HSMF


http://poi.apache.org/hsmf/
HSMF is the POI Project's pure Java implementation of the Outlook MSG format.
This example takes a MSG file and extracts the attachment(s).
POI 3.6
import
import
import
import
import
import
import
import

java.io.ByteArrayInputStream;
java.io.File;
java.io.FileOutputStream;
java.io.IOException;
java.io.OutputStream;
java.io.PrintWriter;
java.util.Iterator;
java.util.Map;

import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
// You need poiscratchpad3.6

and poi3.6 ( http://poi.apache.org/ )

public class DetectMSGAttachment {


public static void main (String ... args) throws IOException {
String msgfile = "c:/temp/messagewithattachment.msg";
MAPIMessage msg = new MAPIMessage(msgfile);
Map attachmentMap = msg.getAttachmentFiles();
if(attachmentMap.size() > 0) {
for (Iterator ii = attachmentMap.entrySet().iterator(); ii.hasNext();) {
Map.Entry entry = (Map.Entry)ii.next();
String attachmentfilename = entry.getKey().toString();
System.out.println(attachmentfilename);
// extract attachment
ByteArrayInputStream fileIn = (ByteArrayInputStream)entry.getValue();
File f = new File("c:/temp", attachmentfilename); // output
OutputStream fileOut = null;
try {
fileOut = new FileOutputStream(f);
byte[] buffer = new byte[2048];
int bNum = fileIn.read(buffer);
while(bNum > 0) {
fileOut.write(buffer);
bNum = fileIn.read(buffer);
}
}
finally {
try {
if(fileIn != null) {
fileIn.close();
}
}
finally {
if(fileOut != null) {

21.43 Apache POI HSMF

fileOut.close();
}
}
}
}
}
else {
System.out.println("No attachment");
}
}
}

POI 3.7
import
import
import
import
import
import
import
import

java.io.ByteArrayInputStream;
java.io.File;
java.io.FileOutputStream;
java.io.IOException;
java.io.OutputStream;
java.io.PrintWriter;
java.util.Iterator;
java.util.Map;

import
import
import
import
import

org.apache.poi.hdgf.chunks.Chunk;
org.apache.poi.hsmf.MAPIMessage;
org.apache.poi.hsmf.datatypes.AttachmentChunks;
org.apache.poi.hsmf.datatypes.Chunks;
org.apache.poi.hsmf.exceptions.ChunkNotFoundException;

// You need poiscratchpad3.7 and poi3.7 ( http://poi.apache.org/ )


public class DetectMSGAttachment {
public static void main (String ... args) throws IOException {
String msgfile = "c:/temp/messagewithattachment.msg";
MAPIMessage msg = new MAPIMessage(msgfile);
AttachmentChunks attachments[] = msg.getAttachmentFiles();
if(attachments.length > 0) {
for (AttachmentChunks a : attachments) {
System.out.println(a.attachLongFileName);
// extract attachment
ByteArrayInputStream fileIn = new ByteArrayInputStream(a.attachData.getVa
File f = new File("c:/temp", a.attachLongFileName.toString()); // output
OutputStream fileOut = null;
try {
fileOut = new FileOutputStream(f);
byte[] buffer = new byte[2048];
int bNum = fileIn.read(buffer);
while(bNum > 0) {
fileOut.write(buffer);
bNum = fileIn.read(buffer);
}
}
finally {
try {
if(fileIn != null) {
fileIn.close();
}
}
finally {
if(fileOut != null) {
fileOut.close();
}
}
}

21.43 Apache POI HSMF

}
}
else {
System.out.println("No attachment");
}
}
}

21.44 msgparser
http://auxilii.com/msgparser/
msgparser is a small open source Java library that parses Outlook .msg files and provides
their content using Java objects. msgparser uses the Apache POI POIFS library to parse
the message files which use the OLE 2 Compound Document format.
import java.util.List;
import com.auxilii.msgparser.*;
import com.auxilii.msgparser.attachment.*;
public class SimpleMsgParser {
public static void main(String[] args) throws Exception{
MsgParser msgp = new MsgParser();
Message msg = msgp.parseMsg("c:/temp/test2.msg");
String
String
String
String

fromEmail = msg.getFromEmail();
fromName = msg.getFromName();
subject = msg.getSubject();
body = msg.getBodyText();

System.out.println("From :" + fromName + " <" + fromEmail + ">");


System.out.println("Subject :" + subject);
System.out.println("");
System.out.println(body);
System.out.println("");
List atts = msg.getAttachments();
for (Attachment att : atts) {
if (att instanceof FileAttachment) {
FileAttachment file = (FileAttachment) att;
System.out.println("Attachment : " + file.getFilename());
// you get the actual attachment with
// byte date[] = file.getData();
}
}
}
}

21.45 jmbox
https://jmbox.dev.java.net/
The jmbox project (read jambox) is a Local Store Provider for JavaMail, enabling developers
to use JavaMail api to manage the mail stored in local repositories like Outlook Express,
Mozilla, Netscape etc.

21.44 msgparser

At the moment are supported navigation and reading from Outlook Express 5/6 mail (dbx
format).

21.46 File/directory polling to detect changeTag(s): IO Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0617.html

21.47 jpoller (directory poller)


http://jpoller.sourceforge.net/
A general purpose Java component to enable polling on directories and aysnchronously
notify client code of incoming files. It's instrumented via JMX and controllable (also) via a
JMX agent, like JBoss' JMX console.

21.48 JNotify
http://jnotify.sourceforge.net/
JNotify is a java library that allow java application to listen to file system events. JNotify
works on both Windows (Windows 2000, XP, Vista) and Linux with INotify support (Kernel
2.6.14 and above).

21.49 Java Native Access (JNA)


https://jna.dev.java.net/
The goal of the JNA project is to let you access native code from Java while avoiding C and
the Java Native Interface.
One example provides notification of file system changes using the mechanism provided by
the OS. FileMonitor.java
Javaworld article about JNA

21.50 Call native methods in a DLL from Java (NativeCall)

http://johannburkard.de/blog/programming/java/CallnativemethodsinaDLLfromJavawithout
In this blog entry, the package NativeCall is used to call the Windows API to get notification
about modification in given folder.

21.46 File/directory polling to detect changeTag(s): IO Open Source

21.51 Java 7
Java 7 provides a mechanism to get notificaton on file change without polling (JSR 203).
http://blogs.sun.com/thejavatutorials/entry/watching_a_directory_for_changes

21.52 The simple (and naive!) approach


Detect file modification
Using Threads and file lookup at regular interval.

21.53 Clear the console and control attributesTag(s):


IO Open Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0047.html
There is no builtin way to really control characterbased application in Java.
To clear the screen, you can use many System.out.println();, that's about it!
for (int i=0; i<25; i++)
System.out.println();

... Or use some JNI functions, see this HowTo.


While it is possible to use the DOS ANSI.SYS driver with Windows 9x and make old JVM
use it ... it won't work with modern Windows installations. Windows NT (or better) CMD.EXE
does not support ANSI escape sequences at all.
Fortunately many Open Source solutions are coming to the rescue and Jansi and JCurses
are two of them.

21.54 Jansi
Jansi is a small java library that allows you to use ANSI escape sequences to format your
console output which works even on Windows.
import org.fusesource.jansi.AnsiConsole;
public class Test {
public static final
public static final
public static final
public static final

21.51 Java 7

String
String
String
String

ANSI_CLS = "\u001b[2J";
ANSI_HOME = "\u001b[H";
ANSI_BOLD = "\u001b[1m";
ANSI_AT55 = "\u001b[10;10H";

public static final String ANSI_REVERSEON = "\u001b[7m";


public static final String ANSI_NORMAL = "\u001b[0m";
public static final String ANSI_WHITEONBLUE = "\u001b[37;44m";
public static void main(String args[]){
AnsiConsole.systemInstall();
AnsiConsole.out.println(ANSI_CLS);
AnsiConsole.out.println
(ANSI_AT55 + ANSI_REVERSEON + "Hello world" + ANSI_NORMAL);
AnsiConsole.out.println
(ANSI_HOME + ANSI_WHITEONBLUE + "Hello world" + ANSI_NORMAL);
AnsiConsole.out.print
(ANSI_BOLD + "Press a key..." + ANSI_NORMAL);
try {System.in.read();}catch(Exception e){}
AnsiConsole.out.println(ANSI_CLS);
AnsiConsole.systemInstall();
}
}
NOTE: Check this "old" text file to have an overview of ANSI Escape Sequences.

The above example shows that it's possible to use ANSI codes directly but Jansi provides a
neat mechanism to help building the required ANSI sequence.

import static org.fusesource.jansi.Ansi.*;


import static org.fusesource.jansi.Ansi.Color.*;
...
System.out.println( ansi().eraseScreen().fg(RED).a("Hello").fg.(GREEN).a(" World").rese

Jansi works on Linux32/64, Windows 32/64 and OS/X.

21.55 JCurses
The Java Curses Library (JCurses) is a library for developing text terminal based
applications using Java programming language. It is implemented as a Windowing toolkit
similar to AWT, but built upon the UNIX "curses" windowing system.
JCurses works on Unix and Windows (32 bit only, on a 64bit OS you need to use JCurses
with a 32bit JVM).
This example will display a characterbased window with a label, a textfield and a button
(don't click with you mouse, use the keyboard!).
import
import
import
import

jcurses.system.*;
jcurses.widgets.*;
jcurses.util.*;
jcurses.event.*;

public class Test2 extends Window implements ItemListener, ActionListener,


ValueChangedListener, WindowListener, WidgetsConstants {
static Test2 window = null;
static TextField textfield = null;
static Button button = null;
public Test2(int width, int height) {
super(width, height, true, "JCurses Test");
}

21.55 JCurses

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


window = new Test2(30, 20);
window.init();
}
public void init() {
DefaultLayoutManager mgr = new DefaultLayoutManager();
mgr.bindToContainer(window.getRootPanel());
mgr.addWidget(
new Label("Hello World!",
new CharColor(CharColor.WHITE, CharColor.GREEN)),
0, 0, 20, 10,
WidgetsConstants.ALIGNMENT_CENTER,
WidgetsConstants.ALIGNMENT_CENTER);
textfield = new TextField(10);
mgr.addWidget(textfield, 0, 0, 20, 20,
WidgetsConstants.ALIGNMENT_CENTER,
WidgetsConstants.ALIGNMENT_CENTER);
button = new Button("Quit");
mgr.addWidget(button, 0, 0, 20, 30,
WidgetsConstants.ALIGNMENT_CENTER,
WidgetsConstants.ALIGNMENT_CENTER);
button.setShortCut('q');
button.addListener(this);
window.addListener((WindowListener) this);
window.show();
}
public void actionPerformed(ActionEvent event) {
Widget w = event.getSource();
if (w == button) {
new Message("HowTo", "You are about to quit", "OK").show();
window.close();
}
}
public void stateChanged(ItemEvent e) {

public void valueChanged(ValueChangedEvent e) {

public void windowChanged(WindowEvent event) {


if (event.getType() == WindowEvent.CLOSING) {
event.getSourceWindow().close();
// Toolkit.clearScreen(new CharColor(CharColor.WHITE, CharColor.BLACK));
}
}
}

21.56 Disable Checkstyle from code Tag(s): OpenSource


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javadisablecheckstylefromcode.html
21.56 Disable Checkstyle from code Tag(s): OpenSource

Checkstyle is a useful to enforce coding style but ...


sometime it may be to strict. Hopefully, there is a way to disable Checkstyle checking for a
certain area to ebable to reach to the glory of having a Checkstyle == 0 ;)

<module name="Checker">
<property name="severity" value="warning"/>
<property name="localeLanguage" value="fr"/>
<module name="SuppressionCommentFilter"/>
<module name="TreeWalker">
<module name="FileContentsHolder"/>
...
<module name="HideUtilityClassConstructor"/>
</module>
</module>

Then to disable Checkstyle, you use //CHECKSTYLE:OFF and //CHECKSTYLE:ON (default


values) in your code.
In this example, we want the disable it because we don't want to get the warning for the
missing Javadoc tags for the getter/setter methods.

//CHECKSTYLE:OFF
public void setDriverFileName(String driverFileName) { this.driverFileName = driverFileNa
public String getDriverFileName () { return this.driverFileName;}
//CHECKSTYLE:ON

21.57 Create or process a PDF fileTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0523.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");
Document document = new Document();
try {

21.57 Create or process a PDF fileTag(s): IO Open Source

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
import
import
import
import
import
import

com.lowagie.text.Element;
com.lowagie.text.Image;
com.lowagie.text.PageSize;
com.lowagie.text.pdf.BaseFont;
com.lowagie.text.pdf.PdfContentByte;
com.lowagie.text.pdf.PdfReader;
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
(Element.ALIGN_LEFT, "DUPLICATE", 230, 430, 45);
over.endText();

21.57 Create or process a PDF fileTag(s): IO Open Source

}
// 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();
}
}
}

See also this HowTo

21.58 Create a PDFTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0618.html

21.59 iText
http://www.lowagie.com/iText/
iText is a very simple to use package to create and manipulate PDF file.
For the simple need, only 1 jar is required (ex. itext2.1.3.jar, download at
http://www.lowagie.com/iText/download.html)
In this example, you pass on the command line a filename (plain text file args[0]) to
convert to a PDF file (args[1]).
import java.io.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;
public class TextFileToPDF {
/*
ex. java TextFileToPDF

c:\temp\text.txt

21.58 Create a PDFTag(s): IO Open Source

c:\temp\text.pdf

*/
public static void main (String [] args){
BufferedReader input = null;
Document output = null;
System.out.println("Convert text file to pdf");
System.out.println("input : " + args[0]);
System.out.println("output : " + args[1]);
try {
// text file to convert to pdf as args[0]
input =
new BufferedReader (new FileReader(args[0]));
// letter 8.5x11
//
see com.lowagie.text.PageSize for a complete list of pagesize constants.
output = new Document(PageSize.LETTER, 40, 40, 40, 40);
// pdf file as args[1]
PdfWriter.getInstance(output, new FileOutputStream (args[1]));
output.open();
output.addAuthor("RealHowTo");
output.addSubject(args[0]);
output.addTitle(args[0]);
String line = "";
while(null != (line = input.readLine())) {
System.out.println(line);
Paragraph p = new Paragraph(line);
p.setAlignment(Element.ALIGN_JUSTIFIED);
output.add(p);
}
System.out.println("Done.");
output.close();
input.close();
System.exit(0);
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}

See also this HowTo


A good introduction to iText : http://www.informit.com/articles/printerfriendly.aspx?p=420686

21.60 Split a PDF file (using iText)Tag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0647.html
This HowTo is based on the iText package. You need a recent version (ex. 2.*)

21.60 Split a PDF file (using iText)Tag(s): IO Open Source

This a command line utility. You specify the pdf file to be split. Each page is extracted to its
own pdf file.
/*
* java SplitPDFFile file.pdf
*
*
gives
file001.pdf ... filennn.pdf
*
* itext2.1.5.jar
*/
import java.io.FileOutputStream;
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.pdf.PdfCopy;
com.lowagie.text.pdf.PdfImportedPage;
com.lowagie.text.pdf.PdfReader;

public class SplitPDFFile {


/**
* @param args
*/
public static void main(String[] args) {
try {
String inFile = args[0].toLowerCase();
System.out.println ("Reading " + inFile);
PdfReader reader = new PdfReader(inFile);
int n = reader.getNumberOfPages();
System.out.println ("Number of pages : " + n);
int i = 0;
while ( i < n ) {
String outFile = inFile.substring(0, inFile.indexOf(".pdf"))
+ "" + String.format("%03d", i + 1) + ".pdf";
System.out.println ("Writing " + outFile);
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, new FileOutputStream(outFile));
document.open();
PdfImportedPage page = writer.getImportedPage(reader, ++i);
writer.addPage(page);
document.close();
writer.close();
}
}
catch (Exception e) {
e.printStackTrace();
}
/* example :
java SplitPDFFile d:\temp\x\tx.pdf
Reading d:\temp\x\tx.pdf
Number of pages : 3
Writing d:\temp\x\tx001.pdf
Writing d:\temp\x\tx002.pdf
Writing d:\temp\x\tx003.pdf
*/
}
}

21.60 Split a PDF file (using iText)Tag(s): IO Open Source

21.61 Concatenate PDF files (using iText)Tag(s): IO Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0646.html
This HowTo is based on the iText package. You need a recent version (ex. 2.*)
This a command line utility. You specify the pdf files to be merge into one.
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import
import
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.pdf.PRAcroForm;
com.lowagie.text.pdf.PdfCopy;
com.lowagie.text.pdf.PdfImportedPage;
com.lowagie.text.pdf.PdfReader;
com.lowagie.text.pdf.SimpleBookmark;

public class ConcatPDFFiles {


@SuppressWarnings("unchecked")
public static void main(String[] args) {
try {
if (args.length < 2) {
System.out.println
("Usage: ConcatPDFFiles file1.pdf [file2.pdf... fileN.pdf] out.pdf");
System.exit(1);
}
int pageOffset = 0;
ArrayList master = new ArrayList();
int f = 0;
String outFile = args[args.length 1];
Document document = null;
PdfCopy writer = null;
while (f < args.length 1) {
PdfReader reader = new PdfReader(args[f]);
reader.consolidateNamedDestinations();
int n = reader.getNumberOfPages();
List bookmarks = SimpleBookmark.getBookmark(reader);
if (bookmarks != null) {
if (pageOffset != 0) {
SimpleBookmark.shiftPageNumbers(bookmarks, pageOffset,
null);
}
master.addAll(bookmarks);
}
pageOffset += n;

21.61 Concatenate PDF files (using iText)Tag(s): IO Open Source

if (f == 0) {
document = new Document(reader.getPageSizeWithRotation(1));
writer = new PdfCopy(document,
new FileOutputStream(outFile));
document.open();
}
PdfImportedPage page;
for (int i = 0; i < n;) {
++i;
page = writer.getImportedPage(reader, i);
writer.addPage(page);
}
PRAcroForm form = reader.getAcroForm();
if (form != null) {
writer.copyAcroForm(reader);
}
f++;
}
if (!master.isEmpty()) {
writer.setOutlines(master);
}
document.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

ref : iText example


See also this HowTo.

21.62 Convert TIF to PDFTag(s): AWT IO IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/java0645.html
This HowTo is based on the iText package. You need a recent version (ex. 2.*)
This a command line utility. You pass one or many tif files as argument and corresponding
PDF are produced. Multipage TIF are supported. TIF are resized to fit a letterpage
dimension.
import java.io.FileOutputStream;
import
import
import
import
import
import

com.lowagie.text.Document;
com.lowagie.text.Image;
com.lowagie.text.PageSize;
com.lowagie.text.Rectangle;
com.lowagie.text.pdf.PdfContentByte;
com.lowagie.text.pdf.PdfWriter;

21.62 Convert TIF to PDFTag(s): AWT IO IO Open Source

import com.lowagie.text.pdf.RandomAccessFileOrArray;
import com.lowagie.text.pdf.codec.TiffImage;
public class TiffToPDF {
public static void main(String[] args) {
if (args.length < 1) {
System.out
.println("Usage: Tiff2Pdf file1.tif [file2.tif ... fileN.tif]");
System.exit(1);
}
String tiff;
String pdf;
for (int i = 0; i < args.length; i++) {
tiff = args[i];
pdf = tiff.substring(0, tiff.lastIndexOf('.') + 1) + "pdf";
Document document = new Document(PageSize.LETTER, 0, 0, 0, 0);
try {
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(pdf));
int pages = 0;
document.open();
PdfContentByte cb = writer.getDirectContent();
RandomAccessFileOrArray ra = null;
int comps = 0;
try {
ra = new RandomAccessFileOrArray(tiff);
comps = TiffImage.getNumberOfPages(ra);
}
catch (Throwable e) {
System.out.println("Exception in " + tiff + " "
+ e.getMessage());
continue;
}
System.out.println("Processing: " + tiff);
for (int c = 0; c < comps; ++c) {
try {
Image img = TiffImage.getTiffImage(ra, c + 1);
if (img != null) {
System.out.println("page " + (c + 1));
img.scalePercent
(7200f / img.getDpiX(), 7200f / img.getDpiY());
document.setPageSize
(new Rectangle(img.getScaledWidth(), img.getScaledHeight()));
img.setAbsolutePosition(0, 0);
cb.addImage(img);
document.newPage();
++pages;
}
}
catch (Throwable e) {
System.out.println("Exception " + tiff + " page "
+ (c + 1) + " " + e.getMessage());
}
}
ra.close();
document.close();
}
catch (Throwable e) {
e.printStackTrace();
}
System.out.println("done");
}
}

21.62 Convert TIF to PDFTag(s): AWT IO IO Open Source

21.63 Convert HTML to PDF using iTextTag(s): IO Open


Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javahtmltopdfusingitext.html
iText
Using iText HTMLWorker, you can produce PDF version of an HTML document. The
document must be simple. Many things like FORM elements or external images are not
supported.
Done with iText 5.4.1.

import java.io.FileOutputStream;
import java.io.StringReader;
import
import
import
import

com.itextpdf.text.Document;
com.itextpdf.text.PageSize;
com.itextpdf.text.html.simpleparser.HTMLWorker; // deprecated
com.itextpdf.text.pdf.PdfWriter;

public class HtmlToPDF1 {


// itextpdf5.4.1.jar http://sourceforge.net/projects/itext/files/iText/
public static void main(String ... args ) {
try {
Document document = new Document(PageSize.LETTER);
PdfWriter.getInstance(document, new FileOutputStream("c://temp//testpdf1.pdf"));
document.open();
document.addAuthor("Real Gagnon");
document.addCreator("Real's HowTo");
document.addSubject("Thanks for your support");
document.addCreationDate();
document.addTitle("Please read this");

HTMLWorker htmlWorker = new HTMLWorker(document);


String str = "<html><head></head><body>"+
"<a href='http://www.rgagnon.com/howto.html'><b>Real's HowTo</b></a>" +
"<h1>Show your support</h1>" +
"<p>It DOES cost a lot to produce this site in ISP storage and transfer fees, "
"in personal hardware and software costs to set up test environments, and above a
"the huge amounts of time it takes for one person to design and write the actual
"<p>If you feel that effort has been useful to you, perhaps you will consider giv
"<p>Donate using PayPal to real@rgagnon.com." +
"<p>Contributions via PayPal are accepted in any amount " +
"<P><br><table border='1'><tr><td>Java HowTo<tr>" +
"<td bgcolor='red'>Javascript HowTo<tr><td>Powerbuilder HowTo</table>" +
"</body></html>";
htmlWorker.parse(new StringReader(str));
document.close();
System.out.println("Done");

21.63 Convert HTML to PDF using iTextTag(s): IO Open Source

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

As you can see, the validity of the parsed HTML (using HTMLWorker) is very relax. Closing
tags are not required : <BR> is ok (<BR/> is not mandatory).
HTMLWorker is ok with older iText version but the recommended approach with new iText
(HTMLWorker is now deprecated) is to use the XMLWorker. XMLWorker is stricter since you
must send XHTML document to it.
import java.io.FileOutputStream;
import java.io.StringReader;
import
import
import
import
public

com.itextpdf.text.Document;
com.itextpdf.text.PageSize;
com.itextpdf.text.pdf.PdfWriter;
com.itextpdf.tool.xml.XMLWorkerHelper;
class HtmlToPDF2 {
// itextpdf5.4.1.jar http://sourceforge.net/projects/itext/files/iText/
// xmlworker5.4.1.jar http://sourceforge.net/projects/xmlworker/files/
public static void main(String ... args ) {
try {
Document document = new Document(PageSize.LETTER);
PdfWriter pdfWriter = PdfWriter.getInstance
(document, new FileOutputStream("c://temp//testpdf.pdf"));
document.open();
document.addAuthor("Real Gagnon");
document.addCreator("Real's HowTo");
document.addSubject("Thanks for your support");
document.addCreationDate();
document.addTitle("Please read this");
XMLWorkerHelper worker = XMLWorkerHelper.getInstance();

String str = "<html><head></head><body>"+


"<a href='http://www.rgagnon.com/howto.html'><b>Real's HowTo</b><
"<h1>Show your support</h1>" +
"<p>It DOES cost a lot to produce this site in ISP storage and
"in personal hardware and software costs to set up test environme
"the huge amounts of time it takes for one person to design and w
"<p>If you feel that effort has been useful to you, perhaps you w
"<p>Donate using PayPal to real@rgagnon.com.</p>" +
"<p>Contributions via PayPal are accepted in any amount</p>" +
"<P><br/><table border='1'><tr><td>Java HowTo</td></tr><tr>" +
"<td style='backgroundcolor:red;'>Javascript HowTo</td></tr>" +
"<tr><td>Powerbuilder HowTo</td></tr></table></p>" +
"</body></html>";
worker.parseXHtml(pdfWriter, document, new StringReader(str));
document.close();
System.out.println("Done.");
}
catch (Exception e) {
e.printStackTrace();
}
}
}

21.63 Convert HTML to PDF using iTextTag(s): IO Open Source

Note : To get the color on a table cell, you need to use a style because the bgcolor attribute
is not supported. By default, FORM elements are not rendered. Review this document to see
what is supported : http://demo.itextsupport.com/xmlworker/doc.html
See also Convert HTML to PDF using YAHP

21.64 Convert HTML to PDF using YAHP Tag(s):


IO OpenSource
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaconverthtmltopdfusingyahp.html
As seen in this HowTo, iText can be used to transform an HTML document to PDF. The
result is good with simple HTML but if you get fancy then the result is not so good.
For better result, the Open Source package YAHP (Yet another Html to Pdf converter) is a
good choice. YAHP is based on iText, FlyingSaucer and JTidy.
import
import
import
import
import
import

java.io.File;
java.io.FileOutputStream;
java.util.ArrayList;
java.util.HashMap;
java.util.List;
java.util.Map;

// http://www.allcolor.org/YaHPConverter/
import org.allcolor.yahp.converter.CYaHPConverter;
import org.allcolor.yahp.converter.IHtmlToPdfTransformer;
public class HtmlToPdf_yahp {
public static void main(String ... args ) throws Exception {
htmlToPdfFile();
}
public static void htmlToPdfFile() throws Exception {
CYaHPConverter converter = new CYaHPConverter();
File fout = new File("c:/temp/x.pdf");
FileOutputStream out = new FileOutputStream(fout);
Map properties = new HashMap();
List headerFooterList = new ArrayList();
String str = "<HTML><HEAD></HEAD><BODY><H1>Testing</H1><FORM>" +
"check : <INPUT TYPE='checkbox' checked=checked/><br/>"
"</FORM></BODY></HTML>";
properties.put(IHtmlToPdfTransformer.PDF_RENDERER_CLASS,
IHtmlToPdfTransformer.FLYINGSAUCER_PDF_RENDERER);
//properties.put(IHtmlToPdfTransformer.FOP_TTF_FONT_PATH, fontPath);
converter.convertToPdf(str,
IHtmlToPdfTransformer.A4P,
headerFooterList,

21.64 Convert HTML to PDF using YAHP Tag(s): IO OpenSource

"file:///temp/", // root for relative external CSS and IMAGE


out,
properties);
out.flush();
out.close();
}
}

In the next example, we read an existing HTML file and convert it to a PDF file.
import
import
import
import
import
import
import

java.io.File;
java.io.FileOutputStream;
java.util.ArrayList;
java.util.HashMap;
java.util.List;
java.util.Map;
java.util.Scanner;

// http://www.allcolor.org/YaHPConverter/
import org.allcolor.yahp.converter.CYaHPConverter;
import org.allcolor.yahp.converter.IHtmlToPdfTransformer;
public class HtmlToPdf_yahp_2 {
public static void main(String ... args ) throws Exception {
String root = "c:/temp/html";
String input = "file_1659686.htm"; // need to be charset utf8
htmlToPdfFile(new File(root, input),
new File(root, input + ".pdf"));
System.out.println("Done");
}
public static void htmlToPdfFile(File htmlIn, File pdfOut) throws Exception {
Scanner scanner =
new Scanner(htmlIn).useDelimiter("\\Z");
String htmlContents = scanner.next();
CYaHPConverter converter = new CYaHPConverter();
FileOutputStream out = new FileOutputStream(pdfOut);
Map properties = new HashMap();
List headerFooterList = new ArrayList();
properties.put(IHtmlToPdfTransformer.PDF_RENDERER_CLASS,
IHtmlToPdfTransformer.FLYINGSAUCER_PDF_RENDERER);
//properties.put(IHtmlToPdfTransformer.FOP_TTF_FONT_PATH, fontPath);
converter.convertToPdf(htmlContents,
IHtmlToPdfTransformer.A4P,
headerFooterList,
"file:///temp/html/",
out,
properties);
out.flush();
out.close();
}
}
NOTE : After downloading YAHP (and its dependencies), you still need to build a YAHP.JAR, it's done easily with Eclipse... but you
can get it here.

21.64 Convert HTML to PDF using YAHP Tag(s): IO OpenSource

21.65 Convert a png/jpg/gif file to PDF using iTextTag(s):


IO Open Source
Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaimagetopdfusingitext.html
iText

import java.io.FileOutputStream;
//com.lowagie...
old version
//com.itextpdf... recent version
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.Image;

public class ImageToPDF {


public static void main(String ... args) {
Document document = new Document();
String input = "c:/temp/capture.png"; // .gif and .jpg are ok too!
String output = "c:/temp/capture.pdf";
try {
FileOutputStream fos = new FileOutputStream(output);
PdfWriter writer = PdfWriter.getInstance(document, fos);
writer.open();
document.open();
document.add(Image.getInstance(input));
document.close();
writer.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}

You can get the image from an URL :


document.add(Image.getInstance
(new java.net.URL("http://www.rgagnon.com/images/javahowto.jpg")));

And you can resize it :


Image img = Image.getInstance
(new java.net.URL("http://www.rgagnon.com/images/javahowto.jpg"));
img.scalePercent(50);
document.add(img);

21.65 Convert a png/jpg/gif file to PDF using iTextTag(s): IO Open Source

21.66 Print a PDFTag(s): IO Open Source


Current version of this HowTo :
http://www.rgagnon.com/javadetails/../javadetails/javaprintapdf.html
[Windows only]
You can launch the Acrobat Reader to print a PDF to the default printer.
More infos the "unsupported" commandline switches for the Acrobat reader :
http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/intro_to_sdk/DeveloperFAQ.pdf
(page 27).
import java.io.IOException;
public class PdfUtils {
static final String WIN_COMSPEC = System.getenv("comspec");
static final String WIN_ACROBAT = "acrord32.exe";
public static void print(String pdf) throws IOException
{
String[] commands =
{WIN_COMSPEC,
"/c",
"start",
WIN_ACROBAT,
"/t",
"/h",
pdf };
Runtime.getRuntime().exec(commands);
}
public static void main(String[] args) throws IOException {
PdfUtils.print("c:/users/public/temp/test.pdf");
}
}

Unfortunately, Acrobat Reader stays opened (but minimized because of the /h switch) after
the printing operation :(
You can use a special wrapper to force the closing the Acrobat Reader after the print
operation. See http://www.biopdf.com/acrowrap/close_adobe_reader.php (acrowrap.exe).

21.67 Extract text from a PDF (with Apache Tika) Tag(s): IO


OpenSource

21.66 Print a PDFTag(s): IO Open Source

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javaextracttextfromapdf.html
You can do it with Apache Tika
import java.io.FileInputStream;
import java.io.InputStream;
import
import
import
import
import

org.apache.tika.parser.pdf.PDFParser;
org.apache.tika.metadata.Metadata;
org.apache.tika.parser.ParseContext;
org.apache.tika.sax.BodyContentHandler;
org.xml.sax.ContentHandler;

public class ParsePDFWithTika {


public static void main(String args[]) throws Exception {
InputStream is = null;
try {
is = new FileInputStream("C:/Temp/realhowtovbs20121221.pdf");
ContentHandler contenthandler = new BodyContentHandler();
Metadata metadata = new Metadata();
PDFParser pdfparser = new PDFParser();
pdfparser.parse(is, contenthandler, metadata, new ParseContext());
System.out.println(contenthandler.toString());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (is != null) is.close();
}
}
}

See also Extract text from HTML, Get Mime Type from a file.

21.68 Detect and remove blank page in pdf (iText)Tag(s):


PDF

Current version of this HowTo :


http://www.rgagnon.com/javadetails/../javadetails/javadetectandremoveblankpageinpdf.htm
It's not easy to detect if a pdf page is blank or not.
In this HowTo, we check if we found some resource reference, if found then the page is not
blank. The xext step is to get the content as a byte array. We compare the size of content
with a threshold value. This value depends on how the PDF is produced. For example, a
Word document converted in PDF (with CutePDF) shows that a blank page has a size of
156 bytes. So my threshold value in this context is 160. Obviously, this method can produce
false positive match and you need to test and retest before setting this value!
21.68 Detect and remove blank page in pdf (iText)Tag(s): PDF

A nice extra step would be that to extract the content as text, do a trim() and check if the result is empty or not ... this is left as an
exercise to the reader for now ;).

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import
import
import
import
import
import
import
import
import

com.itextpdf.text.Document;
com.itextpdf.text.DocumentException;
com.itextpdf.text.io.RandomAccessSourceFactory;
com.itextpdf.text.pdf.PdfCopy;
com.itextpdf.text.pdf.PdfDictionary;
com.itextpdf.text.pdf.PdfImportedPage;
com.itextpdf.text.pdf.PdfName;
com.itextpdf.text.pdf.PdfReader;
com.itextpdf.text.pdf.RandomAccessFileOrArray;

public class RemoveBlankPageFromPDF {


// value where we can consider that this is a blank image
// can be much higher or lower depending of what is considered as a blank page
public static final int BLANK_THRESHOLD = 160;
public static void removeBlankPdfPages(String source, String destination)
throws IOException, DocumentException
{
PdfReader r = null;
RandomAccessSourceFactory rasf = null;
RandomAccessFileOrArray raf = null;
Document document = null;
PdfCopy writer = null;
try {
r = new PdfReader(source);
// deprecated
//
RandomAccessFileOrArray raf
//
= new RandomAccessFileOrArray(pdfSourceFile);
// itext 5.4.1
rasf = new RandomAccessSourceFactory();
raf = new RandomAccessFileOrArray(rasf.createBestSource(source));
document = new Document(r.getPageSizeWithRotation(1));
writer = new PdfCopy(document, new FileOutputStream(destination));
document.open();
PdfImportedPage page = null;

for (int i=1; i<=r.getNumberOfPages(); i++) {


// first check, examine the resource dictionary for /Font or
// /XObject keys. If either are present > not blank.
PdfDictionary pageDict = r.getPageN(i);
PdfDictionary resDict = (PdfDictionary) pageDict.get( PdfName.RESOURCES )
boolean noFontsOrImages = true;
if (resDict != null) {
noFontsOrImages = resDict.get( PdfName.FONT ) == null &&
resDict.get( PdfName.XOBJECT ) == null;
}
System.out.println(i + " noFontsOrImages " + noFontsOrImages);

if (!noFontsOrImages) {
byte bContent [] = r.getPageContent(i,raf);
ByteArrayOutputStream bs = new ByteArrayOutputStream();
bs.write(bContent);
System.out.println
(i + bs.size() + " > BLANK_THRESHOLD " + (bs.size() > BLANK_THRESH

21.68 Detect and remove blank page in pdf (iText)Tag(s): PDF

if (bs.size() > BLANK_THRESHOLD) {


page = writer.getImportedPage(r, i);
writer.addPage(page);
}
}
}
}
finally {
if (document != null) document.close();
if (writer != null) writer.close();
if (raf != null) raf.close();
if (r != null) r.close();
}
}
public static void main (String ... args) throws Exception {
removeBlankPdfPages
("C://temp//documentwithblank.pdf", "C://temp//documentwithnoblank.pdf");
}
}

Test documents : DOCX PDF


See also Detect if a TIF is blank .

Written and compiled Ral Gagnon 2007 real@rgagnon.com


http://www.rgagnon.com

21.68 Detect and remove blank page in pdf (iText)Tag(s): PDF

You might also like